Intervju: Možemo li stvoriti apstraktnu klasu?

Anketar je pitao: Je li moguće stvoriti primjerak apstraktne klase? Rekao sam: Ne. Rekao mi je: "Pogrešno, možemo.

Malo sam se raspravljao o tome. Onda mi je rekao da pokušam kod kuće.

 abstract class my { public void mymethod() { System.out.print("Abstract"); } } class poly { public static void main(String a[]) { my m = new my() {}; m.mymethod(); } } 

Ovdje kreiram instancu klase i metodu pozivanja apstraktne klase. Može li mi itko to objasniti? Jesam li stvarno bio u krivu tijekom intervjua?

507
02 дек. 02 prosinac postavio Ravi 2012-12-02 19:01 '12 u 19:01 2012-12-02 19:01
@ 15 odgovora

Ovdje stvaram primjerak svoje klase.

Ne, ovdje ne stvarate primjerak apstraktne klase. Umjesto toga, stvarate instancu anonimne podklase vaše apstraktne klase. I tada pozivate metodu u svojoj apstraktnoj klasnoj referenci koja upućuje na objekt potklase.

To je izričito navedeno u JLS-u - odjeljak # 15.9.1 : -

Ako izraz kreiranja instance klase završava u klasi klase, onda je instanca klase anonimna klasa. zatim:

  • Ako T označava klasu, proglašava se anonimna izravna potklasa klase T. To je greška u vremenu prevođenja ako je klasa označena s T konačna klasa.
  • Ako T označava sučelje, tada se proglašava anonimna izravna podrazreda Objekta koji implementira sučelje po imenu T.
  • U svakom slučaju, tijelo potklase je ClassBody, kao što je navedeno u izrazu stvaranja primjerka klase.
  • Klasa koja se stvara je anonimna podklasa.

Usredotočite se na moje.

Osim toga, u JLS - Odjeljku # 12.5 možete čitati o procesu stvaranja objekta. Ovdje ću vam dati jednu od sljedećih izjava:

Kad god se kreira nova instanca klase, za nju se dodjeljuje memorijski prostor sa sobom za sve varijable instance deklarirane u tipu klase i sve varijable instance koje su deklarirane u svakoj vrsti klase superklase, uključujući sve varijable instance koje se mogu sakriti.

Prije nego što se referenca na novo stvoreni objekt vrati kao rezultat, specificirani konstruktor se obrađuje da inicijalizira novi objekt koristeći sljedeći postupak:

O cijelom postupku možete pročitati na poveznici koju sam dao.


Da biste vidjeli da je klasa koja se stvara anonimni SubClass, trebate samo kompilirati obje vaše klase. Pretpostavimo da stavite te klase u dvije različite datoteke:

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

Sada kompajlirajte obje izvorne datoteke:

 javac My.java Poly.java 

Sada u direktoriju u kojem ste sastavili izvorni kôd vidjet ćete sljedeće datoteke razreda:

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

Pogledajte ovaj razred - Poly$1.class . Ovo je klasna datoteka koju je stvorio prevodilac, koja odgovara anonimnoj podklasi koju ste stvorili pomoću koda u nastavku:

 new My() {}; 

Dakle, jasno je da se kreira instanca druge klase. Samo je ovoj klasi dodijeljeno ime samo nakon kompilacije od strane prevodioca.

Općenito, svi anonimni podklasi u vašem razredu bit će pozvani na sljedeći način:

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

Ovi brojevi označavaju redoslijed po kojem se te anonimne klase pojavljuju u obuhvatnoj klasi.

638
02 дек. Odgovor daje Rohit Jain 02. prosinca. 2012-12-02 19:04 '12 u 19:04 2012-12-02 19:04

Gore navedena instanca je anonimna unutarnja klasa, koja je potklasa apstrakta my klase. Ona nije strogo ekvivalentna instanci apstraktne klase. OTO, svaka instanca podrazreda je instanca svih njezinih nadklasa i sučelja, tako da je većina apstraktnih klasa zapravo stvorena tako da se instalira jedna od njihovih podklasa.

border=0

Ako je intervjuer upravo rekao "pogrešno!" bez objašnjenja, i dao ovaj primjer kao jedinstveni protuprimjer, mislim da on ne zna o čemu govori.

85
02 дек. Odgovor daje JB Nizet 02. prosinca. 2012-12-02 19:04 '12 u 19:04 2012-12-02 19:04

