Java의 상속으로 인해 얼마나 많은 객체가 생성됩니까?
세 가지 클래스가 있다고 가정 해 보겠습니다.
class A {
A() {
// super();
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
}
}
클래스 C의 인스턴스를 만들 때 슈퍼 클래스의 생성자를 호출합니다. 그래서, 생성되는 객체가 둘 이상입니까? 객체가 하나만 생성되면 super ()는 다른 클래스의 생성자와 어떻게 비슷합니까? super () 메서드는 내부적으로 객체를 생성합니까? 내가 아는 것은 생성자도 메서드라는 것입니다 (내가 틀렸을 수 있습니다).
내 질문은 다음과 같습니다.
- 이 경우 얼마나 많은 Object가 생성됩니까?
- 하나의 객체가 생성되면 Super ()는 내부적으로 부모 클래스 생성자를 어떻게 호출합니까?
좋은 질문입니다. 당신이 조사하는 것은 Java가 객체를 초기화 하는 방법 이며 관련된 여러 단계가 있습니다.
나는 생성자가 또한 방법이라는 것을 알고 있습니다 (아마 내가 틀렸을 수도 있습니다).
거의 맞습니다. 생성자는 특별한 방법입니다. 클래스 파일을 디 컴파일하면 생성자의 이름이 <init>
. <init>
예를 들어, 다른 방법과, 다르게 취급되는 키워드의 사용을 통해 제외하고 명시 적으로 호출 할 수 없습니다 new
나 super
. 이것은 매우 기본적이어서 Java 언어로 정의 된 것이 아니라 JVM 자체에서 구현됩니다.
이 경우 생성되는 Object 수입니다.
하나의 개체 ( C
.
C
추가적으로 동시에의 인스턴스이며 B
및의 인스턴스 A
이기도 Object
합니다.
하나의 객체가 생성되면 내부적
super()
으로 Parent class Constructor를 호출 하는 방법 입니다. Super가 부모 클래스 생성자를 호출하는 방법.
여기에서 초기화를 시작합니다. 초기화는 JVM이 객체의 새 인스턴스를 만들고 모든 멤버 값 (특정 클래스 및 수퍼 클래스의 값)을 설정하는 방법입니다. 관련된 여러 단계가 있습니다.
- 참조 된 모든 클래스를로드하고 해당 클래스를 초기화합니다. 클래스 초기화는 그 자체로 중요하지 않으므로 여기서는 다루지 않겠습니다. 읽을만한 가치가 있습니다.
A
,B
및 의 모든 멤버를 포함하는 인스턴스 멤버를 보유하기 위해 메모리 청크를 할당합니다C
. 참고 이것은 질문의 한 측면을 설명합니다. 기본 클래스와 하위 클래스의 생성자가 동일한 객체를 업데이트하거나 참조하는 방법- 모든 클래스의 인스턴스의 모든 멤버가 동일한 메모리 청크에 차례로 저장 됩니다.- 모든 구성원을 기본값으로 초기화합니다 . 예를 들어,
int
및float
회원 0 0.0f로 설정됩니다. 멤버 이니셜 라이저를 실행하거나 계산합니다. 예 :
private int a = 10; private int b = a * 5; private String c = Singleton.getInstance().getValue();
참고 (1) 멤버 초기화는 클래스에서 멤버가 선언 된 순서대로 엄격하게 발생합니다. 이는 선언의 뒷부분에있는 멤버에 대한 참조가 끊어짐을 의미합니다.
private int a = b * 5; // Forward reference; won't compile private int b = 10;
참고 (2) Java 에는 생성자가 실행 되기 전에 값을 초기화 하기 위해 임의의 코드를 실행하는 기능이 부족 합니다. 이 코드 블록은 선언 순서대로 엄격하게이 시점에서 다시 실행됩니다.
private int a; private int b = 1; { // Initization occurs after b but before c. // c cannot be referenced here at all int i = SomeClass.getSomeStatic(); a = i * 2; } private int c = 99;
의 생성자를 실행합니다
C
. 생성자는 수퍼 클래스에서 생성자를 직접 호출해야합니다. 그렇지 않으면 컴파일러가super()
생성자의 첫 번째 줄로 자동으로 추가 합니다. 이는 생성자가 순서대로 엄격하게 실행됨을 의미합니다.Object
A
B
C
이제 개체가 초기화되었으며 사용할 준비가되었습니다. 인스턴스 메서드를 사용하여 값을 초기화하면 위험한 작업을 수행 할 수 있습니다.
public class Wrong {
int a = getB(); // Don't do this!
int b = 10;
public int getB() {
return b;
}
}
여기서는 a
로 초기화됩니다 0
. 이는 getB()
호출 시점 에서 Java가의 값을 b
기본값 ( 0
)으로 지 웠지만 아직 10
초기화의 두 번째 단계에서로 설정하지 않았기 때문 입니다.
요약하면 객체는 하나 뿐이며 단계적으로 생성되고 초기화됩니다. 이러한 단계에서 개체는 정의에 따라 완전히 정의되지 않습니다.
하나의 개체 만 생성됩니다. 개체.
클래스 A가 B를 확장하면 모든 메서드와 변수가 클래스 A에 복사되는 것처럼 상상할 수 있습니다.
코드에서는 하나의 객체 만 생성되고 상위 클래스 생성자를 슈퍼 호출합니다.
개체 생성 증명 :
package one;
public class A {
public static A super_var;
public A() {
super_var = this;
System.out.println("Constrcutor of A invoked");
}
}
package two;
public class B extends A {
public static A sub_var;
public B() {
sub_var = this;
System.out.println("Constructor of B invoked");
}
public void confirm() {
if (sub_var == A.super_var)
System.out.println("There is only one object is created");
else
System.out.println("There are more than one object created");
}
public static void main(String Args[]) {
B x = new B();
x.confirm();
}
}
이것은 하나의 객체 만 생성된다는 것을 증명할 것입니다.
그리고 약 Super()
. 내가 부모 클래스 생성자를 호출한다는 것을 알고 있습니다. 그리고 각 생성자 Super()
는 코드에서 언급 한 것처럼 첫 번째 문으로 사용됩니다. 알 수 있도록
내부적으로 슈퍼 클래스 생성자를 호출하는 방법을 모르겠습니다.
이것이 당신이 프로그램에서 만든 instace 만 있다는 것을 이해하게하기를 바랍니다.
- 귀하의 경우에만 1 개의 객체가 생성됩니다.
- 서브 클래스 생성자가 호출되면 내부적으로 슈퍼 클래스의 생성자를 호출하여 슈퍼 클래스의 멤버를 초기화합니다.
생성자를 호출한다고해서 개체를 만드는 것은 아닙니다. 생성자를 호출 할 때 객체가 이미 생성 된 상태입니다. 객체는 먼저 JVM에 의해 생성됩니다 (즉 메모리가 힙에 할당 된 다음 생성자가 호출 됨).
생성자는 개체의 구성원을 초기화하기위한 것입니다.
수업은 내부적으로 다음과 같이 변환됩니다.
class A
{
A(){
super();
System.out.println("class A");
}
}
class B extends A{
B(){
super();
System.out.println("class B");
}
}
public class C extends B
{
public static void main(String args[])
{
C c = new C(); //Parent constructor will get call
}
}
이 경우 생성되는 Object 수입니다.
인스턴스는 하나, C
전화, super()
단지는 호출 생성자 의 부모 클래스 와 객체를 생성하지 않습니다
하나의 객체가 생성되면 내부적으로 Super ()가 Parent 클래스 Constructor를 호출하는 방식입니다. Super가 부모 클래스 생성자를 호출하는 방법.
C
의 인스턴스 를 만들 때 . C
'생성자가되는 첫 번째 전화, 호출되는 B
의 생성자,'차례로 호출에서 A
의 생성자
이 SO 답변에 따라 객체 할당의 역학을 살펴보면 new
연산자 를 사용 하면 명령문 당 하나의 객체 만 생성 된다는 것이 분명해야합니다 . 생성되는 개체가 하나뿐이라는 의심을 더 명확히하려면 다음 프로그램을 수행하십시오.
public class A {
public static int aInstanceCount=0;
public static A aInstance;
public String aInstanceVariable;
A() {
//Super();
aInstanceCount++;
aInstanceVariable="aInstanceVar";
System.out.println("class A");
aInstance=this;
}
}
class B extends A {
public static int bInstanceCount=0;
public static B bInstance;
public String bInstanceVariable;
B() {
//Super();
bInstanceCount++;
bInstanceVariable="bInstanceVar";
System.out.println("class B");
bInstance=this;
}
}
class C extends B {
public static void main(String args[]) {
int instanceCount=0;
C c = new C(); //Parent constructor will get call
if(A.aInstance!=null){
instanceCount++;
System.out.println("Value of aInstanceVariable: "+A.aInstance.aInstanceVariable);
}
if(B.bInstance!=null){
instanceCount++;
System.out.println("Value of bInstanceVariable: "+B.bInstance.bInstanceVariable);
}
A a=A.aInstance;
B b=B.bInstance;
System.out.println("bInstanceVariable of B earlier: " + B.bInstance.bInstanceVariable);
//Now we are changing the bInstanceVariable of c which is inherited from B
c.bInstanceVariable="bInstance After modified by C";
System.out.println("bInstanceVariable of B after: " + B.bInstance.bInstanceVariable);
System.out.println("aInstanceVariable of A earlier: " + A.aInstance.aInstanceVariable);
//Now we are changing the aInstanceVariable of c which is inherited from A
c.aInstanceVariable="aInstance After modified by C";
System.out.println("bInstanceVariable of A after: " + A.aInstance.aInstanceVariable);
}
}
출력 :
class A
class B
Value of aInstanceVariable: aInstanceVar
Value of bInstanceVariable: bInstanceVar
bInstanceVariable of B earlier: bInstanceVar
bInstanceVariable of B after: bInstance After modified by C
aInstanceVariable of A earlier: aInstanceVar
bInstanceVariable of A after: aInstance After modified by C
알 수 있다면 슈퍼 생성자는 서브 클래스 객체가 생성 될 때마다 암묵적으로 호출되지만 new
연산자는 한 번만 사용 되기 때문에 실제로 공간이 할당 된 객체는 하나뿐입니다. 그리고 aInstanceVariable
via C
객체 를 수정함으로써 c
우리는 실제로 aInstanceVariable
of aInstance
. 그래서 그것은 실제로 하나의 물체가 있다는 것을 분명히 증명합니다.
객체를 생성하기 위해 생성자를 호출 할 때 객체 생성 단계 :
init를 사용한 메모리 할당 이 완료되었습니다. 이 초기화는 객체 생성을 위해 메모리를 할당하기 위해 시스템 호출을 합니다.
그런 다음 생성자가 호출되어 객체의 필드를 초기화합니다.
그런 다음 슈퍼 클래스 생성자 (슈퍼 클래스가있는 경우)를 호출하고 1 ~ 3 단계를 반복합니다.
javap를 사용하여 클래스 파일을 디 컴파일 할 때 표시되는 내용은 수행해야 할 다른 호출을 보여줍니다. init 는 메모리 할당을 초기화하기 위해 시스템 호출을하지만 생성자의 코드가 실행될 때 객체의 필드가 초기화됩니다.
GC 당시 다형성 / 재정의가 어떻게 작동하는지 잘 모르겠습니다.
그러나 finalize
모든 클래스에서 메서드 를 재정의 하고 JVM이 주 메서드를 종료 할 때 확인하는 것이 좋습니다.
C
객체 만 생성 된 경우finalize
'C'를 호출해야합니다 .- 모든 경우
A
,B
,C
객체가 생성, 그것은 호출해야합니다finalize
위해A
,B
,C
.
신청할 수있는 가장 간단한 수표라고 생각합니다.
class A {
A() {
//Super();
System.out.println("class A");
}
public void finalize(){
System.out.println("Class A object destroyed");
}
}
class B extends A {
B() {
//Super();
System.out.println("class B");
}
public void finalize(){
System.out.println("Class B object destroyed");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get call
}
public void finalize(){
System.out.println("Class C object destroyed");
}
}
이전에 게시 된 답변에 동의하지만이 문제에 대한 최종 권한 인 Java 언어 사양에 대한 참조를 추가하고 싶습니다.
표현식 new C()
은 "클래스 인스턴스 생성 표현식"입니다. 섹션 15.9.4 클래스 인스턴스 생성 표현식 의 런타임 평가 에서는 객체 생성과 관련된 런타임 단계를 설명합니다. "객체"를 참조하고 공간을 한 번만 할당하지만 "다음에 지정된 클래스 유형의 선택된 생성자가 호출됩니다. 이로 인해 클래스 유형의 각 수퍼 클래스에 대해 하나 이상의 생성자가 호출됩니다."라고 표시됩니다.
이 모든 것은 새로운 객체를 생성하는 것과 생성자를 호출하는 것을 구별함으로써 훨씬 더 명확 해집니다. 생성자를 호출하는 것은 객체 생성의 일부, 이니셜 라이저를 실행하는 부분, 수퍼 클래스 생성자 및 생성자의 본문 만 수행합니다. C도 B이기 때문에 B 생성자는 C를 만드는 동안 실행되어야합니다.
super 키워드를 사용하면 하위 클래스가 해당 수퍼 클래스의 메서드와 필드를 호출 할 수 있습니다. 이것은 수퍼 클래스 객체의 인스턴스가 아니라 참조 할 메서드 나 필드를 컴파일러에 알리는 방법입니다. 효과는 서브 클래스가 자체 메서드 중 하나를 호출하는 것과 같습니다. 예 :
수퍼 클래스 Person을 확장하는 하위 클래스 Employee를 고려하십시오.
public class Employee extends Person{
public Employee()
{
//reference the superclass constructor
super();
}
public String getName()
{
//reference superclass behaviors
return super.getFirstName() + " " + super.getLastName();
}
}
super 키워드는 Person 클래스의 생성자 또는 액세스 권한이있는 모든 비헤이비어 또는 필드 (예 : getFirstName () 및 getLastName ())를 참조하는 데 사용할 수 있습니다.
Case One 개체가 생성됩니다.
다음을 수행하는 동안이 super ()는 컴파일러에서 암시 적으로 제공합니다.
class A { A() { System.out.println("class A"); } } class B extends A { B() { System.out.println("class B"); } } class C extends B { public static void main(String args[]) { C c = new C(); // } }
메서드 내에서 super ()를 호출하는 것과 비슷합니다.
B() {
super();
System.out.println("class B");
}
super 키워드는 현재 클래스에서 메서드가 재정의되었지만 슈퍼 클래스 메서드를 호출하려는 경우에도 사용할 수 있습니다.
super ()는 모든 생성자가 하나의 클래스를 참조하도록합니다. (쉽게 이해할 수 있도록 : 모든 멤버 함수가 같은 클래스에있는 것과 마찬가지로) 모든 생성자 메서드 만 호출합니다.
따라서 생성자 만 호출하는 작업을 수행 했으므로 super ()는 객체 생성을 수행하지 않습니다. 멤버 함수를 참조하는 것뿐입니다.
How many number of Object is created in this case.
When you create an instance of Class C by C cInstance = new C();
a single instance(Object) of Class C is creates(None of A and B). However since C extends B and B extends A, C will have all the methods of Class A and B(Actually depends on access modifiers used but lets say for this case they are public or default).
If one object is created then how internally Super() is calling Parent class Constructor
. How Super is able to call parent class constructor.
That is how inheritance works. When a new object is created it will call it's super class constructor and that super class will call it's super class constructor and so on. In other ordinary function you have to explicitly call super(). So calling super class constructor goes bottom-up fashion while execution goes top-down fashion of the inheritance hierarchy tree
If you add one more line of Code System.out.println(this.hashCode())
will remove your confusion.
Here in All Case hashCode()
will print same hashCode
all the time. It means there is one and only one unique Object
is Created.
class A {
A() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class A");
}
}
class B extends A {
B() {
// super();
System.out.println(this.hashCode()); // it will print 2430287
System.out.println("class B");
}
}
class C extends B {
public static void main(String args[]) {
C c = new C(); //Parent constructor will get called
System.out.println(this.hashCode()); // it will print 2430287
}
}
but there is two Constructor is getting invoked to initialize the Parent
member variable. I think if you know the concept of super()
keyword which invokes the Constructor of parent
Class and Initialize the member Variable of parent
Class.
3 constructors will call
Code:
class A
{
A()
{
System.out.println("In A");
}
}
class B extends A
{
B()
{
System.out.println("In B");
}
}
class C extends B
{
C()
{
System.out.println("In C");
}
}
public class InheritanceTest {
public static void main(String args[])
{
C c1=new C();
}
}
Output:
In A
In B
In C
ReferenceURL : https://stackoverflow.com/questions/17877615/how-many-objects-are-created-due-to-inheritance-in-java
'programing' 카테고리의 다른 글
ID에 마침표가 포함 된 경우 ApiController가 404를 반환합니다. (0) | 2021.01.15 |
---|---|
Facebook 페이지에 대한 "만료되지 않는"액세스 토큰 생성 (0) | 2021.01.15 |
Django에서 HTTP 400 응답을 반환하는 방법은 무엇입니까? (0) | 2021.01.15 |
Entity Framework 7 데이터베이스 우선 POCO 생성기가 있습니까? (0) | 2021.01.15 |
slf4j-log4j12와 log4j-over-slf4j의 차이점 (0) | 2021.01.15 |