Pregunta Entrevista: ¿Podemos instanciar una clase abstracta?


El entrevistador preguntó: ¿Podemos crear una instancia de una clase abstracta? Dije: No. Él me dijo: Mal, podemos.

Discutí un poco sobre esto. Luego me dijo que probara esto en tu casa.

abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

class poly {
    public static void main(String a[]) {
        my m = new my() {};
        m.mymethod();
    }
}

Aquí, estoy creando una instancia de mi clase y método de llamada de clase abstracta. ¿Alguien puede explicarme esto? ¿Estaba realmente equivocado durante mi entrevista?


524
2017-12-02 16:01


origen


Respuestas:


Aquí, estoy creando una instancia de mi clase

No, no estás creando la instancia de tu clase abstracta aquí. Más bien estás creando una instancia de subclase anónima de tu clase abstracta Y luego está invocando el método en su clase abstracta referencia que apunta a objeto de subclase.

Este comportamiento está claramente enumerado en JLS - Sección # 15.9.1: -

Si la expresión de creación de instancia de clase termina en un cuerpo de clase, entonces   la clase que se está instanciando es una clase anónima. Entonces:

  • Si T denota una clase, entonces se declara una subclase directa anónima de la clase nombrada por T. Es un error en tiempo de compilación si   clase denotada por T es una clase final.
  • Si T denota una interfaz, entonces se declara una subclase directa anónima de Object que implementa la interfaz nombrada por T.
  • En cualquier caso, el cuerpo de la subclase es el ClassBody dado en la expresión de creación de instancia de clase.
  • La clase que se crea una instancia es la subclase anónima.

Énfasis mío

También en JLS - Sección # 12.5, puedes leer sobre el Proceso de creación de objetos. Citaré una declaración de eso aquí:

Siempre que se crea una nueva instancia de clase, se asigna espacio de memoria   para ello con espacio para todas las variables de instancia declaradas en la clase   Escriba y todas las variables de instancia declaradas en cada superclase de la   tipo de clase, incluidas todas las variables de instancia que pueden estar ocultas.

Justo antes de que se devuelva una referencia al objeto recién creado como el   resultado, el constructor indicado se procesa para inicializar el nuevo   objeto utilizando el siguiente procedimiento:

Puede leer sobre el procedimiento completo en el enlace que proporcioné.


Prácticamente ver que la clase que se ejemplifica es una Subclase anónima, solo necesitas compilar tus dos clases. Supongamos que coloca esas clases en dos archivos diferentes:

My.java:

abstract class My {
    public void myMethod() {
        System.out.print("Abstract");
    }
}

Poly.java:

class Poly extends My {
    public static void main(String a[]) {
        My m = new My() {};
        m.myMethod();
    }
}

Ahora, compila tus dos archivos fuente:

javac My.java Poly.java

Ahora en el directorio donde compiló el código fuente, verá los siguientes archivos de clase:

My.class
Poly$1.class  // Class file corresponding to anonymous subclass
Poly.class

Mira esa clase - Poly$1.class. Es el archivo de clase creado por el compilador correspondiente a la subclase anónima que instanciaste usando el siguiente código:

new My() {};

Entonces, está claro que hay una clase diferente siendo instanciada. Es solo que, esa clase recibe un nombre solo después de la compilación del compilador.

En general, todas las subclases anónimas en su clase se nombrarán de esta manera:

Poly$1.class, Poly$2.class, Poly$3.class, ... so on

Esos números denotan el orden en que esas clases anónimas aparecen en la clase adjunta.


663
2017-12-02 16:04



Lo anterior crea una clase interna anónima que es una subclase del my clase abstracta. No es estrictamente equivalente a crear una instancia de la clase abstracta en sí misma. OTOH, cada instancia de subclase es una instancia de todas sus superclases e interfaces, por lo que la mayoría de las clases abstractas se instancian instanciando una de sus subclases concretas.

Si el entrevistador acaba de decir "¡mal!" sin explicar, y dio este ejemplo, como contraejemplo único, creo que él no sabe de lo que está hablando, sin embargo.


87
2017-12-02 16:04



= my() {}; significa que hay una implementación anónima, no una instanciación simple de un objeto, que debería haber sido: = my(). Nunca puedes instanciar una clase abstracta.


82
2017-12-02 16:29



Solo observaciones que podrías hacer:

  1. Por qué poly se extiende my? Esto es inútil ...
  2. ¿Cuál es el resultado de la compilación? Tres archivos: my.class, poly.class y poly$1.class
  3. Si podemos crear una instancia de una clase abstracta como esa, también podemos instanciar una interfaz ... extraño ...


¿Podemos instanciar una clase abstracta?

No, no podemos. Lo que podemos hacer es crear una clase anónima (ese es el tercer archivo) y crear una instancia.


¿Qué tal una instanciación de superclase?

La superclase abstracta no está instanciada por nos pero por java

EDITAR: Pídale que pruebe esto

public static final void main(final String[] args) {
    final my m1 = new my() {
    };
    final my m2 = new my() {
    };
    System.out.println(m1 == m2);

    System.out.println(m1.getClass().toString());
    System.out.println(m2.getClass().toString());

}

salida es:

false
class my$1
class my$2

29
2017-12-06 16:12



Simplemente puede responder, en una sola línea

No, nunca puedes instanciar la clase abstracta

Pero, entrevistador todavía no está de acuerdo, entonces usted puede decirle

Todo lo que puedes hacer es crear una clase anónima.

Y, según la clase Anónima, clase declarada e instancia en el mismo lugar / línea 

Por lo tanto, es posible que el entrevistador esté interesado en verificar su nivel de confianza y cuánto sabe acerca de los OOP.


17
2017-12-07 04:09



La parte técnica ha sido bien cubierta en las otras respuestas, y principalmente termina en:
 "Está equivocado, no sabe nada, pídele que se una a SO y aclare todo :)"

Me gustaría abordar el hecho (que se ha mencionado en otras respuestas) que esto podría ser una pregunta de estrés y es una herramienta importante para que muchos entrevistadores sepan más sobre usted y cómo reacciona ante situaciones difíciles e inusuales. Al darte códigos incorrectos, él probablemente quería ver si discutiste. Para saber si tiene la confianza para enfrentarse a sus superiores en situaciones similares a esta.

P.S: No sé por qué, pero tengo la sensación de que el entrevistador ha leído esta publicación.


16
2018-04-07 05:20



Las clases abstractas no se pueden crear instancias, pero se pueden subclasificar. Ver este enlace

El mejor ejemplo es

A pesar de que La clase de calendario tiene un método abstracto getInstance ()pero cuando dices Calendar calc=Calendar.getInstance();

calc se refiere a la instancia de clase de la clase GregorianCalendar como "GregorianCalendar extends Calendar""

De hecho tipo interno anónimo  le permite crear una subclase sin nombre de la clase abstracta y una instancia de esto.


13
2017-12-03 09:14