= my() {}; znači da postoji anonimna implementacija, a ne jednostavna izrada objekta, koja bi trebala biti: = my() . Nikada ne možete stvoriti apstraktnu klasu.

81
02 дек. odgovor na dan 2. prosinca 2012-12-02 19:29 '12 u 19:29 2012-12-02 19:29

Samo zapažanja koja možete napraviti:

  • Zašto poly proteže my ? Beskorisno je ...
  • Što je rezultat kompilacije? Tri datoteke: my.class , poly.class i poly$1.class
  • Ako možemo stvoriti takvu apstraktnu klasu, možemo stvoriti sučelje previše ... čudno ...


Je li moguće stvoriti primjerak apstraktne klase?

Ne, ne možemo. Možemo stvoriti anonimnu klasu (treću datoteku) i stvoriti njezinu instancu.


Što misliš o stvaranju superklase?

Apstraktni superklasa ne stvaramo mi , već java.

EDIT: zamolite ga da provjeri ovo

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

:

 false class my$1 class my$2 
29
06 дек. Odgovor dat od ncenerar Dec 06 2012-12-06 19:12 '12 u 19:12 2012-12-06 19:12

Možete samo odgovoriti u jednom retku.

Ne , nikada ne možete koristiti primjer klase Abstract.

No, ispitivač se još uvijek ne slaže, onda mu možete reći

sve što možete učiniti je stvoriti anonimni razred.

A, prema anonimnom razredu, klasa je deklarirana i instanca je stvorena na istom mjestu / liniji.

Stoga je moguće da će ispitivač biti zainteresiran za provjeru vaše razine povjerenja i koliko znate o PLO-u.

17
07 дек. Odgovor daje korisnik918477 07. prosinca. 2012-12-07 07:09 '12 u 7:09 2012-12-07 07:09

Tehnički dio je dobro pokriven u drugim odgovorima, a u osnovi završava s:
"On greši, ne zna, zamoli ga da se pridruži ovome, i sve će to biti očišćeno :)"

Željela bih se osvrnuti na činjenicu (koja je spomenuta u drugim odgovorima) da to može biti stresno pitanje i važno je sredstvo za mnoge anketare da saznaju više o vama i kako reagirate na teške i neuobičajene situacije. Dajući vam pogrešne kodove, vjerojatno je htio vidjeti imate li što protiv. Da saznate imate li povjerenja da se suočite sa starijima u ovakvim situacijama.

PS: Ne znam zašto, ali imam osjećaj da je ispitivač pročitao ovaj post.

17
07 апр. Odgovor dao Mixcels 07. \ T 2015-04-07 08:20 '15 u 8:20 2015-04-07 08:20

Apstraktne klase ne mogu se kreirati, ali mogu biti podklasa. Pogledajte ovu vezu

Najbolji primjer je

Iako kalendarska klasa ima apstraktnu metodu getInstance () , ali kad kažete Calendar calc=Calendar.getInstance();

calc se odnosi na instancu klase klase GregorianCalendar jer "GregorianCalendar proširuje kalendar "

Infact anonimni interni tip vam omogućuje da stvorite pod-klasu bez naziva apstraktne klase i instance.

13
03 дек. Odgovor je dan Abhi_Mishra 03 dec. 2012-12-03 12:14 '12 u 12:14 2012-12-03 12:14

Tehnički odgovor

Apstraktne klase se ne mogu stvarati - to je po definiciji i dizajnu.

Iz JLS-a, Poglavlje 8. Klase:

Imenovana klasa može biti deklarirana kao apstraktna (§8.1.1.1), a sažetak mora biti objavljen ako nije u potpunosti implementiran; takva klasa ne može biti instanca, ali se može proširiti podskupinama.

S JSE 6 java dokumenta za Classes.newInstance ():

InstantationException - ako ova klasa predstavlja apstraktnu klasu, sučelje, klasu niza, primitivni tip ili void; ili ako klasa nema null konstruktor; ili ako je instanca izrađena iz drugog razloga.

Možete, naravno, stvoriti konkretnu potklasu apstraktne klase (uključujući i anonimnu podklasu), a također i baciti tip objekta na apstraktni tip.

Različiti kut u ovome - Teamplay i društvena inteligencija:

Ovaj tehnički nesporazum često se događa u stvarnom svijetu kada se bavimo sofisticiranom tehnologijom i pravnim specifikacijama.

