Pourquoi les types suivants sont-ils réifiables et non-réifiables en java?
en informatique, la réification a fini par signifier une représentation explicite d'un type-c'est-à-dire, des informations de type run-time.
tutoriels oracle dit
un type reifiable est un type dont les informations sur le type sont entièrement disponibles au moment de l'exécution. Cela inclut les primitives, les types non génériques, les types bruts, et invocations de caractères génériques non liés.
les types Non réifiables sont les types pour lesquels l'information été retiré à temps de compilation par type erasure-invocations de types génériques qui sont Non défini comme caractères génériques non limités.
Un type est reifiable si c'est l'un des éléments suivants:
- Un type primitif (comme
int
) //compris- une classe ou un type d'interface non paramétré (tel que
Number
,) // pourquoi- un type paramétré dans lequel tous les arguments de type sont caractères génériques non limités (tels que
List<?>
,ArrayList<?>
, ouMap<?, ?>
) // pourquoi- un type brut (tel que
List
,ArrayList
, ouMap
) // pourquoi- un tableau dont le type de composant est reifiable (tel que
int[]
,Number[]
,List<?>[]
,List[]
, ouint[][]
) // pourquoi
Un type n'est pas reifiable si c'est l'un des éléments suivants:
- une variable de type (telle que
T
) // pourquoi- un type paramétré avec des paramètres réels (tels que
List<Number>
,ArrayList<String>
, ouMap<String, Integer>
) // pourquoi- Un type paramétré avec une limite (par exemple
List<? extends Number>
ouComparable<? super String>
) // pourquoi
pourquoi 2,3,4,5 est-il réifiable et 6,7,8 non réifiable?
7 réponses
Sun / Oracle dit la raison est le combo de besoin (la vérification de type de compilation est suffisante), la taille du code (éviter le bloat de code de type STL) et la performance (éviter la vérification de type à l'exécution qui a déjà été fait à la compilation):
L'effacement de Type garantit qu'aucune nouvelle classe n'est créée pour paramétrer types; par conséquent, les génériques n'entraînent pas de frais généraux de fonctionnement.
en bref, 1-6 sont réifiables parce qu'ils restent simplement les mêmes types que spécifié dans le code de façon à ce qu'il n'y ait pas d'information de type perdue/effacée, mais 7-9 perdra l'information de type pendant la compilation (le truc entre le <>) donc ne peut pas être accédé à l'exécution.
vous pourriez demander à google la même question:
reifiable type
quand vous utilisez generics, la plupart du temps, compiler-time type l'information est perdue. À l'exécution, souvent tout le programme sait à propos d'un référence est une référence à une sorte d'Objet. Si tous les type d'information est également connu au moment de l'exécution, le type est appelé reifiable. Peut-être un jour les génériques seront-ils redessinés pour que tous les types sont reifiable.
un type reifiable est un type dont les informations sur le type sont entièrement disponibles au moment de l'exécution. Cela inclut les primitives, les types non génériques, les types bruts, et invocations de caractères génériques non liés.
les types Non réifiables sont des types pour lesquels l'information a été supprimée à temps de compilation par type erasure-invocations de types génériques qui sont Non défini comme caractères génériques non limités. Un type non réifiable n'a pas toutes ses informations disponibles à l'exécution. Des exemples de non reifiable les types sont List < String> et List
; la JVM ne peut pas dire la différence entre ces types à l'exécution. Comme indiqué dans les Restrictions Génériques, Il ya certaines situations où les types non réifiables ne peut pas être utilisé: dans un instanceof expression, par exemple, ou comme un élément dans un tableau.
Comprendre le sens de ces deux termes.
Reifiable signifie dont le type est entièrement disponible au moment de l'exécution signifie que le compilateur java n'a pas besoin de processus d'effacement de type.
Non-Reifiable signifie que le compilateur java a besoin d'un processus d'effacement de type parce que le type n'est pas entièrement disponible.
un type est réifiable s'il est l'un des suivants:
1. Un type primitif (comme int) :
Ici pense que lorsque vous écrivez ou utiliser un int comme une référence, pensez-vous que le compilateur a besoin d'un processus pour l'identification du type d'int? non, car int est int.... idem pour tout type primitif
2. Une classe ou un type d'interface non paramétré (tel que Nombre, chaîne ou exécutable)
même réponse que j'ai dit dans la réponse précédente que le compilateur n'a pas besoin d'effacement de type pour le nombre, la chaîne, ou Praticable.
3. Un type paramétré dans lequel tous les arguments de type sont des caractères génériques non limités (comme List> , ArrayList> , ou carte, ?>)
tous les caractères génériques non limités sont acceptés comme type reifiable parce qu'il est déjà mentionné dans la définition de type reifiable, maintenant c'est au développeur D'API de décider pourquoi ils le considèrent comme un type reifiable.
4. Une crue de type (tels que Liste de, liste de tableaux, ou de la Carte) ::
même réponse que première question
5. Un tableau dont le type de composant est reifiable(comme int [], [], List> [], [], Int[][]) ::
même réponse que la première question
un type n'est pas réifiable s'il est l'un des suivants:
6. Une variable type (telle que T):
parce que java ne peut pas identifier le type de T, le compilateur a besoin d'une effacement de type pour identifier le type.
7. Un paramétrable type de paramètres (tels que la Liste
ici tout type est un type générique, au compilateur d'exécution voir Liste sous Liste ... ainsi, selon la définition de Non-refiable, toutes ces collections sont considérées comme non reifiable.
8. Un type paramétré avec une limite (telle que List étend le nombre> ou Comparable super String>).
même réponse que la précédente
Java implémentée à l'origine de la réflexion dans la version 1.1.
les classes génériques ont été introduites dans la version 5.0.
lors de l'introduction des génériques, il a été décidé que, pour des raisons de compatibilité ascendante, les informations de type générique seront effacées à l'exécution. Ce code autorisé qui a été écrit pré génériques pour fonctionner avec le code basé génériques sans modification.
Par exemple List[Integer32]
serait traduite par le compilateur Integer32[]
.
Toutes les vérifications de type serait fait au moment de la compilation, et si quelque chose manquait, cela générerait une erreur d'exécution.
ce détail de mise en œuvre signifie que les génériques n'ont pas été validés (il n'y a pas de mise en œuvre spécifique de ceux-ci dans la VM) et donc chaque fois que l'on tenterait de refléter le type générique, les informations retournées seraient celles du type sous-jacent. Une autre raison pour laquelle cela serait avantageux est qu'aucune implémentation pour les types reified ne devrait être émise par le VM chaque fois qu'un type a été utilisé (dans c# par exemple, chaque fois que vous utilisez un type générique, son implémentation réelle est générée par la VM à l'exécution, ainsi que les métadonnées de réflexion, ayant ainsi un impact de performance chaque fois qu'un nouveau type devait être généré).
juste une supposition instruite, mais je soupçonne que la clé pour comprendre ceci est de reconnaître que bien que Java soit un langage fortement tapé et vérifie les références de type dans le cadre du processus de compilation, dans de nombreux cas, l'information de type n'est pas réellement nécessaire pour exécuter la logique. Dans ce cas, le bytecode généré peut savoir qu'il fonctionne avec une instance D'un objet, mais ne pas connaître le type. Cela serait particulièrement logique étant donné que les langues qui n'utilisent pas de Dactylographie forte peut être généré comme java bytecode. Ainsi, si le type d'objet a été supprimé, l'instance ne sera pas réifiable.
Je ne suis pas tout à fait sûr de comprendre votre question, mais vous pourriez faire référence à des types d'objets plutôt qu'à des types primitifs. Cette question Est d'autant plus importante que les types primitifs tels que int ou double ne peuvent pas être utilisés comme types génériques -- d'où leurs classes d'enrubannage telles que Integer.
// This won't work
ArrayList<int> list = new ArrayList<int>();
// But this will
ArrayList<Integer> list = new ArrayList<Integer>();
pour résumer je dirais tous les objets -- et objets-sont reifiable. (Et donc utilisable comme instanciation de types génériques)