인터뷰 중 하나에서 “추상 수업을 인스턴스화 할 수 있을까요?”라는 질문을 받았습니다.
답장은 “아니요.”라고 대답했습니다. 그러나 면접관은 “잘못, 우리는 할 수있다”고 말했다.
나는 이것에 대해 조금 논쟁했다. 그런 다음 집에서 직접 해보라고했습니다.
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
여기에서는 클래스의 인스턴스를 만들고 추상 클래스의 메서드를 호출합니다. 누구든지 나에게 이것을 설명해 주시겠습니까? 인터뷰 중에 정말 잘못 되었습니까?
답변
여기, 내 수업의 인스턴스를 만들고 있습니다
아니요, 여기서 추상 클래스의 인스턴스를 만들지 않습니다. 오히려 추상 클래스 의 익명 서브 클래스 인스턴스를 작성하는 것 입니다. 그런 다음 추상 클래스 참조에서 하위 클래스 객체를 가리키는 메소드를 호출 합니다 .
이 동작은 JLS 섹션 15.9.1 에 명확하게 나와 있습니다 .
클래스 인스턴스 작성 표현식이 클래스 본문으로 끝나면 인스턴스화되는 클래스는 익명 클래스입니다. 그때:
- T가 클래스를 나타내는 경우 T로 명명 된 클래스의 익명 직접 서브 클래스가 선언됩니다. T로 표시된 클래스가 최종 클래스 인 경우 컴파일 타임 오류입니다.
- T가 인터페이스를 나타내는 경우 T로 명명 된 인터페이스를 구현하는 Object의 익명 직접 서브 클래스가 선언됩니다.
- 두 경우 모두 서브 클래스의 본문은 클래스 인스턴스 작성 표현식에 제공된 ClassBody입니다.
- 인스턴스화되는 클래스는 익명 서브 클래스입니다.
강조합니다.
또한 JLS 섹션 12.5 에서 객체 생성 프로세스 에 대해 읽을 수 있습니다 . 여기에서 하나의 진술을 인용하겠습니다 :-
새 클래스 인스턴스가 작성 될 때마다 클래스 유형에 선언 된 모든 인스턴스 변수 및 클래스 유형의 각 수퍼 클래스에 선언 된 모든 인스턴스 변수 (숨겨 질 수있는 모든 인스턴스 변수 포함)를위한 공간이있는 메모리 공간이 할당됩니다.
새로 작성된 오브젝트에 대한 참조가 결과로 리턴되기 직전에 표시된 생성자가 다음 프로 시저를 사용하여 새 오브젝트를 초기화하도록 처리됩니다.
내가 제공 한 링크에서 전체 절차에 대해 읽을 수 있습니다.
실제로 인스턴스화되는 클래스가 Anonymous SubClass 임을 확인하려면 두 클래스를 모두 컴파일하면됩니다. 해당 클래스를 두 개의 다른 파일에 넣었다고 가정하십시오.
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();
}
}
이제 두 소스 파일을 모두 컴파일하십시오.
javac My.java Poly.java
이제 소스 코드를 컴파일 한 디렉토리에 다음 클래스 파일이 표시됩니다.
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
해당 클래스를 참조하십시오 Poly$1.class
. 아래 코드를 사용하여 인스턴스화 한 익명 서브 클래스에 해당하는 컴파일러가 생성 한 클래스 파일입니다.
new My() {};
따라서 다른 클래스가 인스턴스화되고 있음이 분명합니다. 단지 그 클래스에는 컴파일러가 컴파일 한 후에 만 이름이 지정됩니다.
일반적으로 클래스의 모든 익명 서브 클래스는 다음과 같은 방식으로 이름이 지정됩니다.
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
이 숫자는 해당 익명 클래스가 묶는 클래스에 나타나는 순서를 나타냅니다.
답변
위의 클래스는 my
추상 클래스 의 서브 클래스 인 익명의 내부 클래스를 인스턴스화합니다 . 추상 클래스 자체를 인스턴스화하는 것과 완전히 동일하지는 않습니다. OTOH, 모든 서브 클래스 인스턴스는 모든 수퍼 클래스 및 인터페이스의 인스턴스이므로 대부분의 추상 클래스는 실제로 구체적인 서브 클래스 중 하나를 인스턴스화하여 인스턴스화됩니다.
면접관이 방금 “잘못!” 설명하지 않고이 예제를 고유 한 반례로 제시했지만, 그는 자신이 무엇을 말하는지 모른다고 생각합니다.
답변
= my() {};
은 객체의 간단한 인스턴스화가 아닌 익명의 구현이 있음을 의미합니다 = my()
. 추상 클래스를 인스턴스화 할 수 없습니다.
답변
당신이 할 수있는 관찰 :
- 왜
poly
연장my
되나요? 이건 쓸모 없다 … - 편집 결과는 무엇입니까? 세 개의 파일 :
my.class
,poly.class
및poly$1.class
- 우리가 그런 추상 클래스를 인스턴스화 할 수 있다면 인터페이스도 인스턴스화 할 수 있습니다 … 이상한 …
추상 클래스를 인스턴스화 할 수 있습니까?
아니요, 우리는 할 수 없습니다. 우리가 할 수있는 일은 익명 클래스 (세번째 파일)를 만들고 인스턴스화하는 것입니다.
슈퍼 클래스 인스턴스화는 어떻습니까?
추상 슈퍼 클래스는 우리 가 아닌 자바에 의해 인스턴스화됩니다 .
편집 : 그를 테스트하도록 요청
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
답변
한 줄로 간단히 대답 할 수 있습니다.
아니요 , 추상 클래스를 인스턴스화 할 수 없습니다.
그러나 면접관은 여전히 동의하지 않습니다. 그러면 말할 수 있습니다.
익명 클래스를 만들 수 있습니다.
그리고 Anonymous 클래스에 따르면 클래스 는 동일한 장소 / 라인에서 선언되고 인스턴스화됩니다.
따라서 면접관은 자신의 신뢰 수준과 OOP에 대해 얼마나 많이 알고 있는지 관심이있을 수 있습니다.
답변
기술 부분은 다른 답변에서 잘 다루어졌으며 주로
“그는 잘못 되었습니다. 그는 물건을 알지 못하고 그에게 가입하여 모든 것을 지우십시오 :)”
나는 이것이 다른 질문에 언급되었을 것이라는 사실을 강조 하고 싶습니다. 이것은 스트레스 질문 일 수 있으며 많은 면접관이 당신에 대해 더 많이 알 수있는 중요한 도구이며 어렵고 특이한 상황에 어떻게 대처 하는가입니다. 당신에게 잘못된 코드를 제공함으로써, 아마도 당신이 말다툼했는지를 알고 싶었을 것입니다 . 이와 비슷한 상황에서 선배들과 대항 할 자신이 있는지를 알기 위해.
추신 : 이유를 모르겠지만 면접관이이 게시물을 읽은 느낌이 있습니다.
답변
추상 클래스는 인스턴스화 할 수 없지만 서브 클래스화할 수 있습니다. 이 링크를보십시오
가장 좋은 예는
하지만 캘린더 클래스) (추상 메소드의 getInstance를 가지고 ,하지만 당신은 때를 말한다Calendar calc=Calendar.getInstance();
calc는 “GregorianCalendar extends Calendar “로 GregorianCalendar 클래스의 클래스 인스턴스를 참조합니다.
사실 익명의 내부 유형을 사용하면 추상 클래스의 이름없는 서브 클래스 와이 인스턴스 를 만들 수 있습니다 .