web-dev-qa-db-fra.com

Est-il possible de rendre des classes internes anonymes dans Java statique?

En Java, les classes imbriquées peuvent être static ou non. S'ils sont static, ils ne contiennent pas de référence au pointeur de l'instance contenante (ils ne sont également plus appelés classes internes, ils sont appelés classes imbriquées).

Oublier de créer une classe imbriquée static lorsqu'elle n'a pas besoin de cette référence peut entraîner des problèmes avec la récupération de place ou l'analyse d'échappement.

Est-il également possible de créer une classe interne anonyme static? Ou le compilateur comprend-il cela automatiquement (ce qu'il pourrait, car il ne peut pas y avoir de sous-classes)?

Par exemple, si je fais un comparateur anonyme, je n'ai presque jamais besoin de la référence à l'extérieur:

  Collections.sort(list, new Comparator<String>(){
       int compare(String a, String b){
          return a.toUpperCase().compareTo(b.toUpperCase());
       }
  }
118
Thilo

Non, vous ne pouvez pas, et non, le compilateur ne peut pas le comprendre. C'est pourquoi FindBugs suggère toujours de changer les classes internes anonymes en classes imbriquées nommées static si elles n'utilisent pas leur référence implicite this.

Edit: Tom Hawtin - tackline dit que si la classe anonyme est créée dans un contexte statique (par exemple dans la méthode main), le la classe anonyme est en fait static. Mais le JLS n'est pas d'accord :

Une classe anonyme n'est jamais abstract (§8.1.1.1). Une classe anonyme est toujours une classe interne (§8.1.3); ce n'est jamais static (§8.1.1, §8.5.1). Une classe anonyme est toujours implicitement final (§8.1.1.2).

Java Glossary de Roedy Green dit que le fait que les classes anonymes sont autorisées dans un contexte statique dépend de l'implémentation:

Si vous voulez dérouter ceux qui gèrent votre code, les wags ont découvert javac.exe autorisera les classes anonymes dans le code init static et les méthodes static, même si la spécification de langue indique que les classes anonymes ne sont jamais static. Ces classes anonymes, bien sûr, n'ont pas accès aux champs d'instance de l'objet. Je ne recommande pas de faire ça. La fonction peut être retirée à tout moment.

Édition 2: Le JLS couvre en fait plus explicitement les contextes statiques dans §15.9.2 :

Soit [~ # ~] c [~ # ~] soit la classe en cours d'instanciation, et soit i l'instance en cours de création. Si [~ # ~] c [~ # ~] est une classe interne alors i peut avoir une instance immédiatement englobante. L'instance immédiatement englobante de i (§8.1.3) est déterminée comme suit.

  • Si [~ # ~] c [~ # ~] est une classe anonyme, alors:
    • Si l'expression de création d'instance de classe se produit dans un contexte statique (§8.1.3), alors i n'a pas d'instance immédiatement englobante.
    • Sinon, l'instance immédiatement englobante de i est this.

Ainsi, une classe anonyme dans un contexte statique est à peu près équivalente à une classe imbriquée static en ce qu'elle ne conserve pas de référence à la classe englobante, même si techniquement ce n'est pas une classe static.

134
Michael Myers

En quelque sorte. Une classe interne anonyme créée dans une méthode statique sera évidemment effectivement statique car il n'y a pas de source pour un this externe.

Il existe des différences techniques entre les classes internes dans des contextes statiques et les classes imbriquées statiques. Si vous êtes intéressé, lisez le JLS 3rd Ed.

15

Je pense qu'il y a un peu de confusion dans la nomenclature ici, ce qui est certes trop stupide et déroutant.

Peu importe comment vous les appelez, ces modèles (et quelques variantes avec une visibilité différente) sont tout possible, normal, Java légal:

public class MyClass {
  class MyClassInside {
  }
}

public class MyClass {
  public static class MyClassInside {
  }
}

public class MyClass {
  public void method() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

public class MyClass {
  public static void myStaticMethod() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

Ils sont pris en charge dans la spécification de langue (si vous êtes vraiment gêné, voir la section 15.9.5.1 pour celle à l'intérieur de la méthode statique).

Mais cette citation est tout simplement faux:

javac.exe autorisera les classes anonymes dans le code d'initialisation statique et les méthodes statiques, même si la spécification de langue indique que les classes anonymes ne sont jamais statiques

Je pense que l'auteur cité confond le mot clé statique avec le contexte statique . (Certes, le JLS est également un peu déroutant à cet égard.)

Honnêtement, tous les modèles ci-dessus sont très bien (peu importe comment vous les appelez "imbriqués", "intérieurs", "anonymes" peu importe ...). Vraiment, personne ne supprimera soudainement cette fonctionnalité dans la prochaine version de Java. Honnêtement!

14
Neil Coffey

Les classes internes ne peuvent pas être statiques - une classe imbriquée statique n'est pas une classe interne. Le tutoriel Java en parle ici .

6
Andrew Duffy

les classes internes anonymes ne sont jamais statiques (elles ne peuvent pas déclarer des méthodes statiques ou des champs statiques non finaux), mais si elles sont définies dans un contexte statique (méthode statique ou champ statique), elles se comportent comme statiques dans le sens où elles ne peuvent pas accéder aux membres non statiques (c'est-à-dire les instances) de la classe englobante (comme tout le reste à partir d'un contexte statique)

0
Luca