111 votes

L'utilisation de définitions de classe à l'intérieur d'une méthode en Java

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 trouvé que cette partie de code est parfaitement légal en Java. J'ai les questions suivantes.

  1. Qu'est-ce que l'utilisation de jamais avoir une définition de classe à l'intérieur d'une méthode?
  2. Un fichier de classe seront générés pour DummyClass
  3. Difficile pour moi d'imaginer ce concept dans un Objet. Avoir une définition de classe à l'intérieur d'un comportement. Probablement quelqu'un peut-il me dire l'équivalent des exemples du monde réel.
  4. Les classes abstraites à l'intérieur d'une méthode semble un peu fou de moi. Mais pas d'interfaces de permis. Est-il une raison derrière tout cela?

Merci

Edit: Ajout de la question concernant la méthode Abstraite classes.

78voto

Jacob Mattison Points 32137

Ceci est appelé une classe locale.

2 est facile: oui, un fichier de classe sera généré.

1 et 3 sont en quelque sorte la même question. Vous pouvez utiliser un local de classe où vous n'avez jamais besoin d'instancier un ou de connaître les détails de l'application n'importe où, mais dans une méthode.

Une utilisation typique serait de créer un jeter de la mise en œuvre d'une interface. Par exemple, vous aurez souvent quelque chose comme ceci:

  //within some method
  taskExecutor.execute( new Runnable() {
       public void run() {
            classWithMethodToFire.doSomething( parameter );
       }
  }); 

Si vous avez besoin de créer un tas de ces et faire quelque chose avec eux, vous pouvez modifier ce

  //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());

Concernant les interfaces: je ne sais pas si il y a un problème technique qui rend définies localement des interfaces un problème pour le compilateur, mais même si il n'y en a pas, ils ne seraient pas ajouter de la valeur. Si une classe qui implémente une interface locale ont été utilisés en dehors de la méthode, l'interface serait vide de sens. Et si une classe locale est uniquement destiné à être utilisé à l'intérieur de la méthode, à la fois l'interface et la classe devrait être mis en œuvre à l'intérieur de cette méthode, de sorte que la définition de l'interface serait redondante.

17voto

BalusC Points 498232

Ceux-ci sont appelés classes locales. Vous trouverez une explication détaillée et un exemple ici. L'exemple renvoie une mise en œuvre spécifique qui on n'a pas besoin de connaître en dehors de la méthode.

11voto

Chris Lercher Points 22134
  1. La classe ne peut pas être vu (c'est à dire instancié, ses méthodes d'accéder sans Réflexion) de l'extérieur de la méthode. Aussi, il peut accéder aux variables locales définies dans testMethod(), mais avant la définition de la classe.

  2. J'ai pensé: "un tel fichier sera écrit." jusqu'à ce que je l'ai juste essayé: Oh oui, un tel fichier est créé! Il sera appelé quelque chose comme$1B.class, où A est l'extérieur de la classe, et B est la classe locale.

  3. En particulier pour les fonctions de rappel (gestionnaires d'événements dans les Interfaces graphiques, comme onClick() quand on clique sur un Bouton, etc.), c'est tout à fait habituel d'utiliser des "anonymes classes" - tout d'abord parce que vous pouvez vous retrouver avec beaucoup d'entre eux. Mais parfois anonymes classes ne sont pas assez bons - en particulier, vous ne pouvez pas définir un constructeur. Dans ces cas, la méthode de classes locales peuvent être une bonne alternative.

7voto

Steve B. Points 23227

Le but réel de ce qui est pour nous permettre de créer des classes en ligne dans les appels de fonction pour consoler ceux d'entre nous qui aiment à prétendre que nous sommes en train d'écrire dans un langage fonctionnel ;)

4voto

Alexander Pogrebnyak Points 24964

Le seul cas où vous souhaitez avoir une véritable fonction interne de la classe vs classe anonyme ( un.k.un. Java fermeture ), c'est quand les conditions suivantes sont réunies

  1. vous devez fournir une interface ou une classe abstraite de la mise en œuvre
  2. vous souhaitez utiliser certains paramètres définis dans l'appel de fonction
  3. vous avez besoin d'enregistrer de l'état d'exécution de l'interface d'appel.

E. g. quelqu'un veut un Runnable et que vous souhaitez enregistrer lorsque l'exécution a commencé et s'est terminée.

Avec la classe anonyme, il n'est pas possible de le faire, à l'intérieur de la classe, vous pouvez le faire.

Voici un exemple ne montrer mon point de

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 l'utilisation de ce modèle cependant, veuillez évaluer si le bon vieux haut-niveau de la classe, ou à l'intérieur de la classe, ou statiques à l'intérieur de la classe sont de meilleures alternatives.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X