Exemple:
public class TestClass {
public static void main(String[] args) {
TestClass t = new TestClass();
}
private static void testMethod() {
abstract class TestMethod {
int a;
int b;
int c;
abstract void implementMe();
}
class DummyClass extends TestMethod {
void implementMe() {}
}
DummyClass dummy = new DummyClass();
}
}
J'ai découvert que le code ci-dessus est parfaitement légal en Java. J'ai les questions suivantes.
DummyClass
Ceci s'appelle une classe locale.
2 est le plus simple: oui, un fichier de classe sera généré.
1 et 3 sont un peu la même question. Vous utiliseriez une classe locale dans laquelle vous n'avez jamais besoin d'instancier ou de connaître les détails de l'implémentation ailleurs que dans une méthode.
Une utilisation typique serait de créer une implémentation jetable de certaines interfaces. Par exemple, vous verrez souvent quelque chose comme ceci:
//within some method
taskExecutor.execute( new Runnable() {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
});
Si vous deviez en créer un ensemble et en faire quelque chose, vous pouvez le changer en
//within some method
class myFirstRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomething( parameter );
}
}
class mySecondRunnableClass implements Runnable {
public void run() {
classWithMethodToFire.doSomethingElse( parameter );
}
}
taskExecutor.execute(new myFirstRunnableClass());
taskExecutor.execute(new mySecondRunnableClass());
En ce qui concerne les interfaces: je ne sais pas s'il existe un problème technique qui fait des interfaces définies localement un problème pour le compilateur, mais même s'il n'y en avait pas, elles ne créeraient aucune valeur. Si une classe locale implémentant une interface locale était utilisée en dehors de la méthode, l'interface n'aurait aucun sens. Et si une classe locale devait uniquement être utilisée dans la méthode, l'interface et la classe seraient implémentées dans cette méthode, de sorte que la définition de l'interface serait redondante.
Celles-ci sont appelées des classes locales . Vous pouvez trouver une explication détaillée et un exemple ici . L'exemple retourne une implémentation spécifique que nous n'avons pas besoin de connaître en dehors de la méthode.
La classe ne peut pas être vue (c'est-à-dire instanciée, ses méthodes accessibles sans réflexion) de l'extérieur de la méthode. En outre, il peut accéder aux variables locales définies dans testMethod (), mais avant la définition de la classe.
J'ai en fait pensé: "Aucun fichier de ce genre ne sera écrit." jusqu'à ce que je viens de l'essayer: Oh oui, un tel fichier est créé! On l'appellera quelque chose comme A $ 1B.class, où A est la classe externe et B est la classe locale.
En particulier pour les fonctions de rappel (gestionnaires d'événements dans les interfaces graphiques, comme onClick () lorsqu'un bouton est cliqué, etc.), il est assez habituel d'utiliser des "classes anonymes", tout d'abord parce que vous pouvez en avoir beaucoup. Mais parfois, les classes anonymes ne suffisent pas - en particulier, vous ne pouvez pas définir un constructeur sur elles. Dans ces cas, ces méthodes locales peuvent être une bonne alternative.
Le but réel de ceci est de nous permettre de créer des classes en ligne dans les appels de fonctions pour consoler ceux d’entre nous qui aimons prétendre écrire dans un langage fonctionnel;)
Le seul cas où vous souhaiteriez avoir une fonction entièrement développée interne et une classe anonyme (a.k.a. Java fermeture)) est lorsque les conditions suivantes sont remplies
Par exemple. quelqu'un veut un Runnable
et vous voulez enregistrer quand l'exécution a commencé et s'est terminée.
Avec une classe anonyme, ce n'est pas possible, avec une classe intérieure, vous pouvez le faire.
Voici un exemple démontre mon point
private static void testMethod (
final Object param1,
final Object param2
)
{
class RunnableWithStartAndEnd extends Runnable{
Date start;
Date end;
public void run () {
start = new Date( );
try
{
evalParam1( param1 );
evalParam2( param2 );
...
}
finally
{
end = new Date( );
}
}
}
final RunnableWithStartAndEnd runnable = new RunnableWithStartAndEnd( );
final Thread thread = new Thread( runnable );
thread.start( );
thread.join( );
System.out.println( runnable.start );
System.out.println( runnable.end );
}
Avant d’utiliser ce modèle, veuillez cependant évaluer si les anciennes classes de classe supérieure, ou internes, ou les classes internes statiques sont tout simplement meilleures.
La principale raison de définir des classes internes (au sein d'une méthode ou d'une classe) est de traiter de l'accessibilité des membres et des variables de la classe et de la méthode englobantes. Une classe interne peut rechercher des membres de données privés et les exploiter. Si, dans une méthode, il peut également traiter de la variable locale finale.
Avoir des classes internes aide à s'assurer que cette classe n'est pas accessible au monde extérieur. Ceci est particulièrement vrai pour les cas de programmation d'interface utilisateur dans GWT ou GXT, etc., où le code générateur de JS est écrit en Java et le comportement de chaque bouton ou événement doit être défini en créant des classes anonymes