Vještine ljudi mogu biti važnije od tehničkih vještina. Ako ste konkurentni i agresivno pokušavate dokazati svoju stranu argumenta, onda ste možda teoretski u pravu, ali također možete napraviti dodatnu štetu u bitci / šteti "licu" / stvaranju neprijatelja, nego što to košta. Budite pomirljivi i razumjeti u rješavanju vaših razlika. Tko zna - možda ste “oboje u pravu”, ali ste smislili nešto drugačije značenje pojmova?

Tko zna - iako je malo vjerojatno, možda je intervjuer namjerno uveo malo sukoba / nesporazuma kako bi vas stavio u teško stanje i vidjeli kako se ponašate emocionalno i društveno. Budite ljubazni i konstruktivni s kolegama, slijedite savjete starijih i pratite nakon razgovora da riješite bilo koji problem / nesporazum - putem e-maila ili telefonom. Pokazuje da ste motivirani i detaljni.

11
18 марта '13 в 6:10 2013-03-18 06:10 odgovor je dao Glen Best 18. ožujka '13 u 6:10 2013-03-18 06:10

Dobro je poznato da abstract class ne može biti instanca, kao što su svi reagirali.

Kada program definira anonimnu klasu, kompajler zapravo stvara novu klasu s drugim imenom (ima predložak EnclosedClassName$n , gdje je n broj anonimne klase).

Dakle, ako dekompilirate ovu Java klasu, naći ćete kôd kao što je prikazano u nastavku:

my.class

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

poly $ 1.class (generirana klasa "anonimna klasa")

 class poly$1 extends my { } 

