11

Java のオブジェクトのコンパイル時型と実行時型の違いは何ですか? 私はEffective Java bookを読んでいます.Joshua Blochは、主にキャスト警告を抑制することが安全な場合があることを説明するために、アイテム26の配列インスタンスのコンパイル時の型と実行時の型について何度も言及しています。

// Appropriate suppression of unchecked warning
public E pop() {
 if (size == 0)
   throw new EmptyStackException();
   // push requires elements to be of type E, so cast is correct
   @SuppressWarnings("unchecked") E result = (E) elements[--size];
   elements[size] = null; // Eliminate obsolete reference
   return result;
}

ここで著者は、これらのさまざまなタイプtypesの配列について話しています。compile time typesしかし、この質問を通じて、 vs run time typesfor any type of objectの違いを理解したいと思います。

4

5 に答える 5

17

Javaは静的に型付けされた言語であるため、コンパイラーはすべての型を判別し、すべてが型に対して安全であることを確認しようとします。残念ながら、静的型推論は本質的に制限されています。コンパイラは保守的である必要があり、実行時情報も表示できません。したがって、実際にタイプセーフであっても、特定のコードがタイプセーフであることを証明することはできません。

実行時型は、実行時の変数の実際の型を指します。プログラマーとして、あなたはコンパイラーよりもこれをよく知っているといいのですが、そうすることが安全であることがわかっているときに警告を抑制することができます。

たとえば、次のコードを考えてみましょう(コンパイルされません)

public class typetest{
    public static void main(String[] args){
        Object x = args;
        String[] y = x;

        System.out.println(y[0])
    }
}

変数xは常に型を持ちますString[]が、コンパイラーはこれを理解できません。したがって、に割り当てるときは明示的なキャストが必要ですy

于 2013-02-19T17:48:17.060 に答える
1

Java は静的に型付けされます。つまり、言語のすべての式 (変数を含む) には、言語の規則に従ってコンパイル時に認識される型があります。これは、静的型 (「コンパイル時型」と呼ばれるもの) として知られています。Java の型には、プリミティブ型と参照型があります。

また、Java の実行時の各オブジェクトには、実行時に認識される「クラス」があります (ここでは、「クラス」には架空の配列「クラス」が含まれます)。オブジェクトのクラスは、オブジェクトが作成されたクラスです。

混乱の一部は、Java の各クラス (およびインターフェイスと配列型) が、クラス (またはインターフェイスまたは配列型) の名前を持つ、対応する参照型を持っているという事実に由来します。参照型の値は参照であり、オブジェクトであるnullか、オブジェクトを指すことができます。Java 言語は、参照型の参照が、 クラスX またはそのサブクラス (またはインターフェイスX を実装するクラス)であるオブジェクトを常に指すXように設計されています。null

ランタイム クラスはobjectsを適用しますが、オブジェクトは Java の値ではないことに注意してください。一方、型は、コンパイル時の概念である変数と式に適用されます。オブジェクト型がないため、変数または式がオブジェクトの値を持つことはありません。オブジェクトを指す参照の値を持つことができます。

于 2013-02-19T21:19:01.810 に答える
0

「コンパイル時の型」とは、変数がコンパイル時に持つことができる任意の型と考えています。これには、宣言されたクラス、スーパークラス、および実装されたインターフェイスが含まれます。

実行時に、特定のオブジェクトには最下位レベルのクラスが 1 つしかありません。そのクラスの変数に合法的にキャストまたは代入できますが、そのサブクラスまたは実装されたインターフェースの任意の変数にもキャストできます。コンパイラは (多くの場合、とにかく) それを何にでもキャストできるようにしますが、正当でないものを代入しようとすると、ランタイムは例外をスローします。

オブジェクトが変数に割り当てられると、コンパイラはそれを変数の型であるかのように扱います。したがって、「コンパイル時」の別の用途は変数型である可能性があり、実行時にキャストが有効であることがわかっている限り、コンパイル時に別の型にキャストすることでそれを回避できます。

1 つの型だけについて話す場合、変数の「ランタイム型」は、変数の実際の下位 (上位?) レベルのサブクラスであると考えます。キャストできる最下位のサブクラス。しかし、私は日常的に、あらゆるオブジェクトをその正当な型のインスタンス化と考えています。

それが役立つことを願っています。

于 2013-02-19T18:15:53.617 に答える