Question Interview: Pouvons-nous instancier une classe abstraite?


L'intervieweur a demandé - Pouvons-nous instancier un cours abstrait? J'ai dit, Non. Il m'a dit - Faux, nous pouvons.

J'ai discuté un peu à ce sujet. Puis il m'a dit de l'essayer vous-même chez vous.

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

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

Ici, je crée une instance de ma classe et appelle une méthode de classe abstraite. Quelqu'un peut-il m'expliquer cela? Avais-je vraiment tort pendant mon interview?


524
2017-12-02 16:01


origine


Réponses:


Ici, je crée une instance de ma classe

Non, vous ne créez pas l'instance de votre classe abstraite ici. Au contraire, vous créez une instance d'un sous-classe anonyme de votre classe abstraite. Et puis vous invoquez la méthode sur votre classe abstraite référence pointant vers objet de la sous-classe.

Ce comportement est clairement répertorié dans JLS - Section # 15.9.1: -

Si l'expression de création d'instance de classe se termine par un corps de classe, alors   la classe en cours d'instanciation est une classe anonyme. Alors:

  • Si T désigne une classe, alors une sous-classe directe anonyme de la classe nommée par T est déclarée. C'est une erreur de compilation si le   la classe désignée par T est une classe finale.
  • Si T désigne une interface, alors une sous-classe directe anonyme d'Object qui implémente l'interface nommée par T est déclarée.
  • Dans les deux cas, le corps de la sous-classe est le ClassBody donné dans l'expression de création de l'instance de classe.
  • La classe en cours d'instanciation est la sous-classe anonyme.

Emphase la mienne.

Aussi dans JLS - Section # 12.5, vous pouvez lire sur le Processus de création d'objet. Je citerai une déclaration de cela ici:

Chaque fois qu'une nouvelle instance de classe est créée, l'espace mémoire est alloué   pour cela avec de la place pour toutes les variables d'instance déclarées dans la classe   type et toutes les variables d'instance déclarées dans chaque superclasse du   type de classe, y compris toutes les variables d'instance qui peuvent être masquées.

Juste avant qu'une référence à l'objet nouvellement créé soit renvoyée   résultat, le constructeur indiqué est traité pour initialiser le nouveau   objet en utilisant la procédure suivante:

Vous pouvez lire la procédure complète sur le lien que j'ai fourni.


Pour voir pratiquement que la classe en cours d'instanciation est un Sous-classe anonyme, vous avez juste besoin de compiler vos deux classes. Supposons que vous placiez ces classes dans deux fichiers différents:

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

Maintenant, compilez vos deux fichiers sources:

javac My.java Poly.java

Maintenant, dans le répertoire où vous avez compilé le code source, vous verrez les fichiers de classe suivants:

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

Voir cette classe - Poly$1.class. C'est le fichier de classe créé par le compilateur correspondant à la sous-classe anonyme que vous avez instancié en utilisant le code ci-dessous:

new My() {};

Donc, il est clair qu'il y a une autre classe en cours d'instanciation. C'est juste que cette classe ne reçoit un nom qu'après compilation par le compilateur.

En général, toutes les sous-classes anonymes de votre classe seront nommées de cette manière:

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

Ces chiffres indiquent l'ordre dans lequel ces classes anonymes apparaissent dans la classe englobante.


663
2017-12-02 16:04



Ce qui précède instancie une classe interne anonyme qui est une sous-classe du my classe abstraite. Ce n'est pas strictement équivalent à l'instanciation de la classe abstraite elle-même. OTOH, chaque instance de sous-classe est une instance de toutes ses super classes et interfaces, de sorte que la plupart des classes abstraites sont instanciées en instanciant l'une de leurs sous-classes concrètes.

Si l'intervieweur vient de dire "mal!" sans expliquer, et a donné cet exemple, comme un contre-exemple unique, je pense qu'il ne sait pas de quoi il parle, cependant.


87
2017-12-02 16:04



= my() {}; signifie qu'il y a une implémentation anonyme, pas une simple instanciation d'un objet, qui aurait dû être: = my(). Vous ne pouvez jamais instancier une classe abstraite.


82
2017-12-02 16:29



Juste des observations que vous pourriez faire:

  1. Pourquoi poly s'étend my? C'est inutile ...
  2. Quel est le résultat de la compilation? Trois fichiers: my.class, poly.class et poly$1.class
  3. Si nous pouvons instancier une classe abstraite comme ça, nous pouvons instancier une interface aussi ... bizarre ...


