web-dev-qa-db-fra.com

Accéder au constructeur d'une classe anonyme

Disons que j'ai une classe concrète Class1 et que je crée une classe anonyme à partir de celle-ci.

Object a = new Class1(){
        void someNewMethod(){
        }
      };

Est-il possible maintenant de surcharger le constructeur de cette classe anonyme? Comme montré ci-dessous

Object a = new Class1(){
        void someNewMethod(){
        }
        public XXXXXXXX(int a){
          super();
          System.out.println(a);
        }
      };

Avec quelque chose à xxxxxxxx pour nommer le constructeur?

208
Saravanan M

À partir de spécification de langage Java , section 15.9.5.1:

Une classe anonyme ne peut pas avoir un constructeur explicitement déclaré.

Pardon :(

EDIT: Vous pouvez également créer des variables locales finales et/ou inclure un initialiseur d’instance dans la classe anonyme. Par exemple:

public class Test {
    public static void main(String[] args) throws Exception {
        final int fakeConstructorArg = 10;

        Object a = new Object() {
            {
                System.out.println("arg = " + fakeConstructorArg);
            }
        };
    }
}

C'est minable, mais cela pourrait vous aider. Sinon, utilisez une classe imbriquée appropriée :)

269
Jon Skeet

Ce n'est pas possible, mais vous pouvez ajouter un initialiseur anonyme comme ceci:

final int anInt = ...;
Object a = new Class1()
{
  {
    System.out.println(anInt);
  }

  void someNewMethod() {
  }
};

N'oubliez pas final sur les déclarations de variables locales ou de paramètres utilisés par la classe anonyme, comme je l'ai fait pour anInt.

96
Arne Burmeister

Voici un autre moyen de contourner le problème:

public class Test{

    public static final void main(String...args){

        new Thread(){

            private String message = null;

            Thread initialise(String message){

                this.message = message;
                return this;
            }

            public void run(){
                System.out.println(message);
            }
        }.initialise(args[0]).start();
    }
}
72
Joel Shemtov

Je sais que le fil est trop vieux pour poster une réponse. Mais je pense que cela en vaut la peine.

Bien que vous ne puissiez pas avoir de constructeur explicite, si votre intention est d'appeler le constructeur de la super-classe, alors tout ce que vous avez à faire est la suivante.

StoredProcedure sp = new StoredProcedure(datasource, spName) {
    {// init code if there are any}
};

Ceci est un exemple de création d'un objet StoredProcedure dans Spring en passant un DataSource et un objet String.

Donc, si vous voulez créer une classe anonyme et appeler le constructeur de la super classe, créez-la avec une signature correspondant au constructeur de la super classe .

13

Vous pouvez avoir un constructeur dans la classe abstraite qui accepte les paramètres init. La spécification Java spécifie uniquement que la classe anonyme, qui est la progéniture de la classe abstraite (facultative) ou l'implémentation d'une interface, ne peut pas avoir de constructeur par elle-même.

Ce qui suit est absolument légal et possible:

static abstract class Q{
    int z;
    Q(int z){ this.z=z;}
    void h(){
        Q me = new Q(1) {
        };
    }
}

Si vous avez la possibilité d'écrire vous-même la classe abstraite, placez-y un tel constructeur et utilisez une API fluide là où il n'y a pas de meilleure solution. Vous pouvez ainsi remplacer le constructeur de votre classe d'origine en créant une classe sœur nommée avec un constructeur avec des paramètres et l'utiliser pour instancier votre classe anonyme.

3
Peter Verhas

Si vous n'avez pas besoin de passer d'arguments, le code d'initialisation suffit, mais si vous devez passer les arguments d'un contrôleur, il existe un moyen de résoudre la plupart des cas:

Boolean var= new anonymousClass(){
    private String myVar; //String for example

    @Overriden public Boolean method(int i){
          //use myVar and i
    }
    public String setVar(String var){myVar=var; return this;} //Returns self instane
}.setVar("Hello").method(3);
2
Whimusical

Oui, il est vrai que vous ne pouvez pas définir de construction dans une classe anonyme, mais cela ne signifie pas que la classe anonyme n'a pas de constructeur. Confuse ... En fait, vous ne pouvez pas définir de construction dans une classe anonyme, mais le compilateur génère un constructeur avec la même signature que son constructeur parent appelé. Si le parent a plus d'un constructeur, l'anonyme aura un et un seul constructeur

2
Akash Shanker

Peter Norvig's Java IAQ: questions rarement répondues

http://norvig.com/Java-iaq.html#constructors - Constructeurs de classe anonymes

http://norvig.com/Java-iaq.html#init - Constructeurs et initialisation

En résumé, vous pouvez construire quelque chose comme ça ..

public class ResultsBuilder {
    Set<Result> errors;
    Set<Result> warnings;

...

    public Results<E> build() {
        return new Results<E>() {
            private Result[] errorsView;
            private Result[] warningsView;
            {
                errorsView = ResultsBuilder.this.getErrors();
                warningsView = ResultsBuilder.this.getWarnings();
            }

            public Result[] getErrors() {
                return errorsView;
            }

            public Result[] getWarnings() {
                return warningsView;
            }
        };
    }

    public Result[] getErrors() {
        return !isEmpty(this.errors) ? errors.toArray(new Result[0]) : null;
    }

    public Result[] getWarnings() {
        return !isEmpty(this.warnings) ? warnings.toArray(new Result[0]) : null;
    }
}
2
Diogo Quintela

Dans mon cas, une classe locale (avec constructeur personnalisé) fonctionnait comme une classe anonyme:

Object a = getClass1(x);

public Class1 getClass1(int x) {
  class Class2 implements Class1 {
    void someNewMethod(){
    }
    public Class2(int a){
      super();
      System.out.println(a);
    }
  }
  Class1 c = new Class2(x);
  return c;
}
1
arnaldocan

Cela n'a aucun sens d'avoir un constructeur surchargé nommé dans une classe anonyme, car il n'y aurait aucun moyen de l'appeler, de toute façon.

Selon ce que vous essayez réellement de faire, accéder à une variable locale finale déclarée en dehors de la classe ou utiliser un initialiseur d'instance, comme le montre Arne, peut constituer la meilleure solution.

1
Ilja Preuß