ploly.cass

 public class poly extends my { public static void main(String[] a) { my m = new poly.1(); // instance of poly.1 class NOT the abstract my class m.mymethod(); } } 
7
14 февр. Odgovor daje iTech 14. veljače. 2013-02-14 15:33 '13 u 15:33 2013-02-14 15:33

O apstraktnim satovima

  • Nije moguće stvoriti apstraktni objekt klase
  • Mogu stvoriti varijable (mogu se ponašati kao vrste podataka)
  • Ako dijete ne može nadjačati barem jednu apstraktnu metodu roditelja, tada dijete također postaje apstraktno
  • Nastava apstrakta je beskorisna bez predavanja djece.

Svrha apstraktne klase je da se ponaša kao baza. U hijerarhiji nasljeđivanja vidjet ćete apstraktne klase prema gore.

4
26 дек. odgovor je dan Priyankara 26. prosinca. 2013-12-26 13:43 '13 u 13:43 2013-12-26 13:43

Ne, ne možete stvoriti apstraktnu klasu. Stvaramo instancu samo anonimne klase. U apstraktnoj klasi deklariramo apstraktne metode i definiramo samo specifične metode.

4
04 янв. odgovor je dao vikas agrahari siječanj 04 2014-01-04 10:24 '14 u 10:24 2014-01-04 10:24

Možete reći:
ne možemo stvoriti instancu apstraktne klase, ali možemo koristiti ključnu riječ new za stvaranje instance anonimne klase jednostavnim dodavanjem {} kao implementacijskog tijela na kraju apstraktne klase.

3
25 нояб. odgovor je dao Eddy 25. studenog. 2015-11-25 15:31 '15 u 15:31 2015-11-25 15:31

Ne može se stvoriti instanca apstraktne klase. Ono što doista možete učiniti jest primijeniti neke uobičajene metode u apstraktnoj klasi i dopustiti drugima da implementiraju (apstraktno) svoje apstraktne prikaze i dopustiti određenom descenderu da ih implementira ovisno o njihovim potrebama. Tada možete napraviti tvornicu, koja vraća instancu ove apstraktne klase (zapravo njen izvođač). U tvornici ćete tada odlučiti koji će programer odabrati. To se zove tvornički uzorak dizajna:

  public abstract class AbstractGridManager { private LifecicleAlgorithmIntrface lifecicleAlgorithm; // ... more private fields //Method implemented in concrete Manager implementors abstract public Grid initGrid(); //Methods common to all implementors public Grid calculateNextLifecicle(Grid grid){ return this.getLifecicleAlgorithm().calculateNextLifecicle(grid); } public LifecicleAlgorithmIntrface getLifecicleAlgorithm() { return lifecicleAlgorithm; } public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) { this.lifecicleAlgorithm = lifecicleAlgorithm; } // ... more common logic and getters-setters pairs } 

Određeni izvođač bi trebao primjenjivati ​​samo metode koje su deklarirane kao apstraktne, ali će imati pristup logici implementiranoj u tim klasama u apstraktnoj klasi koja nije deklarirana kao sažetak:

 public class FileInputGridManager extends AbstractGridManager { private String filePath; //Method implemented in concrete Manager implementors abstract public Grid initGrid(); public class FileInputGridManager extends AbstractGridManager { private String filePath; //Method implemented in concrete Manager implementors abstract public Grid initGrid(); public Grid initGrid(String filePath) { List<Cell> cells = new ArrayList<>(); char[] chars; File file = new File(filePath); // for example foo.txt // ... more logic return grid; } } 

Zatim, tvornica izgleda ovako:

 public class GridManagerFactory { public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){ AbstractGridManager manager = null; // input from the command line if(args.length == 2){ CommandLineGridManager clManager = new CommandLineGridManager(); clManager.setWidth(Integer.parseInt(args[0])); clManager.setHeight(Integer.parseInt(args[1])); // possibly more configuration logic ... manager = clManager; } // input from the file else if(args.length == 1){ FileInputGridManager fiManager = new FileInputGridManager(); fiManager.setFilePath(args[0]); // possibly more method calls from abstract class ... manager = fiManager ; } //... more possible concrete implementors else{ manager = new CommandLineGridManager(); } manager.setLifecicleAlgorithm(lifecicleAlgorithm); return manager; } } 

Prijemnik AbstractGridManager nazvat će metode na njemu i dobiti logiku implementiranu u određenom descenderu (i djelomično u apstraktnim metodama klase), ne znajući koja je specifična implementacija primila. To je također poznato kao inverzija ili injekcija ovisnosti.

3
03 июня '14 в 19:11 2014-06-03 19:11 odgovor je dao Picrochole 03. lipnja 2014. u 19:11 2014-06-03 19:11

Proširenje klase ne znači da stvarate instancu klase. Zapravo, u vašem slučaju, vi stvarate instancu podklase.

Siguran sam da apstraktne klase ne dopuštaju pokretanje. Stoga bih rekao ne: ne možete stvoriti apstraktnu klasu. Ali možete ga proširiti / naslijediti.

Ne možete izravno stvoriti apstraktnu klasu. Ali to ne znači da ne možete indirektno dobiti instancu klase (i ne činiti se instancom izvorne apstraktne klase). Mislim da ne možete stvoriti instancu apstraktne orginalne klase, ali možete:

  • Napravite praznu klasu
  • Naslijedi ga od apstraktne klase.
  • Izvedite dervirani razred akcija

Tako dobivate pristup svim metodama i svojstvima apstraktne klase kroz instancu izvedene klase.

3
03 нояб. Odgovor je dao Steve Jobs 03 Nov. 2013-11-03 18:39 '13 u 6:39 2013-11-03 18:39

Ne, ne možemo stvoriti objekt apstraktne klase, ali stvorit ćemo referentnu varijablu apstraktne klase. Referentna varijabla koristi se za upućivanje na objekte izvedenih klasa (podklasa apstraktne klase)

Ovdje je primjer koji ilustrira ovaj koncept.

 abstract class Figure { double dim1; double dim2; Figure(double a, double b) { dim1 = a; dim2 = b; } // area is now an abstract method abstract double area(); } class Rectangle extends Figure { Rectangle(double a, double b) { super(a, b); } // override area for rectangle double area() { System.out.println("Inside Area for Rectangle."); return dim1 * dim2; } } class Triangle extends Figure { Triangle(double a, double b) { super(a, b); } // override area for right triangle double area() { System.out.println("Inside Area for Triangle."); return dim1 * dim2 / 2; } } class AbstractAreas { public static void main(String args[]) { // Figure f = new Figure(10, 10); // illegal now Rectangle r = new Rectangle(9, 5); Triangle t = new Triangle(10, 8); Figure figref; // this is OK, no object is created figref = r; System.out.println("Area is " + figref.area()); figref = t; System.out.println("Area is " + figref.area()); } } 

Ovdje vidimo da ne možemo stvoriti objekt tipa Slika, ali možemo stvoriti referentnu varijablu tipa Slika. Ovdje smo kreirali referentnu varijablu tipa Reference i referentnu varijablu klase Class, koja se odnosi na objekte klase Rectangle i Triangle.

1
21 апр. Odgovor daje Ketan G 21 Apr. 2015-04-21 22:06 '15 u 22:06 2015-04-21 22:06