Construire des objets de classe internes par réflexion
Écrivez d'abord une classe contenant des classes internes sous le package javalang :
package javalang; public class Outer { public static class Inner1{} }
Notez que cette classe est publique statique, nous allons ralentir vers le bas plus tard Supprimez ces modificateurs lentement.
Pour créer un objet Inner1 par réflexion, vous devez d'abord obtenir l'objet Class d'Inner1. Nous écrivons la méthode principale dans Outer :
public class Outer { public static class Inner1{} public static void main(String[] args) { System.out.println(Inner1.class); } }
Résultat de sortie :
class javalang.Outer$Inner1
Ensuite, nous essayons de voir si le nom de la classe est correct :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1")); }
Exécutez-le, c'est vrai. Ensuite, utilisez-le simplement pour créer des objets. La création d'objets repose sur des constructeurs. Cette classe a-t-elle une méthode constructeur ? On peut écrire :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors().length); }
Exécutez-le et sortez 1. Il semble que ce soit le cas. Jetez ensuite un œil à ce à quoi ressemble cette méthode de construction :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1").getConstructors()[0]); }
Résultat de sortie : public javalang.Outer$Inner1(). Il s'agit de la méthode de construction par défaut. On peut donc écrire comme ceci :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getConstructors()[0].newInstance(); }
Résultat de sortie : javalang.Outer$Inner1@ca0b6. Cela indique que l'exécution a réussi.
Ensuite, nous supprimons le mot-clé public d'Inner et l'exécutons à nouveau. Le résultat est une erreur :
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
Cela signifie que la méthode de construction n'a pas été trouvée. Vraiment pas ? Nous modifions la méthode principale :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getConstructors().length); }
Résultat de sortie : 0. Il n'y a vraiment pas de constructeur ? En fait non, c'est juste que la méthode de construction n'est pas publique. À ce stade, nous devons utiliser getDeclaredConstructors() pour obtenir :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors().length); }
Résultat de sortie : 1. On retrouve ainsi la méthode de construction. Ensuite, nous continuons à appeler ce constructeur :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0].newInstance()); }
Résultat de sortie : javalang.Outer$Inner1@ca0b6. Nous pouvons désormais utiliser la réflexion pour construire des objets de classes internes non publiques.
Ensuite, supprimons le mot-clé statique. À ce moment-là, une erreur a été signalée :
Exception dans le thread "main" java.lang.IllegalArgumentException : mauvais nombre d'arguments
Qu'est-ce que cela signifie ? Nous n'avons pas transmis de paramètres lors de notre appel et le contenu de l'erreur était que le nombre de paramètres était incorrect. Alors, quels sont les paramètres de ce constructeur ? Modifions le code et jetons un œil :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0]); }
Résultat de sortie : javalang.Outer$Inner1(javalang.Outer)
Il s'avère que le constructeur nécessite un paramètre de type Outer. C'est facile à faire :
public static void main(String[] args) throws Exception { System.out.println(Class.forName("javalang.Outer$Inner1") .getDeclaredConstructors()[0].newInstance(new Outer())); }
Résultat de sortie :
javalang.Outer$Inner1@ca0b6
OK, c'est tout. Il semble que les classes internes non statiques n'aient pas de méthode de construction par défaut et qu'une instance d'une classe externe doive être passée en paramètre lors de la construction.
Java : Comment accéder à un objet
Un casse-tête pour les débutants Java est de savoir comment décider s'il faut définir un objet comme variable de méthode ou comme variable membre ?
Les débutants ne s'en soucieront pas au début. Mais lorsque les programmes écrits deviennent de plus en plus grands et qu'il y a de plus en plus de classes, ce genre de détresse surgit aussi.
Mais ce que je veux écrire ici, c'est : comment agencer un objet comme on l'entend pour pouvoir y accéder à tout moment. Une fois que vous maîtrisez cela, vous pouvez décider librement où placer un objet.
Voici un exemple simple :
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { // 这里如何获得 main() 方法中的 date 变量? } }
Comme décrit dans la méthode anHourLater(), vous souhaitez obtenir l'heure une heure après la date. Ce qu'il faut faire? Il existe plusieurs méthodes ci-dessous.
(1) Passage de paramètres
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); anHourLater(date); } // 获得 date 对象一小时后的时间 private static void anHourLater(Date d) { Date anHourLater = new Date(d.getTime() + 3600000); } }
(2) Défini en tant que membre. Les membres sont accessibles par toutes les méthodes et l'initialisation des membres peut être placée là où ils sont définis ou dans n'importe quelle méthode.
public class AccessingObject { private static Date date; public static void main(String[] args) { date = new Date(); anHourLater(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { Date anHourLater = new Date(date.getTime() + 3600000); } }
(3) Mettez-le dans une autre classe. Dans l'exemple suivant, DateHolder.date est accessible à toutes les classes du même package, pas seulement à la classe AccessingObject.
public class AccessingObject { public static void main(String[] args) { DateHolder.date = new Date(); } // 获得 date 对象一小时后的时间 private static void anHourLater() { Date anHourLater = new Date(DateHolder.date.getTime() + 3600000); } } class DateHolder { public static Date date; }
En comparant ces trois exemples, les deux premiers ne peuvent être utilisés qu'à l'intérieur de la classe et sont relativement sûrs. Si vous ne souhaitez pas que cet objet soit modifié directement par d'autres classes, n'utilisez pas la troisième méthode.
La différence entre la première méthode et la deuxième méthode est la suivante : si un objet est uniquement utilisé dans une méthode, alors lorsque la méthode est exécutée, l'objet peut être facilement recyclé (attention, il n'est pas recyclé immédiatement) . S'il est défini comme membre d'une classe, l'objet ne sera recyclé qu'après le recyclage de la classe dans laquelle il se trouve. De toute évidence, la première méthode est la plus économe en ressources, et nous devrions essayer d’utiliser la première méthode.
En repensant à ces trois exemples, si la méthode main() veut obtenir l'heure une heure plus tard obtenue dans la méthode anHourLater(), elle a également plusieurs manières correspondantes. Il n'est pas nécessaire de modifier les deux derniers exemples, l'objet date est accessible directement ; dans le premier exemple, il existe deux méthodes de modification :
(1) comme valeur de retour
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); Date anHourLater = anHourLater(date); } // 获得 date 对象一小时后的时间 private static Date anHourLater(Date d) { return new Date(d.getTime() + 3600000); } }
(2) Modifier directement le contenu des paramètres
public class AccessingObject { public static void main(String[] args) { Date date = new Date(); anHourLater(date); } // 获得 date 对象一小时后的时间 private static void anHourLater(Date d) { d.setTime(d.getTime() + 3600000); } }
La deuxième méthode doit être utilisée avec prudence, car c'est mal de toucher aux choses des autres avec désinvolture. Vous ne savez pas si l'appelant de la méthode l'aime ou non.
Pour plus d'articles expliquant comment construire des objets de classe internes et accéder aux objets en Java, veuillez faire attention au site Web PHP chinois !