31
public class TestClass(){
    public static void main(String []args) {
        TestClass t1 = new TestClass();
        t1.anything();
    }
}

同じクラスの定義でオブジェクトを作成するのはおかしくないですか?それに応じて、このオブジェクトは新しいオブジェクトを作成し、この新しいオブジェクトは別のオブジェクトを作成し、メモリがいっぱいになるまで無限ループが始まります。

4

7 に答える 7

27

オブジェクトが新しいオブジェクトを作成し、この新しいオブジェクトが別のオブジェクトを作成し、無限ループが始まるのに応答して、同じクラスの定義でオブジェクトを作成するのは奇妙ではありませんか

いいえ、メイン メソッドは、プログラムを実行するときに 1 回だけ実行されます。再度実行されることはありません。したがって、オブジェクトは一度だけ作成されます。

メインメソッドはクラスの外にあると考えてください。クラスのインスタンスを作成し、作成したインスタンスを使用します。したがって、mainメソッドからインスタンスを作成すると、コンストラクターが呼び出されてインスタンスの状態が初期化され、コンストラクターが戻ると、メイン メソッドの次のステートメントが実行されます。

main実際、メソッドはクラスのインスタンスの状態の一部ではないと考えることができます。

ただし、コンストラクター内にクラスのインスタンスを作成し (0-arg など)、参照をインスタンス参照変数として作成した場合、それは無限再帰になります。

public class A {
    private A obj;
    public A() {
        obj = new A();  // This will become recursive creation of object.
                        // Thus resulting in StackOverflow 
    }
}
于 2012-10-24T07:58:46.623 に答える
6

以下を実行しようとすると、無限ループ(スタックオーバーフローエラー)のみが発生します。

public class TestClass {
    public TestClass() {
        TestClass t = new TestClass();
    }
}

そして他の場所では、クラスのオブジェクトを作成しようとしますTestClass

于 2012-10-24T08:01:49.057 に答える
3
public class TestClass{
  public static void main(String []args) {
    TestClass t1 = new TestClass();
    t1.anything();
  }
}

これは完全に有効なコードです。メソッドが呼び出されたとき、main前のインスタンスは存在しません(メソッドはTestClassであるため、存在する必要はありません)。mainstatic

public class Test2{
  public Test2 clone(){
    return new Test2();
  }
}

これも完全に有効です。Test2の新しいインスタンスを作成すると、cloneメソッドが含まれますが、メソッドは自動的に実行されません。メソッドが呼び出された場合にのみ、cloneTest2のインスタンスがもう1つ作成されます。

public class MyLinkedList{
  MyLinkedList next;
  MyLinkedList(int elems){
    if(elems>0){
      next = new MyLinkedList(elems-1);
    }else{
      next = null;
    }
  }
}

コンストラクターが同じコンストラクターを使用して新しいインスタンスを作成する場合でも、作成は条件付きで保護されているため、インスタンスを作成すると新しい作成がトリガーされることがあるため、も完全に有効です。

public class Fail{
  public Fail(){
    new Fail();
  }
}

ここで問題となる唯一の例です。コンパイラは文句を言いません。バイトコードに変換して実行することができます。ただし、実行時にスタックオーバーフローが発生します。

  • 新しい失敗が割り当てられます
  • その引数なしのコンストラクターは呼び出されます
  • コンストラクターは新しいFailを作成しようとします
  • 新しい失敗が割り当てられます
  • その引数なしのコンストラクターは呼び出されます
  • ..。

一般に、コンパイラはすべての無限再帰を防ぐことができないため、コンパイラはこれを許可します。コンパイラは、バイトコードに変換できるものなら何でも許可します

ただし、コンパイラがメソッドを検出した場合、またはメソッドチェーンが無条件に自分自身を呼び出した場合、コンパイラは警告発行することがあります。

于 2012-10-24T08:16:12.273 に答える
2

それは本当に奇妙ではありません。私が知っているすべてのオブジェクト指向言語はこれを許可します。コードは意味的にはオブジェクト定義の一部ですが、実際には、特定のオブジェクトの実際の状態とは別のものと見なすことができます。したがって、オブジェクトの構築ではメソッドが呼び出されないため、ループは発生しません(もちろん、呼び出されない限り、問題が発生します)。

于 2012-10-24T07:59:44.340 に答える
1

newを使用してオブジェクトを作成すると、インスタンス変数を初期化するコンストラクターが呼び出されます。これは、スーパークラスのすべてのコンストラクターが呼び出されるまで発生します。オブジェクトを作成するたびに実行されるコンストラクター内にいくつかのコードを配置した場合

于 2012-10-24T07:59:55.377 に答える
1

プログラムが起動すると、main メソッドが実行されます。Java では、クラス外にメソッドを作成することはできません。すべてのメソッドは、クラス内にカプセル化する必要があります。したがって、プログラムへのエントリ ポイントとしてのメイン メソッドは、クラス内にある必要があります。このプログラムを実行すると、メイン メソッドが 1 回実行され、その中のコードが実行されます。あなたの場合、囲んでいる class のオブジェクトを作成しますTestClass。これは発生する必要はありません。このクラス以外のオブジェクトも作成できます。@adarshrの回答で説明されているように、無限ループしか得られません。

于 2012-10-24T08:03:15.967 に答える