2

Java でのオブジェクトの参照に関する概念的な質問があります。

ここでNumはインターフェースです

public interface Num {
    void sum();
}

Num を実装する Num2

public class Num2 implements Num{
    @Override
    public void sum() {
        System.out.println(getRandom()+getRandom());
    }

    public int getRandom() {
        Random randomNumber = new Random();
        int number = randomNumber.nextInt(30);
        return number;
    }
}

そして主な機能

Num n = new Num2();
n.sum();

ここで、nはオブジェクト Num2 の参照であり、nはオブジェクト Num2 を指すポインターであることがわかります。Num2 にはメソッドsumgetRandomの両方が含まれています。ただし、 n参照を介してメソッドにアクセスしようとすると、sumメソッドしか取得できません。私の質問は、ポインターがどのメソッドが Num に含まれているかをどのように知ることができるかということです。オブジェクトの初期化中に参照するために、どのように、どの情報がスタックに格納されるか。誤解がある場合は、修正してください。

4

6 に答える 6

3

変数nをインターフェイス型として定義しているNumため、 で宣言されているメソッドのみを呼び出すことができますNum。この解決策は、コンパイル時に行われると私は信じています。コンパイラは、型に基づいた参照変数を使用して、どのフィールドまたはメソッドにアクセスできるかを判断します。

ただし、ランタイムは実際のオブジェクト タイプ、つまりインターフェイスを実装するクラスでメソッドを呼び出すことに注意してください。

クラス型 T の変数は、null 参照、またはクラス T または T のサブクラスである任意のクラスのインスタンスへの参照を保持できます。

以下のコードを見てください:

interface A {
  void method1();
}
class B implements A {
  public void method1() {
  }
  public void methodB(){
  }
}
class C implements A {
  public void method1() {
  }
  public void methodC(){
  }
}
public class InterfaceTest {
   public void testMethod(A a){
       // this is safe because whatever may be the run time type of actual
       // object `a` is referring to , that object will always implement
       // method1.
      a.method1();
      // this cannot be allowed because compiler doesn't know 
      // what will be the actual run time object `a` will refer to
       // It may or may not be an object of B.
      a.methodB(); 
   }
}
于 2013-07-25T04:46:29.247 に答える
2

Numコンパイラ (実行時ではない) は、オブジェクトをではなく のように扱うことを検証します。Num2

于 2013-07-25T04:45:42.127 に答える
1

コンパイル時に変数に定義された型のメソッドにのみアクセスできます。n変数は型からのものであるためNum、インターフェイスで定義されたメソッドのみを使用できNumます。これらのメソッドの動作は、実際のオブジェクト参照型 (この場合は ) によって定義されることに注意してくださいNum2

于 2013-07-25T04:45:03.617 に答える
1
My question is that how can a pointer know which method are contained in Num?

コンパイル時に、参照ポインターによって呼び出される関数またはメソッドが参照ポインターのクラスで宣言されている (必ずしも定義されていない) ことのみがチェックされます。実行時に継承ツリー全体がトップダウン方式で解析され、正しい関数実装が選択されます。

また、実際のオブジェクトがヒープにある間、言及した参照ポインターはスタックにあります。オブジェクトにはクラス情報があります。例を挙げましょう -

    Animal animal = new Dog();
    System.out.println(animal.getClass());

印刷class Dogされません class Animal

于 2013-07-25T04:53:46.050 に答える
1

以下がその背後にあると思います(間違っている場合は修正してください):

参照を作成するNum nと、メモリ内のどこかに、これがそのプロパティとともに作成されます。

したがって、この参照でアクセスできるメソッドなどを定義する必要があります。

オブジェクトを参照すると、オブジェクトはメモリ内の別のエンティティになります。参照を使用してアクセスしようとすると、コンパイラは参照メタデータを使用して、その参照を使用してどのメソッドを呼び出すことができるかを判断する必要があります。

于 2013-07-25T04:49:09.147 に答える
0

Java では、Child extends Parent(またはimplements) と を記述すると、メモリ内のオブジェクトへの参照Parent object = new Child()が作成されます。コードがコンパイルされると、JVMはメモリ内のオブジェクトを処理し、参照変数が実際にメモリ内の型のオブジェクトを参照していることを認識します (この場合は type です)。しかしそれまでは、コンパイラ に対処する必要があります。コンパイラは、この場合は(またはあなたの場合は)である参照のタイプのみを気にするため、 ()クラスで宣言されているメソッドを呼び出すだけです。ParentChild

objectChildnNum2

ParentNumParentNum

これを回避する 1 つの方法は、次のようにキャストを実行することです。メモリ内の型の Object を実際に指している (または指している) ことが

((Num2) n).getRandom();

確実にわかっている場合にのみ、これを行うようにしてください。それ以外の場合は、. ここでは、コンパイラに「信じてください。これが Num2 であることはわかっているので、Num2 のように扱ってください」と伝えています。 総括する:nNum2ClassCastException


  • Num n = new Num2()参照変数を宣言し、メモリ内にオブジェクトを作成します
  • 変数の型は でNumあり、コンパイラが認識しているのはそれだけです
  • メモリ内に作成されたオブジェクトのタイプNum2は であり、JVM はこれを認識します。
  • JVMを実行するには、コンパイラを満たす必要があります
  • このような場合、キャストすることでコンパイラを満足させることができます。
于 2013-07-25T05:00:44.200 に答える