왜 this()와 super()가 컨스트럭터의 첫 번째 문이어야 합니까?
Java는 컨스트럭터에서 this() 또는 super()를 호출할 경우 첫 번째 문이어야 합니다.왜일까요?
예를 들어 다음과 같습니다.
public class MyClass {
public MyClass(int x) {}
}
public class MySubClass extends MyClass {
public MySubClass(int a, int b) {
int c = a + b;
super(c); // COMPILE ERROR
}
}
Sun 컴파일러는 "call to super는 컨스트럭터의 첫 번째 문이어야 한다"고 말합니다.Eclipse 컴파일러는 "컨스트럭터 호출은 컨스트럭터의 첫 번째 문이어야 합니다."라고 말합니다.
단, 코드를 약간 재배치하면 이 문제를 회피할 수 있습니다.
public class MySubClass extends MyClass {
public MySubClass(int a, int b) {
super(a + b); // OK
}
}
다음으로 다른 예를 제시하겠습니다.
public class MyClass {
public MyClass(List list) {}
}
public class MySubClassA extends MyClass {
public MySubClassA(Object item) {
// Create a list that contains the item, and pass the list to super
List list = new ArrayList();
list.add(item);
super(list); // COMPILE ERROR
}
}
public class MySubClassB extends MyClass {
public MySubClassB(Object item) {
// Create a list that contains the item, and pass the list to super
super(Arrays.asList(new Object[] { item })); // OK
}
}
따라서 슈퍼 콜 전에 로직을 실행하는 것을 막는 것은 아닙니다.하나의 표현에 들어갈 수 없는 논리를 실행하지 못하게 할 뿐입니다.
요.this()
컴파일러가 "이것에 대한 호출은 컨스트럭터의 첫 번째 문이어야 합니다."고고말말말말다다
컴파일러에 이러한 제한이 있는 이유는 무엇입니까?컴파일러에 이 제한이 없다면 뭔가 나쁜 일이 발생할 수 있는 코드 예를 들어 주시겠습니까?
상위 클래스의 생성자를 하위 클래스의 생성자보다 먼저 호출해야 합니다.이렇게 하면 컨스트럭터의 부모 클래스에서 메서드를 호출할 경우 부모 클래스가 이미 올바르게 설정되어 있습니다.
에 전달하려고 에 전달하면 됩니다.super
:
public MySubClassB extends MyClass {
public MySubClassB(Object[] myArray) {
super(myArray);
}
}
컴파일러가 이것을 실시하지 않는 경우는, 다음과 같이 할 수 있습니다.
public MySubClassB extends MyClass {
public MySubClassB(Object[] myArray) {
someMethodOnSuper(); //ERROR super not yet constructed
super(myArray);
}
}
부모 클래스에 디폴트컨스트럭터가 있는 경우 슈퍼 콜은 컴파일러에 의해 자동으로 삽입됩니다.는 Java에서 입니다.Object
이것은 컴파일러에 의한 super()의 자동 삽입에 의해 가능하게 됩니다.를 먼저이 올바른 - - ->는 Child of Child입니다
컨스트럭터와 정적 방법을 연결함으로써 이 문제를 해결할 방법을 찾았습니다.제가 하고 싶었던 일은 다음과 같습니다.
public class Foo extends Baz {
private final Bar myBar;
public Foo(String arg1, String arg2) {
// ...
// ... Some other stuff needed to construct a 'Bar'...
// ...
final Bar b = new Bar(arg1, arg2);
super(b.baz()):
myBar = b;
}
}
따라서 기본적으로 생성자 매개 변수를 기반으로 개체를 구성하고, 개체를 멤버에 저장하며, 해당 개체에 대한 메서드의 결과를 슈퍼 생성자로 전달합니다.멤버를 기말고사로 만드는 것 또한 수업의 특성상 불변하기 때문에 상당히 중요했다.실제로 막대를 구축하려면 중간 개체가 몇 개 필요하므로 실제 사용 사례에서는 한 줄로 줄일 수 없습니다.
결국엔 이렇게 만들었죠.
public class Foo extends Baz {
private final Bar myBar;
private static Bar makeBar(String arg1, String arg2) {
// My more complicated setup routine to actually make 'Bar' goes here...
return new Bar(arg1, arg2);
}
public Foo(String arg1, String arg2) {
this(makeBar(arg1, arg2));
}
private Foo(Bar bar) {
super(bar.baz());
myBar = bar;
}
}
법률 코드. 슈퍼 컨스트럭터를 호출하기 전에 여러 개의 스테이트먼트를 실행하는 작업을 수행합니다.
JLS가 그렇게 말하니까JLS를 호환 가능한 방법으로 변경할 수 있습니까?네.
그러나, 그것은 이미 충분히 복잡한 언어 사양을 복잡하게 만들 것입니다. 유용하지 않으며 가지 로 다른 합니다).this(fn())
- 다른 、 른른 、 다super 、 라supersuper ( Super Constructor ) 。따라서 변경 시 중량 대비 검정력 비율은 좋지 않습니다.
이 규칙만으로는 슈퍼클래스가 구축을 완료하기 전에 필드를 사용할 수 없습니다.
이러한 불법 사례를 생각해 보십시오.
super(this.x = 5);
super(this.fn());
super(fn());
super(x);
super(this instanceof SubClass);
// this.getClass() would be /really/ useful sometimes.
이 예는 합법적이지만 "잘못된" 것입니다.
class MyBase {
MyBase() {
fn();
}
abstract void fn();
}
class MyDerived extends MyBase {
void fn() {
// ???
}
}
위의 예에서는 다음과 같습니다.MyDerived.fn
한 .MyDerived
컨스트럭터에서는, 이 툴에 대해서 슬레쉬 할 필요가 있습니다.ThreadLocal
;(.;)
1.4 "Java 1.4"를 입니다.this
내부 클래스 슈퍼 컨스트럭터를 호출하기 전에 할당됩니다.에 특이하게 .NullPointerException
이전 버전을 대상으로 컴파일된 코드의 이벤트.
또한 안전하지 않은 출판물이 있는 경우, 예방 조치를 취하지 않는 한 다른 스레드로 공사를 다시 볼 수 있습니다.
2018년 3월 편집: Records: construction and validation 메시지에서 Oracle은 이 제한을 제거할 것을 제안합니다(단, C#과 달리,this
컨스트럭터 체인을 하기 전에 확실하게 할당 해제(DU)됩니다.
지금까지 this() 또는 super()는 컨스트럭터의 선두여야 합니다.이 제한은 결코 대중적이지 않았고 자의적으로 인식되었다.이 제한에는 호출특성의 검증을 포함한 여러 가지 미묘한 이유에는 호출특수는 이러한 제한에 기여하였다.수년간 NAT은 이러한 문제를 VM 레벨에서 해결해 왔으며, 레코드뿐만 아니라 모든 컨스트럭터에 대해 이 제한을 해제하는 방안을 검토하는 것이 현실화될 때까지 해결했습니다.
단순히 이것이 상속 철학이기 때문이다.Java 언어 사양에 따르면 컨스트럭터의 본문은 다음과 같이 정의됩니다.
ConstructorBody: {ExplicitConstructor}호출optopt BlockStatements }
생성자 본문의 첫 번째 문장은 다음 중 하나일 수 있습니다.
- (키워드 "this"를 사용하여) 같은 클래스의 다른 생성자를 명시적으로 호출한다.
- 직접 슈퍼클래스의 명시적 호출(키워드 「super」를 사용)
컨스트럭터 본문이 명시적인 컨스트럭터 호출로 시작하지 않고 선언되는 컨스트럭터가 원시 클래스 객체의 일부가 아닌 경우 컨스트럭터 본문은 인수를 받지 않는 직접 슈퍼 클래스의 컨스트럭터 호출 "super();"로 암묵적으로 시작됩니다.기타 등등..오브젝트 컨스트럭터 전체를 오브젝트 컨스트럭터라고 부릅니다.Java 플랫폼의 모든 클래스는 오브젝트의 하위 클래스입니다.이것은 "컨스트럭터 체인"이라고 불립니다.
왜왜??
Java가 Constructor Body를 이렇게 정의한 이유는 객체의 계층을 유지해야 하기 때문입니다.상속의 정의를 기억한다.수업을 연장하고 있어요.그렇다고 해서 존재하지 않는 것을 확장할 수는 없다.베이스(슈퍼클래스)를 먼저 만든 다음 베이스(서브클래스)를 파생할 수 있습니다.그래서 부모반과 자녀반이라고 불렀어요부모 없이는 아이를 가질 수 없어요
기술 수준에서는 하위 클래스가 부모로부터 모든 멤버(필드, 메서드, 중첩된 클래스)를 상속합니다.또한 컨스트럭터는 멤버가 아니기 때문에 오브젝트에 속하지 않습니다.오브젝트 작성)을 담당하므로 서브클래스에 의해 상속되지 않지만 호출할 수 있습니다.그리고 오브젝트 작성 시 컨스트럭터 1개만 실행되기 때문에서브클래스 오브젝트를 작성할 때 어떻게 슈퍼클래스를 만들 수 있을까요?따라서 "컨스트럭터 체인"의 개념은 현재 컨스트럭터 내에서 다른 컨스트럭터(즉 슈퍼)를 호출할 수 있습니다.그리고 Java는 이 호출을 하위 클래스 생성자의 첫 번째 행으로 하여 계층을 유지하고 보장해야 했습니다.부모 오브젝트를 명시적으로 먼저 작성하지 않은 경우(예를 들어 잊어버린 경우) 암묵적으로 작성한다고 가정합니다.
이 검사는 컴파일 중에 수행됩니다.그러나 런타임에 무슨 일이 일어날지, 런타임에 어떤 오류가 발생할지 알 수 없습니다. 만약 Java가 기본 컨스트럭터를 첫 번째 줄부터가 아니라 서브클래스의 컨스트럭터 중간에서 실행하려고 할 때 컴파일 오류를 발생시키지 않는다면...
(Java Specification에 익숙한 사람들은) (a) 부분적으로 구성된 오브젝트를 사용할 수 없도록 하고 (b) 부모 클래스의 컨스트럭터를 "새로" 오브젝트에 구축하도록 강요하는 것을 방지하기 위한 것이라고 확신합니다.
「나쁜」의 예는 다음과 같습니다.
class Thing
{
final int x;
Thing(int x) { this.x = x; }
}
class Bad1 extends Thing
{
final int z;
Bad1(int x, int y)
{
this.z = this.x + this.y; // WHOOPS! x hasn't been set yet
super(x);
}
}
class Bad2 extends Thing
{
final int y;
Bad2(int x, int y)
{
this.x = 33;
this.y = y;
super(x); // WHOOPS! x is supposed to be final
}
}
왜 그랬냐고 물었더니, 다른 대답은 왜 슈퍼 건설업자에게 전화하는 것이 좋은지 말하지 마세요. 첫 번째 줄에 전화하는 경우에만요.그 이유는 당신이 실제로 건설업자에게 전화하지 않았기 때문입니다.C++에서는 동등한 구문은 다음과 같습니다.
MySubClass: MyClass {
public:
MySubClass(int a, int b): MyClass(a+b)
{
}
};
되기 전에 멤버 에 실행됩니다.나머지 생성자 중 하나가 실행되기 전에 실행되며 실제로 구성원 변수가 초기화되기 전에 실행됩니다.자바어생성자가 실제로 시작되기 전에 하위 클래스의 구성원이 초기화되기 전에 일부 코드(다른 생성자)를 실행할 수 있습니다. '예: '콜'을 붙입니다).super
를 첫 줄에 어떤에서는 그렇게 되어 있다.super
★★★★★★★★★★★★★★★★★」this
첫 번째 오픈브레이스 앞입니다.다음에 입력해도 모든 것이 완전히 구성되기 전에 실행되기 때문입니다.)의 기타 (예: " " " " )int c = a + b;
가 "할 수 있습니다라고 말하도록 .그럼 모든 것을 초기화할 수 있습니다."라고 말하도록 합니다.따라서 슈퍼클래스나 멤버 등이 실행되어 초기화되며 오픈브레이스 후에 코드 실행이 시작됩니다.
몇 줄 후에 "이 개체를 구성할 때 기본 클래스의 생성자에게 전달했으면 하는 매개 변수가 있습니다."라는 코드를 만나면, 이미 늦었고 의미가 없습니다.컴파일러 에러가 표시됩니다.
따라서 슈퍼 콜 전에 로직을 실행하는 것을 막는 것은 아닙니다.하나의 표현에 들어갈 수 없는 논리를 실행하지 못하게 할 뿐입니다.
실제로는 여러 expessions를 사용하여 로직을 실행할 수 있습니다.정적인 함수로 코드를 랩하고 슈퍼스테이트먼트로 호출하기만 하면 됩니다.
예를 들어 다음과 같습니다.
public class MySubClassC extends MyClass {
public MySubClassC(Object item) {
// Create a list that contains the item, and pass the list to super
super(createList(item)); // OK
}
private static List createList(item) {
List list = new ArrayList();
list.add(item);
return list;
}
}
전적으로 동의해요, 제한이 너무 심해요.스태틱 도우미 메서드(Tom Hawtin - tackline 권장)를 사용하거나 모든 "pre-super() computations"를 파라미터의 단일 식에 삽입하는 것이 항상 가능한 것은 아닙니다.예를 들어 다음과 같습니다.
class Sup {
public Sup(final int x_) {
//cheap constructor
}
public Sup(final Sup sup_) {
//expensive copy constructor
}
}
class Sub extends Sup {
private int x;
public Sub(final Sub aSub) {
/* for aSub with aSub.x == 0,
* the expensive copy constructor is unnecessary:
*/
/* if (aSub.x == 0) {
* super(0);
* } else {
* super(aSub);
* }
* above gives error since if-construct before super() is not allowed.
*/
/* super((aSub.x == 0) ? 0 : aSub);
* above gives error since the ?-operator's type is Object
*/
super(aSub); // much slower :(
// further initialization of aSub
}
}
Carson Myers가 제안한 바와 같이 "아직 구성되지 않은 객체" 예외를 사용하는 것이 도움이 되지만, 각 객체 생성 중에 이를 체크하면 실행 속도가 느려집니다.언어 사양을 복잡하게 해도 (불명확하게 if-statement를 금지하지만 파라미터 내에서 ?-operator를 허용하는 대신) 더 나은 차별화를 만드는 Java 컴파일러를 선호합니다.
걱정거리를 찾았어요.
컴파일되지 않음:
public class MySubClass extends MyClass {
public MySubClass(int a, int b) {
int c = a + b;
super(c); // COMPILE ERROR
doSomething(c);
doSomething2(a);
doSomething3(b);
}
}
이 방법은 다음과 같습니다.
public class MySubClass extends MyClass {
public MySubClass(int a, int b) {
this(a + b);
doSomething2(a);
doSomething3(b);
}
private MySubClass(int c) {
super(c);
doSomething(c);
}
}
자바 코드를 처리하는 도구를 쓰는 사람들의 삶을 쉽게 하기 위해서라고 생각합니다.또 자바 코드를 읽고 있는 사람들의 생활도 조금 줄었습니다.
「 」를하면,super()
★★★★★★★★★★★★★★★★★」this()
을 사용하다를 들어, 「」, 「」를 ,super()
★★★★★★★★★★★★★★★★★」this()
로 if()
할 수 해야 할 수도 .super()
else
있을 super()
2회 사용super()
★★★★★★★★★★★★★★★★★」this()
「 」. 「 」까지, 하지 않을 경우가 있습니다.super()
★★★★★★★★★★★★★★★★★」this()
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★♪
모든 사람에게 이 추가 작업을 시키는 것은 이익보다 비용이 더 많이 드는 것처럼 보였다.
컴파일러에 이 제한이 없다면 뭔가 나쁜 일이 발생할 수 있는 코드 예를 들어 주시겠습니까?
class Good {
int essential1;
int essential2;
Good(int n) {
if (n > 100)
throw new IllegalArgumentException("n is too large!");
essential1 = 1 / n;
essential2 = n + 2;
}
}
class Bad extends Good {
Bad(int n) {
try {
super(n);
} catch (Exception e) {
// Exception is ignored
}
}
public static void main(String[] args) {
Bad b = new Bad(0);
// b = new Bad(101);
System.out.println(b.essential1 + b.essential2);
}
}
구성 중 예외는 거의 항상 구성 중인 개체를 제대로 초기화할 수 없으며, 현재 잘못된 상태에 있으며 사용할 수 없으며 가비지 수집 상태여야 함을 나타냅니다.그러나 서브클래스의 컨스트럭터는 슈퍼클래스 중 하나에서 발생한 예외를 무시하고 부분적으로 초기화된 개체를 반환할 수 있습니다.에서는 에 new Bad()
나 둘 다 0 이거나 하지 .essential1
않다essential2
가 올바르게 초기화되어 있습니다.
당신은 예외를 무시하는 것이 항상 나쁜 생각이라고 말할 수 있다.다음은 또 다른 예입니다.
class Bad extends Good {
Bad(int n) {
for (int i = 0; i < n; i++)
super(i);
}
}
재미있네요, 그렇지 않나요?이 예에서는 몇 개의 개체를 만들고 있습니까?1개? 2개?아니면 아무것도...
" " 를 할 수 .super()
★★★★★★★★★★★★★★★★★」this()
도도의상상상상상상열열겁
「」, 「」에의에, 부분을 가 있는 것은 자주 하고 있습니다.super()
★★★★★★★★★★★★★★★★★」this()
. 은 것은, 이이 on on on on on에 하지 않는 일 수 this
하지만, 까지는 순서대로 할 수 ).super()
★★★★★★★★★★★★★★★★★」this()
(서양속담, 친구속담)로 콜 도 있을 수 super()
★★★★★★★★★★★★★★★★★」this()
그 이후에는 필요할 것이다.
이 경우 다음과 같은 기회가 있습니다.
- 이 답변에서 제시된 패턴을 사용하여 제한을 회피할 수 있습니다.
- 이 사전 를 허용할 .
super()
사전 준비this()
어디에 으로 할 수 있습니다. 그것은 어느 장소에 제한을 가함으로써 행해질 수 있습니다.super()
★★★★★★★★★★★★★★★★★」this()
컨스트럭터에서발생할 수 있습니다.사실, 오늘 컴파일러의 정도에 충분히 안전하게 생성자의 초에 정적 코드 추가할 수 있도록 하기 좋고 나쁜(또는 잠재적으로 나쁜)사건을 구별할 수 있다.실제로 오늘날의 컴파일러조차도 컨스트럭터의 시작 부분에서 정적 코드 추가를 안전하게 허용할 수 있는 정도로 좋은 경우와 나쁜 경우(또는 잠재적으로 나쁜 경우)를 구별할 수 있습니다.사실상, 그 과연,라고 가정해 보자를 가정하고 있다.super()
★★★★★★★★★★★★★★★★★」this()
반환 돌아가다this
기준 그리고 차례로, 당신의 생성자 has참조할 수 있고,그 결과,당신의 컨스트럭터는.
return this;
마지막에.컴파일러는 코드를 거부합니다.
public int get() {
int x;
for (int i = 0; i < 10; i++)
x = i;
return x;
}
public int get(int y) {
int x;
if (y > 0)
x = y;
return x;
}
public int get(boolean b) {
int x;
try {
x = 1;
} catch (Exception e) {
}
return x;
}
오류를"변수 x초기화되지 않았을 것" 해서 너무 에러 「initialized) 아니initialized」가 발생했을 경우,수 있습니다 할다음과 같이에서 할 수 있다.this
그것에 단지 다른 지역 variable.variable을 지정하면 다른로컬변수와 마찬가지로 체크합니다에 같은 변수,이 조사합니다.유일한 차이점유일한은차이점은this
어떤 수단 이외의수단으로는할당할 수 없다보다 다른에 의해 배정될 수 없습니다.super()
또는 또는this()
(이고, 여느 때처럼, 만약 생성자도 그런 단기, 전화(그리고 평소처럼 컨스트럭터에이러한 call이 없는 경우는)를 호출합니다.super()
암시적으로 컴파일러에 의해 처음에)두번씩 할당되지 못할 것 삽입합니다.는 컴파일러가 처음에 암묵적으로 삽입한 것으로, 2회 할당할수 없습니다.의심의 여지(첫번째 의심이 가는 경우에서처음처럼처럼)의 경우.get()
, ,어디에x
의이치노이는 단순히 이전에 코멘트 이외의 것이 있는 컨스트럭터에게 오류를 반환하는 것보다 나을 것입니다.super()
★★★★★★★★★★★★★★★★★」this()
.
작성자를 호출하기 전에 익명 이니셜라이저 블록을 사용하여 하위의 필드를 초기화할 수 있습니다.이 예에서는, 다음과 같이 설명합니다.
public class Test {
public static void main(String[] args) {
new Child();
}
}
class Parent {
public Parent() {
System.out.println("In parent");
}
}
class Child extends Parent {
{
System.out.println("In initializer");
}
public Child() {
super();
System.out.println("In child");
}
}
다음과 같이 출력됩니다.
모 in in 。
Initializer(「」)
(子) 。
컨스트럭터는 파생 순서대로 실행을 완료해야 합니다.슈퍼클래스는 서브클래스에 대한 지식이 없기 때문에 실행할 필요가 있는 모든 초기화는 서브클래스에 의해 실행되는 모든 초기화와는 별개이며 경우에 따라서는 그 전제조건이 될 수 있습니다.따라서 먼저 실행을 완료해야 합니다.
간단한 데모:
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
이 프로그램의 출력은 다음과 같습니다.
Inside A's constructor
Inside B's constructor
Inside C's constructor
파티에 조금 늦은 건 알지만, 이 방법을 몇 번 사용해 본 적이 있습니다(좀 이상하다는 것도 알고 있습니다).
인터페이스를 .InfoRunnable<T>
하다
public T run(Object... args);
그리고 컨스트럭터에게 전달하기 전에 해야 할 일이 있으면 다음 작업을 수행합니다.
super(new InfoRunnable<ThingToPass>() {
public ThingToPass run(Object... args) {
/* do your things here */
}
}.run(/* args here */));
로로 actually actually actually actually.super()
서브클래스를 구축하기 전에 슈퍼클래스가 완전히 포맷되어 있는지 확인하기 위해 컨스트럭터의 첫 번째 스테이트먼트입니다.super()
컴파일러가 첫 번째 스테이트먼트에서 추가해 드립니다!
왜냐하면 당신의 컨스트럭터는 다른 컨스트럭터에 의존하기 때문입니다.당신의 컨스트럭터가 올바르게 작업하기 위해서는 종속된 다른 컨스트럭터가 올바르게 동작해야 합니다.그렇기 때문에 먼저 컨스트럭터에서 this() 또는 super()에 의해 호출된 종속 컨스트럭터를 확인해야 합니다.this() 또는 super()에 의해 호출된 다른 컨스트럭터에 문제가 있는 경우 호출된 컨스트럭터가 실패하면 모든 것이 실패하기 때문에 어떤 포인트가 다른 문을 실행합니까?
Java가 왜 이런 짓을 하는지에 대한 의문은 이미 해결되었지만, 저는 이 질문에 대해 원라이너에 대한 더 나은 대안을 찾기를 바라며 이 질문을 우연히 발견했으므로, 이것으로 저의 회피책을 공유하겠습니다.
public class SomethingComplicated extends SomethingComplicatedParent {
private interface Lambda<T> {
public T run();
}
public SomethingComplicated(Settings settings) {
super(((Lambda<Settings>) () -> {
// My modification code,
settings.setting1 = settings.setting2;
return settings;
}).run());
}
}
정적 함수를 호출하면 더 나은 성능을 얻을 수 있지만, 코드를 컨스트럭터 안에 넣어야 하거나 여러 개의 파라미터를 변경하여 많은 정적 메서드를 정의해야 가독성이 저하될 경우 사용합니다.
Tldr:
다른 답변들은 질문의 "왜"에 대해 다루고 있다.이 제한에 대한 해답을 제시하겠습니다.
기본적인 생각은 납치하는 것이다.super
스테이트먼트와 임베디드 스테이트먼트를 조합합니다.이는 문장을 표현으로 위장함으로써 수행할 수 있습니다.
Tsdr:
해 주세요.Statement1()
로로 합니다.Statement9()
하기 super()
:
public class Child extends Parent {
public Child(T1 _1, T2 _2, T3 _3) {
Statement_1();
Statement_2();
Statement_3(); // and etc...
Statement_9();
super(_1, _2, _3); // compiler rejects because this is not the first line
}
}
물론 컴파일러는 우리의 코드를 거부합니다.대신 다음과 같은 작업을 수행할 수 있습니다.
// This compiles fine:
public class Child extends Parent {
public Child(T1 _1, T2 _2, T3 _3) {
super(F(_1), _2, _3);
}
public static T1 F(T1 _1) {
Statement_1();
Statement_2();
Statement_3(); // and etc...
Statement_9();
return _1;
}
}
유일한 제한은 부모 클래스에 적어도1개의 인수를 받아들이는 컨스트럭터가 있어야 표현식으로 스테이트먼트를 슬쩍 삽입할 수 있다는 것입니다.
다음은 보다 상세한 예를 제시하겠습니다.
public class Child extends Parent {
public Child(int i, String s, T1 t1) {
i = i * 10 - 123;
if (s.length() > i) {
s = "This is substr s: " + s.substring(0, 5);
} else {
s = "Asdfg";
}
t1.Set(i);
T2 t2 = t1.Get();
t2.F();
Object obj = Static_Class.A_Static_Method(i, s, t1);
super(obj, i, "some argument", s, t1, t2); // compiler rejects because this is not the first line
}
}
재작업 대상:
// This compiles fine:
public class Child extends Parent {
public Child(int i, String s, T1 t1) {
super(Arg1(i, s, t1), Arg2(i), "some argument", Arg4(i, s), t1, Arg6(i, t1));
}
private static Object Arg1(int i, String s, T1 t1) {
i = Arg2(i);
s = Arg4(s);
return Static_Class.A_Static_Method(i, s, t1);
}
private static int Arg2(int i) {
i = i * 10 - 123;
return i;
}
private static String Arg4(int i, String s) {
i = Arg2(i);
if (s.length() > i) {
s = "This is sub s: " + s.substring(0, 5);
} else {
s = "Asdfg";
}
return s;
}
private static T2 Arg6(int i, T1 t1) {
i = Arg2(i);
t1.Set(i);
T2 t2 = t1.Get();
t2.F();
return t2;
}
}
사실 컴파일러는 이 프로세스를 자동화할 수 있었습니다.그들은 그냥 하지 않기로 결정했다.
하위 개체를 생성하려면 먼저 상위 개체를 생성해야 합니다.여러분도 알다시피 수업을 이렇게 쓸 때:
public MyClass {
public MyClass(String someArg) {
System.out.println(someArg);
}
}
다음 단계로 전환됩니다(예외 및 슈퍼는 숨겨져 있습니다).
public MyClass extends Object{
public MyClass(String someArg) {
super();
System.out.println(someArg);
}
}
.Object
후 이 를 ""로 합니다.MyClass
수 .MyClass
before Object
간단한 규칙은 부모 컨스트럭터를 자식 컨스트럭터보다 먼저 호출해야 한다는 것입니다.하지만 클래스에는 여러 개의 컨스트럭터가 있을 수 있습니다.할 수 (Java가 ).super()
★★★★★★★★★★★★★★★★★」super(yourArgs...)
쓸 super(yourArgs...)
상위 개체를 생성하기 위해 호출되는 생성자를 재정의합니다. 실행이 안 돼요.super()
않기 , 그 후에).super()
오브젝트가 생성되어 원하는 모든 것을 할 수 있게 됩니다.)
왜 는 '우리'를 실행할 수 없는 죠?this()
★★★★★★★★★★★★★★★★★?요.this()
는 현재 클래스의 컨스트럭터입니다. 우리 , ' 반에 다른 수의 건설자가 있다'와 같이 수 .this()
★★★★★★★★★★★★★★★★★」this(yourArgs...)
바와 같이 컨스트럭터에는 가 있습니다.super()
을 super(yourArgs...)
super()
super(yourArgs...)
, 「」를 정의할 「」를 정의합니다.this()
★★★★★★★★★★★★★★★★★」this(yourArgs...)
, ★★★★★★★★★★★★★★★★★★★★★★★★★★★super()
에서는 '만약에'가 있으면 '만약에'가 되기 super()
있었다this()
같은 방법으로 둘 이상의 부모 개체를 만듭니다.에 같은 되고 있는 것입니다.this()
을 다른 만 하면 그 는 부모 오브젝트 작성을 다른 아이 컨스트럭터에게 호출합니다.super()
부모 작성용 컨스트럭터.을 사용하다
public MyClass extends Object{
public MyClass(int a) {
super();
System.out.println(a);
}
public MyClass(int a, int b) {
this(a);
System.out.println(b);
}
}
다른 사람들이 말하듯이 다음과 같은 코드를 실행할 수 있습니다.
this(a+b);
또한 다음과 같은 코드를 실행할 수 있습니다.
public MyClass(int a, SomeObject someObject) {
this(someObject.add(a+5));
}
그러나 메서드가 아직 존재하지 않기 때문에 다음과 같은 코드를 실행할 수 없습니다.
public MyClass extends Object{
public MyClass(int a) {
}
public MyClass(int a, int b) {
this(add(a, b));
}
public int add(int a, int b){
return a+b;
}
}
, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.super()
of of in this()
할 수 없습니다.을 사용하다
public MyClass{
public MyClass(int a) {
this(a, 5);
}
public MyClass(int a, int b) {
this(a);
}
}
class C
{
int y,z;
C()
{
y=10;
}
C(int x)
{
C();
z=x+y;
System.out.println(z);
}
}
class A
{
public static void main(String a[])
{
new C(10);
}
}
「」를 는, 해 주세요.C(int x)
.를 y로 않으면 y에 따라 달라집니다.C()
첫 번째 줄에서는 z의 문제가 됩니다. z는 올바른 값을 얻을 수 없습니다.
서브클래스 컨스트럭터에 super()를 추가하는 주요 목적은 컴파일러의 주요 업무는 오브젝트 클래스와 모든 클래스를 직접 또는 간접적으로 연결하는 것입니다.이 때문에 컴파일러는 슈퍼(파라미터화)를 제공했는지 여부를 체크하고 컴파일러는 어떠한 책임도 지지 않습니다.모든 인스턴스 멤버가 객체에서 하위 클래스로 초기화되도록 합니다.
이치노「이」 「슈퍼」 「슈퍼」 「슈퍼」...
제한은 결코 대중적이지 않았고, 자의적으로 인식되었다.한 명이 있었는데
의 확인을의 수
이 제한의 원인이 되었습니다.지난 몇 년 동안, 우리는
가 될 때까지 할 수 있습니다.
하는 것은 을 위해서도 검토한다.
컨스트럭터
언급URL : https://stackoverflow.com/questions/1168345/why-do-this-and-super-have-to-be-the-first-statement-in-a-constructor
'source' 카테고리의 다른 글
내부 클래스 개체에서 외부 클래스 개체를 가져오는 중 (0) | 2022.08.25 |
---|---|
Larabel 5.5 및 Vue.js 블레이드 테스트 (0) | 2022.08.25 |
기억과 관련하여 아레나라는 용어의 의미는 무엇입니까? (0) | 2022.08.25 |
부모 퇴출 후 자녀 프로세스를 정지시키는 방법 (0) | 2022.08.25 |
js 파일 VUEX에서 상태 액세스 방법 (0) | 2022.08.25 |