this()
コンストラクターでsuper()
両方を一緒に使用できないのはなぜですか?
そのようなものを組み込む理由は何ですか?
this(...)
super()
スーパーコンストラクターを呼び出すのに対し、同じクラスの別のコンストラクターを呼び出します。コンストラクターにない場合super()
、コンパイラーは暗黙的にコンストラクターを追加します。
したがって、両方が許可されている場合、super
コンストラクターを 2 回呼び出すことになる可能性があります。
例 (パラメーターの意味を探さないでください):
class A {
public A() {
this( false );
}
public A(boolean someFlag) {
}
}
class B extends A {
public B() {
super();
}
public B( boolean someFlag ) {
super( someFlag );
}
public B ( int someNumber ) {
this(); //
}
}
ここでnew B(5)
、次のコンストラクターを呼び出すと、呼び出されます。
this( false);
A() ---------------> A(false)
^
|
| super();
|
| this();
B() <--------------- B(5) <--- you start here
更新:
使用できた場合、次のような結果になる可能性がthis()
あります。super()
(注意: これは、許可されている場合に、何がうまくいかないかを示すことを目的としています - 幸いなことに、そうではありません)
this( false);
A() ---------------> A(false)
^ ^
| |
| super(); | super( true ); <--- Problem: should the parameter be true or false?
| |
| this(); |
B() <--------------- B(5) <--- you start here
ご覧のとおり、A(boolean)
コンストラクターがさまざまなパラメーターで呼び出される可能性があるという問題に遭遇し、どちらを使用する必要があるかをどうにかして決定する必要があります。さらに、他のコンストラクター (A()
およびB()
) には、正しく呼び出されない可能性があるコード (つまり、順不同など) が含まれる可能性がありsuper( true )
ますthis()
。
と の間には違いがsuper()
ありthis()
ます。
super()
- 基本クラスのコンストラクターを呼び出しますが、
this()
- 現在のクラスのコンストラクターを呼び出します。
this()
とはどちらsuper()
もコンストラクター呼び出しです。
コンストラクター呼び出しは常に最初のステートメントでなければなりません。したがって、最初のステートメントとしてsuper()
orがあります。this()
this()
とは両方ともsuper()
コンストラクター呼び出しであり、コンストラクター呼び出しは、コンストラクターの最初の (そして唯一の) 呼び出しでなければなりません。そうしObject
ないと、単一のオブジェクトをインスタンス化するときに、コンストラクターが複数回呼び出されます。
意味がないからです。this()
コンストラクターはorをsuper()
(暗黙的または明示的に)呼び出す必要があります。以前のようにor etcthis()
を呼び出す必要がある別のコンストラクターを呼び出します。両方を呼び出したため、最終的に2 回呼び出すコンストラクター。this()
super()
this()
super()
super()
以下の例を比較してください。クラス FirstChild は、super() を呼び出す必要があるため、最初のコンストラクターから 2 番目のコンストラクターを呼び出すことは除外されるため、2 つのコンストラクターでインスタンス変数名を設定します。
クラス SecondChild には、2 つのパラメーターを取る 3 番目のプライベート コンストラクターが導入されています。最初のパラメーターは supper() に渡され、2 番目のパラメーターは名前の設定に使用されます。最初の 2 つのコンストラクターが 3 番目のコンストラクターを呼び出しています。Super() は 1 回だけ呼び出され、インスタンス変数は 1 つのコンストラクターでのみ設定されます。コードは、同じコンストラクターで super() と this() を呼び出す必要なく、同じ結果を生成します。
class FirstChild extends ConstructorTest{
private String name = null;
public FirstChild(){
super("super text 1");
//this("Unknown"); //UNCOMMENTED DOES NOT COMPILE
name = "Unknown";
}
public FirstChild(String name){
super("super text 2");
this.name = name;
}
public String getName(){
return name;
}
}
class SecondChild extends ConstructorTest{
private String name = null;
public SecondChild(){
this("super text 1", "Unknown");
}
public SecondChild(String name){
this("super text 2", name);
}
private SecondChild(String superStr, String name)
{
super(superStr);
this.name = name;
}
public String getName(){
return name;
}
}
public class ConstructorTest{
public ConstructorTest(String str){
System.out.println("ConstructorTest constructor called with parameter \"" + str + "\"");
}
public static void main(String... args)
{
System.out.println("Hello from main, FirstChild results:");
FirstChild fc1 = new FirstChild();
FirstChild fc2 = new FirstChild("John");
System.out.println(" child fc1 name: " + fc1.getName());
System.out.println(" child fc2 name: " + fc2.getName());
System.out.println("Hello from main, SecondChild results:");
SecondChild sc1 = new SecondChild();
SecondChild sc2 = new SecondChild("John");
System.out.println(" child sc1 name: " + sc1.getName());
System.out.println(" child sc2 name: " + sc2.getName());
}
}
super() - 直接の親クラス インスタンスを参照します。直接の親クラス メソッドを呼び出すために使用できます。this() - 現在のクラス インスタンスを参照します。現在のクラス メソッドを呼び出すために使用できます。
コンストラクター呼び出しはメソッドの最初のステートメントである必要があるため、メソッド内でこれとスーパー コンストラクターの両方を定義すると、次のように競合が発生します。このコンストラクターが最初に呼び出された場合、現在のクラス コンストラクターがチェックされ、現在のクラス コンストラクターに別のメソッド呼び出しまたはステートメントがあるかどうかがチェックされます。したがって、この呼び出しでは、現在のクラスコンストラクター内のすべてのメソッドとステートメントが呼び出されてから、スーパークラスコンストラクターが呼び出され、「コンストラクター呼び出しはメソッドの最初のステートメントでなければならない」というステートメントが拒否されます。