2008-12-12 17 views
186

Digamos que tengo una clase concreta Class1 y estoy creando una clase anónima de ella.Accediendo al constructor de una clase anónima

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

Ahora, hay alguna forma de sobrecargar el constructor de esta clase anónima. Como se muestra a continuación

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

¿Hay algo en xxxxxxxx para nombrar el constructor?

+4

Vale la pena leer [DoubleBraceInitialization] (http://c2.com/cgi/wiki?DoubleBraceInitialization) –

Respuesta

240

Desde el Java Language Specification, la sección 15.9.5.1:

Una clase anónima no puede tener un constructor declarado explícitamente.

Lo sentimos :(

EDIT: Como alternativa, puede crear algunas variables locales finales, y/o incluir un inicializador ejemplo, en la clase anónima Por ejemplo:.

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 grotesco, pero podría ayudarle. Alternativamente, use una clase anidada adecuada :)

+1

En realidad, no había visto su solución antes de agregarla. –

+16

Arne, le creo que no lo copió. él sabe lo suficiente de Java para ser lo suficientemente justo como para dar crédito cuando lo habría copiado, creo. –

+18

OMG, ¿alguien culpó a THE Jon Skeet por copiar? – user

85

Eso no es posible, pero puede agregar un inicializador anónimo como este:

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

    void someNewMethod() { 
    } 
}; 

No olvide las declaraciones finales de las variables locales o los parámetros utilizados por la clase anónima, como lo hice para anInt.

1

No tiene ningún sentido tener un nombre sobrecargado constructor en una clase anónima, ya que no habría manera de llamarlo, de todos modos.

Dependiendo de lo que realmente está tratando de hacer, acceder a una variable local final declarada fuera de la clase, o usar un inicializador de instancia como lo muestra Arne, podría ser la mejor solución.

+0

El lenguaje podría fácilmente volverse "normal" "argumentos de constructor en argumentos para la clase anónima, si lo desea. La sintaxis para la declaración del constructor probablemente sería bastante rara ... –

+0

¿No podría decir que declara al constructor como si fuera el constructor de la clase base? no veo problemas con esa –

2

Sí, es correcto que no se puede definir construir en una clase Anónima, pero eso no significa que la clase anónima no tenga constructor. Confuse ... En realidad, no puede definir constructo en una clase Anónima, pero el compilador genera un constructor para él con la misma firma que su constructor padre llamado. Si el padre tiene más de un constructor, el anonimato tendrá uno y sólo un constructor

65

Ésta es otra manera el problema:

public class Test{ 

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

     Thread t = 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(); 
    } 
} 
+17

Buena solución, pero el uso de Thread aquí lo hace algo engañoso al principio (¡por un momento pensé que se te había creado un hilo por separado para inicializar cosas!) – scorpiodawg

+6

Ten en cuenta que después de 't' se define no puedes llamar 't.initialise() 'a menos que esta función esté definida en el tipo clase/interfaz. –

+1

@AramKocharyan Eso hace que funcione aún más como un constructor. – v010dya

1

En mi caso, una clase local (con el constructor personalizado) trabajado como una clase anónima:

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

Si usted no necesita pasar argumentos, entonces inicializador código es suficiente, pero si usted necesita para pasar argumentos de una contrcutor hay una manera de resolver la mayoría de los casos:

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

Si entiendo tu código anonymousClass debería heredar de String (setVar es el tipo de Cadena y lo devuelve), pero String no se puede extender. Supongo que setVar debería devolver de qué se extiende la clase anonymousClass. – alfoks

3

Puede tener un constructor en la clase abstracta que acepte los parámetros init. La especificación de Java solo especifica que la clase anónima, que es la descendencia de la clase abstracta (opcionalmente) o la implementación de una interfaz, no puede tener un constructor por derecho propio.

El siguiente es absolutamente legal y posible:

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

Si usted tiene la posibilidad de escribir la clase abstracta a sí mismo, poner un constructor de tales cosas y utilizar API fluida donde no hay una solución mejor. De esta manera puede anular el constructor de su clase original creando una clase de hermanos nombrada con un constructor con parámetros y usar eso para instanciar su clase anónima.

1

El Java IAQ de Peter Norvig: Preguntas Con poca frecuencia con respuesta

http://norvig.com/java-iaq.html#constructors - contructors anónimos clase

http://norvig.com/java-iaq.html#init - Construtors e inicialización

Resumiendo, se puede construir algo como esto ..

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

No conocía a Peter Norvig, un científico de Google, probablemente sea uno de sus primeros trabajos, ¡se trata de Java 1.1! Interesante en un punto de vista histórico :) – pdem

12

Sé que el hilo es demasiado viejo para publicar una respuesta. Pero aún así creo que vale la pena.

Aunque no puede tener un constructor explícito, si su intención es llamar al constructor de la superclase, lo siguiente es todo lo que tiene que hacer.

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

Este es un ejemplo de creación de un objeto StoredProcedure en la primavera haciendo pasar una DataSource y un objeto de String.

Por lo tanto, la conclusión es que si desea crear una clase anónima y desea llamar al constructor de la superclase, cree la clase anónima con una firma que coincida con el constructor de clase superior.

Cuestiones relacionadas