/ / ClassCastExceptionと「キャストできない」コンパイルエラー-java、継承、キャスト、classcastexception

ClassCastException対 "キャストできません"コンパイルエラー - java、継承、キャスト、クラスキャスト例外

OCA Java SE 7 Programmer I試験のために勉強しているので、初心者の質問です。わからない質問の例があります。次のコードはコンパイルされますが、実行時にClassCastExceptionが発生します。

interface Roamable {
}

class Phone {
}

public class Tablet extends Phone implements Roamable {
public static void main(String... args) {
Roamable var = (Roamable) new Phone();
}
}

私が変わるとき Roamable var = (Roamable) new Phone();Roamable var = (Roamable) new String(); すぐにコンパイルエラーが発生します。

2つの質問:

  1. 上記のコードがまったくコンパイルされないのはなぜですか?電話は私にとってローミング可能とは無関係のようですか?
  2. なぜコードがコンパイルされますか new Phone()、しかし「コンパイルしない」 new String()

回答:

回答№1の13

上記のコードがまったくコンパイルされないのはなぜですか?電話とは無関係のようです 私にローミング可能?

はい、なぜなら Roamable インターフェースである場合、ランタイム例外を引き起こす可能性がありますが、コンパイル時例外は生じません。 Phone 実装していない Roamableのサブクラス Phone 可能性があります、したがって、コンパイラは実行時以外はそれを知る方法がありません。

Java言語仕様で既に定義されています。 ここで私の答えをチェックしてください.

コードが新しいPhone()でコンパイルされるのに、コンパイルされないのはなぜですか 新しいString()で?

なぜなら class String として宣言されています public final classjava.lang パッケージ。で指定されている jls 8.1.1.2 final class セクション:として宣言されたクラス final 「拡張できないため、サブクラスはありません」。そのため、コンパイラはすでにそれを知っています String 「拡張できない:したがって、サブクラスの存在は実装できません」 インタフェース Roamable

編集:(以下のコメントへの返信付き)

仮定しましょう B のサブクラスです A インターフェースを実装します T.

次のステートメント:

   T t = (T)new A();

基本的に次と同じです:

   A aObj = new A() ;
T t = (T)aObj ; // a run-time exception happen

結論を出す前に、次のオブジェクトで同じことをしましょう B

   A aObj = new B();
T t = (T)aObj; // no exception happen.

したがって、ここでのスーパークラスとサブクラスの本当の理由は参照です。の aObj この2番目のコード例のクラスは、クラスのインスタンスでもあります A しかし、それはクラスのインスタンスでもあります B 実装しました T.


回答№2の場合は3

文字列は最終的なものであるため、Roamableにキャストする方法はありません。


回答№3の場合は1

コンパイラにより次のことができるため、コードがコンパイルされます。何にもキャストします。これはプログラマーによる明示的なアクションであり、コンパイラーはリスクを評価し、適切な予防措置を講じていると想定します。

String のインスタンスではありません Roamableので、のインスタンスを割り当てることはできません String 〜に Roamable 参照。そして、それはコンパイル時に決定できるため、失敗します。


回答№4の場合は1

new Phone() クラスに評価する Phoneできた の延長である Phone 実装する Roamable (コンパイラに関する限り)。

電話をした場合 final クラス(Stringなど)、コンパイラエラーが表示されます。


回答№5の場合は0

いい質問です。 new Phone() 間違いなくサブクラスではありません Phone。ただし、その情報は失われますが、javacは Phone そこに入力してください 正確 Phone タイプ。

関連する仕様: http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5.1

Sが最終クラス(§8.1.1)の場合、SはTを実装する必要があり、

仕様は次のように修正できます

式がクラスインスタンス作成式(§15.9)の場合、式のタイプはTのサブタイプである必要があります。


答え№6の場合は0

最初に読む 明示的および暗黙的な型キャスト javaによって。

そのユーザーから明示的に責任がありますオブジェクトの関係を絞り込むときにキャストすることで、ユーザーがある程度の精度を失い、そのためにユーザーがそれを知っていて元気であることを伝えます。ただし、コンパイラーは明示的な誤ったキャストとスローを検出できます CE: Type mismatch error ある時点で。それ以降は実行時までです ClassCastException それに対処する。

コンパイラは、次の明示的なキャストのケースを検出できます。

class A {}
class B {}

A a = (A) new B(); //CE: Type mismatch: cannot convert from B to A
B b = (B) new A(); //compilation error (CE)

interface I {}
final class A {}
I i = (I) new A();  //compilation error

コンパイラは、次の明示的なキャストのケースを検出できません。

class A {}
class B extends A {}
A a = (A) new B(); //Fine
B b = (B) new A(); //Runtime error; because compile time;
//compiler wont be able to tell the reference is instance of A or B.
//means this is something like below. <BR>
B b = (B) (A) new A();

コンパイルエラーなしで、任意のオブジェクトを任意のインターフェイスにキャストできます。

interface I {}
class A {}
class B extends A implements I{}

I i = (I) new A();  //Runtime error
I i = (I) new B();  //Fine

なぜこれはコンパイルされますか?

インターフェイスの参照は、コンパイルエラーなしで任意のオブジェクトにキャストできます。

interface I {}
class A implements I {}
class B {}

B b = (B) getI();     //Runtime error
OR
B b = (B)(I)new A();  //Runtime error

public I getI() {
return new A();
}