Considérez le code suivant
class A{} class B{ void main(){ A a1=new A(); class A{} A a2=new A(); System.out.println(a1); // A@___ System.out.println(a2); // B$1A@____ } }
La classe A et la classe B ne sont à l'intérieur d'aucun package, Comment puis-je créer l'objet de la classe externe A à l'intérieur de main () après la méthode local inner la classe est créée. En d'autres termes, comment puis-je créer l'objet "a2", un objet de classe externe A?
J'ai vérifié cela en mettant ces classes dans un package, et j'ai pu créer l'objet de classe externe A en utilisant le nom complet. Mais, impossible de trouver un moyen de faire la même chose quand ils ne sont dans aucun paquet.
3 Réponses :
Vous pouvez utiliser Class.forName ()
pour charger la classe que vous souhaitez instancier:
System.out.println(a1.getClass()); // class A System.out.println(a2.getClass()); // class B$1A System.out.println(a3.getClass()); // class A
Cela fonctionne, comme la classe locale A
dans B.main ()
a un nom de domaine complet différent de celui déclaré au même niveau que B
:
class A {} class B { public static void main(String[] args) throws Exception { A a1 = new A(); class A {} A a2 = new A(); Class<?> clazz = Class.forName("A"); Object a3 = clazz.getDeclaredConstructor().newInstance(); System.out.println(a1); // A@___ System.out.println(a2); // B$1A@____ System.out.println(a3); // A@___ } }
J'ai dû utiliser Object
comme type de a3
car il n'y a aucun moyen de référencer le A
extérieur à l'intérieur de main ()
une fois que la classe locale A
a été déclarée.
Si vous utilisez le même nom de classe interne que la classe externe, vous devez utiliser nom de classe complet pour faire référence à une classe externe.
C'est comme si le même concept s'applique à la méthode ou aux variables où la déclaration locale obtient une priorité plus élevée.
En règle générale, l'utilisation des mêmes noms de classe n'est pas recommandée et est plus déroutante
Lien de référence à lire à ce sujet: https: // docs. oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4.2
Une excellente réponse SO sur quelque chose de similaire peut être trouvée ici. Thread SO de visibilité de classe interne
En l'absence de package pour les deux classes A, vous n'avez aucun moyen de les distinguer.
Comme le type A est référencé, le compilateur se référera à la déclaration de classe A
la plus locale / close:
A a1=new A(); Supplier<A> Asupplier = A::new; class A{} System.out.println(a1); // A@___ System.out.println(Asupplier.get()); // A@_____
Notez que le package par défaut n'est pas recommandé mais son utilisation avec le même nom de classe est vraiment une chose à ne pas faire.
Avec un Supplier
déclaré avant la classe locale A
, vous pouvez créer le Un
objet externe après la déclaration de classe locale puisque Supplier
crée l'objet uniquement lorsque get ()
est appelé:
A a1=new A(); // refer the outer (the single that is visible in this scope) class A{} A a2=new A(); // refer the inner : the closest in this scope
Cela signifie-t-il que la méthode classe interne locale ayant le même nom que la classe externe masque la classe externe lorsqu'elle est dans le package par défaut?
Je ne sais pas si "cacher" est le terme correct mais sans nom canonique (package + nom de classe) comment voulez-vous distinguer A
de A
lorsque vous les référez ?
Si vous souhaitez créer un objet de
A
dansB
, supprimez laclasse A {}
de votre B. Pourquoi avez-vous besoin de cela?il n'y a pas besoin, mais j'étais curieux de savoir comment un objet de 'A' serait créé si la classe A {} était également dans la classe B.
Je vois ce que vous voulez dire, vous devez utiliser un nom complet pour la classe externe. Voir une réponse ci-dessous