Доступ к конструктору анонимного класса


допустим, у меня есть конкретный класс Class1 и я создаю анонимный класс из него.

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

теперь есть ли способ, которым я мог бы перегрузить конструктор этого анонимного класса. Как показано ниже

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

С чем-то в xxxxxxxx назвать конструктор?

10 196

10 ответов:

С Спецификация Языка Java раздел 15.9.5.1:

анонимный класс не может иметь явно объявленный конструктор.

извините :(

EDIT: в качестве альтернативы вы можете создать некоторые конечные локальные переменные и/или включить инициализатор экземпляра в анонимный класс. Например:

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

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

это гротти, но это может просто помочь вам. Кроме того, используйте правильный вложенный класс:)

это невозможно, но вы можете добавить анонимный инициализатор, как это:

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

  void someNewMethod() {
  }
};

Не забудьте final на объявления локальных переменных или параметров, используемых анонимным классом, как я сделал это для anInt.

вот еще один способ решения проблемы:

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

Я знаю, что поток слишком стар, чтобы опубликовать ответ. Но все же я думаю, что оно того стоит.

хотя у вас не может быть явного конструктора, если вы хотите вызвать конструктор суперкласса, то вам нужно сделать следующее.

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

Это пример создания StoredProcedure объект весной, передавая DataSource и String "объект".

Итак, если вы хотите создать анонимный класс и хотите вызвать конструктор суперкласса, а затем создать анонимный класс с подпись, соответствующая конструктору суперкласса.

вы можете иметь конструктор в абстрактном классе, который принимает параметры инициализации. Спецификация Java только указывает, что анонимный класс, который является потомком (необязательно) абстрактного класса или реализации интерфейса, не может иметь конструктор по своему собственному праву.

абсолютно законно и возможно следующее:

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

Если у вас есть возможность написать абстрактный класс самостоятельно, поместите туда такой конструктор и используйте fluent API, где нет лучшего решения. Таким образом, вы можете переопределить конструктор класса создает именованный класс с братом конструктор с параметрами и использовать его для создания экземпляра анонимного класса.

Да, это правильно, что вы не можете определить конструкцию в анонимном классе, но это не значит, что анонимный класс не имеет конструктора. Смущать... На самом деле вы не можете определить construct в анонимном классе, но компилятор генерирует конструктор для него с той же сигнатурой, что и его родительский конструктор. Если родитель имеет более одного конструктора, анонимный будет иметь один и только один конструктор

Если вам не нужно передавать аргументы, то код инициализатора достаточно, но если вам нужно передать аргументы от contrcutor есть способ решить большинство случаев:

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

Питер Норвиг в Java IAQ: нечасто отвечал на вопросы

http://norvig.com/java-iaq.html#constructors - анонимные конструкторы классов

http://norvig.com/java-iaq.html#init - интерпретаторы и инициализация

суммируя, можно создать что-то вроде этого..

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;
    }
}

нет никакого смысла иметь именованный перегруженный конструктор в анонимном классе, так как его все равно нельзя было бы вызвать.

в зависимости от того, что вы на самом деле пытаетесь сделать, просто доступ к конечной локальной переменной, объявленной вне класса, или использование инициализатора экземпляра, как показано Arne, может быть лучшим решением.

в моем случае локальный класс (с пользовательским конструктором) работал как анонимный класс:

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;
}