it-swarm.com.de

Zugriff auf Konstruktor einer anonymen Klasse

Nehmen wir an, ich habe eine konkrete Klasse Class1 und erstelle daraus eine anonyme Klasse.

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

Jetzt kann ich den Konstruktor dieser anonymen Klasse auf irgendeine Weise überladen. Wie unten gezeigt

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

Mit etwas bei xxxxxxxx, um den Konstruktor zu nennen?

208
Saravanan M

Aus der Java Language Specification , Abschnitt 15.9.5.1:

Eine anonyme Klasse kann keinen explizit deklarierten Konstruktor haben.

Es tut uns leid :(

BEARBEITEN: Alternativ können Sie einige endgültige lokale Variablen erstellen und/oder einen Instanzinitialisierer in die anonyme Klasse aufnehmen. Beispielsweise:

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

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

Es ist grotty, aber es könnte dir nur helfen. Verwenden Sie alternativ eine geeignete verschachtelte Klasse :)

269
Jon Skeet

Das ist nicht möglich, aber Sie können einen anonymen Initialisierer wie diesen hinzufügen:

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

  void someNewMethod() {
  }
};

Vergessen Sie nicht final on-Deklarationen lokaler Variablen oder Parameter, die von der anonymen Klasse verwendet werden, wie ich es für anInt getan habe.

96
Arne Burmeister

Hier ist eine andere Möglichkeit, das Problem zu umgehen:

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

Ich weiß, dass der Thread zu alt ist, um eine Antwort zu schreiben. Trotzdem denke ich, dass es sich lohnt.

Obwohl Sie keinen expliziten Konstruktor haben können, ist das Folgende alles, was Sie tun müssen, wenn Sie den Konstruktor der Superklasse aufrufen möchten.

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

Dies ist ein Beispiel für das Erstellen eines StoredProcedure -Objekts im Frühjahr, indem ein DataSource- und ein String -Objekt übergeben werden .

Wenn Sie also eine anonyme Klasse erstellen und den Superklassenkonstruktor aufrufen möchten, erstellen Sie die anonyme Klasse mit einer Signatur, die dem Superklassenkonstruktor entspricht.

Sie können einen Konstruktor in der abstrakten Klasse haben, der die init-Parameter akzeptiert. Die Java spec gibt nur an, dass die anonyme Klasse, die die Abkömmlinge der (optional) abstrakten Klasse oder die Implementierung einer Schnittstelle ist, keinen eigenen Konstruktor haben kann.

Folgendes ist absolut legal und möglich:

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

Wenn Sie die Möglichkeit haben, die abstrakte Klasse selbst zu schreiben, platzieren Sie einen solchen Konstruktor dort und verwenden Sie eine flüssige API, wo es keine bessere Lösung gibt. Auf diese Weise können Sie den Konstruktor Ihrer ursprünglichen Klasse überschreiben, indem Sie eine benannte Geschwisterklasse mit einem Konstruktor mit Parametern erstellen und diese verwenden, um Ihre anonyme Klasse zu instanziieren.

3
Peter Verhas

Wenn Sie keine Argumente übergeben müssen, reicht der Initialisierungscode aus. Wenn Sie jedoch Argumente von einem Kontributor übergeben müssen, können Sie die meisten Fälle lösen:

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

Ja, es ist richtig, dass Sie in einer anonymen Klasse kein Konstrukt definieren können, dies bedeutet jedoch nicht, dass die anonyme Klasse keinen Konstruktor hat. Confuse ... Eigentlich können Sie in einer anonymen Klasse kein Konstrukt definieren, aber der Compiler generiert dafür einen Konstruktor mit der gleichen Signatur wie der übergeordnete Konstruktor. Wenn das übergeordnete Element mehr als einen Konstruktor hat, hat das anonyme Element nur einen Konstruktor

2
Akash Shanker

Peter Norvigs The Java IAQ: Selten beantwortete Fragen

http://norvig.com/Java-iaq.html#constructors - Anonyme Klassenkonstruktoren

http://norvig.com/Java-iaq.html#init - Construtors und Initialisierung

Zusammenfassend kann man so etwas konstruieren ..

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

In meinem Fall arbeitete eine lokale Klasse (mit benutzerdefiniertem Konstruktor) als anonyme Klasse:

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

Es macht keinen Sinn, einen benannten überladenen Konstruktor in einer anonymen Klasse zu haben, da es sowieso keine Möglichkeit gibt, ihn aufzurufen.

Je nachdem, was Sie tatsächlich versuchen, ist es möglicherweise die beste Lösung, auf eine letzte lokale Variable zuzugreifen, die außerhalb der Klasse deklariert wurde, oder einen Instanzinitialisierer zu verwenden, wie er von Arne gezeigt wird.

1
Ilja Preuß