Classe sur le terrain
La classe de terrain définit certaines méthodes qui peuvent être utilisées pour interroger le type de champ et pour définir ou lire la valeur d'un champ. La combinaison de ces méthodes avec la méthode des membres héréditaires nous permet de trouver toutes les informations sur la déclaration de champ et de pouvoir manipuler les champs d'un objet ou d'une classe spécifique.
La méthode GetGenericType renvoie une instance de type représentant le type de déclaration du champ. Pour les types triviaux comme String ou INT, la méthode renvoie l'objet de classe associé, tel que String.Class et int.classo pour les types de paramétrisés comme List <Stri ng>, la méthode renvoie une instance de ParametezedRype, par exemple, pour un type comme T, la méthode renvoie une instance TypeVariable.
La méthode Legacy GetType renverra un objet de classe de type de champ. Pour les types triviaux, la méthode se comporte de la même manière que la méthode GetGenericType. Si le type déclaré du champ est un type paramétré, la méthode GetType renverra l'objet de classe correspondant pour l'effacement du type paramétré, c'est-à-dire l'objet de classe du type d'origine. Par exemple, pour un objet déclaré comme liste <stri ng>, GetType renverra Li St. Classe. Si le type déclaré d'un champ est une variable de type, la méthode GetType renverra l'objet de classe correspondant pour effacer la variable de type. Par exemple, supposons qu'il y ait une classe Foo <Ding>, et pour les champs déclarés de type T, GetDing YPE renverra l'objet.
objet de classe. Si FOO est déclaré FOO <étend numéro>, alors YPE sous Get renvoiera numéro.classe.
Nous pouvons utiliser la méthode isenumconstante pour demander si un champ est une constante d'énumération, ou nous pouvons utiliser les méthodes GET et définir pour obtenir et définir la valeur du champ. Ces méthodes qui acceptent les citations d'objets et renvoient la valeur de l'objet ECT ont une forme commune, ainsi que des formulaires plus spécialisés qui peuvent gérer directement les types de base. Toutes ces méthodes acceptent une citation pour spécifier l'objet à utiliser. Pour les champs statiques, cette citation d'objet sera ignorée, vous pouvez donc également la définir
Réglé sur null. La méthode suivante imprimera la valeur du champ court d'un objet:
public static void PrintShortfield (objet o, nom de chaîne) lève NosuchFieldException, illégalaccessException {field field = o.getClass (). getField (name); valeur courte = (court) champ.get (o); System.out.println (valeur);La valeur de retour de la méthode GET peut être tout objet référencé par ce champ. Si le champ est un type primitif, la méthode renverra le type approprié d'objet de classe wrapper. Pour notre champ "de type Hort, la méthode GET renvoie un objet de type court contenant la valeur du champ, et lorsqu'il est affecté à la valeur de variable locale, la valeur de l'objet sera automatiquement déballée.
L'utilisation de la méthode SET est similaire. La méthode de définition du champ court sur la valeur fournie peut ressembler à ceci:
public static voi SetShortfield (objet o, nom de chaîne, court nv) lève le champ NosuchFieldException, illégalaccessException Field = 0.getClass (). GetField (nom); champ .set (o .nv);
Bien que SET accepte les paramètres du type d'objet, nous pouvons passer directement une valeur courte et l'envelopper dans un objet court avec la conversion d'emballage.
Dans la méthode ci-dessus, si le domaine de l'objet spécifié est inaccessible et que ce contrôle d'accès est appliqué, une exception illégalaccessException sera lancée; Si l'objet passé est différent du type du domaine, une exception illégalargumentException sera lancée; Si le domaine est non statique et que la référence d'objet passée est nul, une exception NullPointerException sera lancée; L'accès à un domaine statique peut exiger que la classe soit initialisée, de sorte que la méthode lancera également une exception ExceptionInitializerError.
La classe de terrain propose également des méthodes spécifiques pour obtenir et définir des types de base. Par exemple, nous pouvons appeler getPrimitive7ype et définir primitive7ype sur l'objet Field, où primitive7ype est le nom de type de base (capitalisé). La méthode GET peut être utilisée dans l'énoncé suivant:
valeur courte = champ.getShhort (o);
La méthode SET peut être utilisée dans l'énoncé suivant:
field.setShort (o, nv);
L'utilisation d'objets de type wrapper peut être évitée dans les instructions déclarées de deux manières ci-dessus.
La classe de terrain implémente l'interface AnnotateDelement, afin que nous puissions également interroger et l'appliquer au domaine comme la section 16.2.
Notes sur.
Avec la méthode décrite ci-dessus, nous pouvons utiliser l'objet Field comme moyen de manipuler n'importe quelle valeur, mais nous devons essayer de l'éviter. Étant donné que le langage Java capture des erreurs de programmation que possible le plus possible pendant la période de compilation d'un programme, moins de méthodes indirectes telles que "IELD objets" sont utilisées lorsque nous écrivons du code, plus les erreurs peuvent être empêchées avant de les compiler en code. De plus, nous pouvons voir que dans le code précédent, afin de savoir ce qui va se passer exactement, nous avons évidemment dépensé beaucoup plus d'énergie pour lire du code que lors de l'utilisation des noms de domaine directement dans une syntaxe ordinaire.
Champs finaux
Normalement, la définition d'un champ déclaré final entraînera un lancement d'une exception d'accès illégal
Exception, c'est ce à quoi nous pouvons nous attendre, car la valeur du champ final ne changera jamais. Mais il y a des cas particuliers - par exemple, dans la désérialisation personnalisée (voir la section 20.8.4), il est logique de modifier la valeur du champ final, que nous ne pouvons réaliser que par la réflexion sur le champ d'instance, et seulement si SetAcessable (true) a été appelé sur l'objet de champ. Notez qu'il ne suffit pas d'appeler avec succès SetAccessible (vrai) et qu'il doit être appelé en effet.
Cette capacité est fournie pour des contextes hautement spécialisés et n'est pas à des fins générales, et nous l'introduisons pour maintenir l'intégrité du contenu uniquement. Si vous êtes hors d'un contexte spécifique, comme la désérialisation personnalisée, la modification de la valeur du champ final peut entraîner des conséquences inattendues ou même catastrophiques. En dehors de ces contextes, rien ne garantit que les modifications du champ final sont visibles. Même dans de tels contextes, il est nécessaire de s'assurer que le mécanisme de sécurité n'entrave pas l'exécution du code lors du codage à l'aide de cette technologie. La modification du champ final avec une valeur de variable constante (voir section 2.2.3) rendra ce changement invisible, sauf si une telle modification est obtenue en utilisant la réflexion.
Classe de méthode
La classe de méthode et ses méthodes héréditaires de la classe membre nous permettent d'obtenir les informations complètes sur la déclaration de méthode:
"Type public getGenericRetTurnTypeo: Cette méthode renvoie un objet de type du type de retour de la méthode cible. Si la méthode cible est déclarée vide, la méthode renvoie void.classo
"Public Type [] getGenericParameterTypes (): Cette méthode renvoie un tableau d'objets de type de tous les types de paramètres de la méthode cible, qui sera stocké dans le tableau dans l'ordre de déclaration des paramètres. Si la méthode cible n'a pas de paramètres, la méthode renvoie un tableau vide.
.PUBL IC Type [] GetGeneri Cacheti ONTYPES Q: Cette méthode renvoie un tableau d'objets de type de tous les types d'exceptions répertoriés dans la clause des lancers, qui sera stocké dans le tableau dans l'ordre de la déclaration d'exception.
Si la méthode cible ne déclare aucune exception, la méthode renvoie un tableau vide.
Java fournit également des méthodes GetReturnType, GetParameterTypes et GetExceptionTypes pour renvoyer CL comme "objet au lieu de l'objet de type. Tout comme lors de l'utilisation de Field.getType, les variables de type paramétré et de type sont représentées par l'objet de classe correspondant à leur effacement.
La classe de méthode implémente AnnotateDelement, et nous pouvons interroger les annotations appliquées à la méthode telle que discutée dans la section 16.2. De plus, la classe de méthode fournit également des GetParameterannotations pour fournir un accès aux annotations appliquées aux paramètres de la méthode. La méthode GetParameterannotations peut renvoyer un tableau d'annotation, où chaque élément du tableau le plus externe correspond aux paramètres de la méthode; Si un paramètre n'a pas d'annotations, la méthode renvoie un tableau d'annotation de longueur 0 pour ce paramètre. Si la méthode représentée par l'objet de méthode est elle-même un élément d'annotation, la méthode GetDefaultValue renvoie un objet objet représentant la valeur par défaut de l'élément; Si l'objet de méthode lui-même n'est pas un élément d'annotation ou qu'il n'a pas de valeur par défaut, la méthode renvoie Null.Method Class implémente également générique, de sorte que la méthode GetTypeParameters est définie, qui renverra un tableau d'objets typariables. Si l'objet de méthode donnée ne représente pas une méthode générique, la méthode renvoie un tableau vide.
Nous pouvons utiliser la méthode Isvarargs pour vérifier si un objet de méthode est une méthode d'index variable, et la méthode I Sbridge peut être utilisée pour vérifier s'il s'agit d'une méthode de pont
La façon la plus intéressante d'utiliser un objet de méthode est de s'appeler de manière réfléchie:
.Public Object Invoke (Object OnThis, objet… args) lève illégalaccessException, illégalargumentException, argetException sous Nvocation: cette méthode appelle la méthode définie par l'objet de la méthode sur cet objet, et utilise la valeur des args pour définir les paramètres de la méthode appelée. Pour les méthodes non statiques, le type réel d'Outhis détermine quelle implémentation de la méthode à appeler, tandis que pour les méthodes statiques, celle sera ignorée et est généralement définie sur NULL. Le nombre de valeurs des args doit être le même que le nombre réel de paramètres de la méthode appelée, et les types de ces valeurs doivent être attribués aux paramètres de la méthode appelée; Sinon, nous obtiendrons l'exception LlegalargumentException. Notez que le dernier paramètre de la méthode de citation variable est un tableau, nous devons donc remplir le tableau avec les citations "mutables" que nous voulons réellement passer. Si nous voulons appeler une méthode dont nous n'avons pas accès, la méthode lancera une exception illégalaccessException. Si la méthode appelée n'est pas la méthode de l'objet ON, la méthode lancera un LlegalargumentExcepti à l'exception. Si ONTHIS est nul et non statique, la méthode lancera une exception NO 1POINTERException. Si cet objet de méthode représente une méthode statique et que la classe qui déclare que la méthode statique est toujours à l'état à initialiser, la méthode lancera une exception de nitializerror d'exception de travail. Si la méthode appelée a une puissance extraterrestre, l'exception invocationTargetException sera lancée.
Lorsque nous utilisons la méthode Invoke, nous pouvons passer directement le type de base, ou nous pouvons utiliser une classe de wrapper appropriée. Le type représenté par la classe de wrapper doit être attribué au type de paramètre déclaré par la méthode. Nous pouvons utiliser des citations longues, flottantes ou doubles pour envelopper les citations de type double, mais nous ne pouvons pas utiliser le double pour envelopper des citations longues ou de type flotteur, car le double ne peut pas être affecté à long ou à l'avoine. La méthode de traitement de l'objet renvoyé par la méthode invoquée est la même que Field.get, qui renvoie le type de base de la classe de wrapper qui correspond à eux. Si la méthode est déclarée vide, la méthode invoquée renverra nul,
En termes simples, lorsque nous utilisons des méthodes Invoke to Call, nous ne pouvons utiliser que des paramètres juridiques en langue java.
Priorités avec le même type et valeur. Par exemple, l'appel suivant
return str.indexof (".", 8);Il peut être écrit sous la forme suivante en utilisant la réflexion:
Fas jetable; essayez {méthode indexm = string.class. getMethod ("index0f", string.class, int.class); retour (entier) indexm.invoke (str, ",", 8); } catch (NosuchMethodexception e) {échec = e; } catch (invocationTargetException e) {fas = e .getCause (); } catch (illégalaccessException e) {échec = e; } lancer fas;Bien que les vérifications de sécurité du compilateur pour les appels directs ne puissent être effectuées que lors de l'utilisation d'Invoke à l'exécution lors de l'utilisation de la réflexion, le code basé sur la réflexion a des vérifications de sécurité sémantiquement équivalentes au code appelé direct. Les vérifications d'accès peuvent être effectuées d'une manière légèrement différente - le responsable de la sécurité peut refuser l'accès à une méthode de notre package, même si nous pouvons l'appeler directement.
Lorsque nous pouvons utiliser cette forme d'appel, nous avons de bonnes raisons de l'éviter. Mais il aurait du sens si nous utilisons la méthode invoquée ou obtenue / définit lors de l'écriture d'un débogueur ou d'une autre application générique qui doit interpréter la saisie des utilisateurs comme un fonctionnement sur les objets. L'objet de méthode peut être utilisé dans une certaine mesure comme un pointeur de méthode similaire à celui dans d'autres langues, mais nous avons de meilleurs outils, en particulier les interfaces, les classes abstraites et les classes imbriquées, qui peuvent être utilisées pour gérer les problèmes qui sont généralement résolus avec des pointeurs de méthode dans d'autres langues.