Pouvons-nous instancier une classe abstraite?

Non, nous ne pouvons pas. Ce que nous pouvons faire est de créer une classe anonyme (c'est le troisième fichier) et de l'instancier.


Qu'en est-il d'une instanciation de super classe?

La super classe abstraite n'est pas instanciée par nous mais par java.

EDIT: Demandez-lui de tester cette

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

}

la sortie est:

false
class my$1
class my$2

29
2017-12-06 16:12



Vous pouvez simplement répondre, en une seule ligne

Non, vous ne pouvez jamais utiliser la classe abstraite

Mais, l'interviewer n'est toujours pas d'accord, alors vous pouvez lui dire

tout ce que vous pouvez faire est, vous pouvez créer une classe anonyme.

Et, selon la classe anonyme, classe déclarée et instanciée au même endroit / ligne 

Ainsi, il pourrait être possible que l'intervieweur soit intéressé à vérifier votre niveau de confiance et ce que vous savez sur les POO.


17
2017-12-07 04:09



La partie technique a été bien couverte dans les autres réponses, et elle se termine principalement par:
 "Il a tort, il ne connaît pas les choses, lui demande de rejoindre SO et de tout effacer :)"

Je voudrais aborder le fait (qui a été mentionné dans d'autres réponses) que cela pourrait être un stress-question et est un outil important pour de nombreux intervieweurs pour en savoir plus sur vous et comment réagissez-vous à des situations difficiles et inhabituelles. En vous donnant des codes incorrects, il Probablement voulait voir si vous avez plaidé en arrière. Pour savoir si vous avez la confiance nécessaire pour lutter contre vos aînés dans des situations semblables.

P.S: Je ne sais pas pourquoi mais j'ai le sentiment que l'interviewer a lu cet article.


16
2018-04-07 05:20



Les classes abstraites ne peuvent pas être instanciées, mais elles peuvent être sous-classées. Voir ce lien

Le meilleur exemple est

Bien que La classe de calendrier a une méthode abstraite getInstance ()mais quand tu dis Calendar calc=Calendar.getInstance();

calc fait référence à l'instance de classe de la classe GregorianCalendar en tant que "GregorianCalendar extends Calendar"

En réalité type interne  vous permet de créer une sous-classe sans nom de la classe abstraite et une instance de ceci.


13
2017-12-03 09:14



Réponse technique

Les classes abstraites ne peuvent pas être instanciées - c'est par définition et par conception.

De la JLS, chapitre 8. Classes:

Une classe nommée peut être déclarée abstraite (§8.1.1.1) et doit être déclarée   abstrait s'il est incomplètement mis en œuvre; une telle classe ne peut pas être   instancié, mais peut être étendu par des sous-classes.

A partir de JSE 6 java doc pour Classes.newInstance ():

InstantiationException - si cette classe représente une classe abstraite, une interface, un tableau   class, un type primitif ou void; ou si la classe n'a pas de constructeur nul; ou si le   l'instanciation échoue pour une autre raison.

Vous pouvez, bien sûr, instancier une sous-classe concrète d'une classe abstraite (y compris une sous-classe anonyme) et également effectuer un typecast d'une référence d'objet à un type abstrait.

Un angle différent sur ceci - Teamplay et intelligence sociale:

Ce genre de malentendu technique se produit fréquemment dans le monde réel lorsque nous traitons des technologies complexes et des spécifications juridiques.

Les «compétences humaines» peuvent être plus importantes ici que les «compétences techniques». Si vous essayez de prouver votre point de vue de manière compétitive et agressive, alors vous pourriez théoriquement avoir raison, mais vous pourriez aussi faire plus de dégâts en ayant un «combat» / un «ennemi» nuisible / en créant un ennemi. Soyez réconciliant et compréhensif dans la résolution de vos différends. Qui sait - peut-être que vous avez «les deux droits», mais travailler des significations légèrement différentes pour les termes ??

Qui sait - bien que peu probable, il est possible que l'intervieweur ait délibérément introduit un petit conflit / malentendu pour vous mettre dans une situation difficile et voir comment vous vous comportez émotionnellement et socialement. Soyez courtois et constructif avec vos collègues, suivez les conseils des aînés et suivez l'entrevue pour résoudre tout défi / malentendu - par courriel ou par téléphone. Vous montre que vous êtes motivé et axé sur les détails.


11
2018-03-18 03:10