2

私はOOPの過去の試験問題をいくつか見ていますが、次のコードを理解するのに助けていただければ幸いです。問題は、この最初のコードブロックと、SandwichがEdibleを実装していることを考えると、次のステートメントのどれが合法ですか?

Sandwich sub = new Sandwich();
Rectangle cerealBox = new Rectangle(20,30,20,10);
Edible e = null;

e = sub;
sub = e;
sub = (Sandwich) e;
sub = (Sandwich) cerealBox;
e = cerealBox;
e = (Edible) cerealBox;
e = (Rectangle) cerealBox;
e = (Rectangle) null;
e = (Edible) sub;
cerealBox = (Rectangle) new Object();

私の現在の理解では、サブには食用オブジェクトを構成するために必要な要素があるため、最初のステートメントは真です。したがって、2番目のステートメントでは逆に機能しません。そして、3番目のステートメントでは、キャストによってこれが機能します。しかし、cerealBoxはSandwichに適用されないため、4番目はそうではありません。その後、最後の2つはキャストのために機能します。しかし、どうやら6番目のものは機能しますか?

私が知っていることについての私のひどい説明について申し訳ありませんが、どんな助けもいただければ幸いです。

4

2 に答える 2

6

Javaでの継承とインターフェースの実装は、「is-a」関係を表すと言われています。つまり、Boyから継承するPerson場合Boyは、-aPersonです。その結果、それがそうであるかのように扱うことができます(そうであるPersonため)。これは特に、タイプがのインスタンスに割り当てることができることを意味しますPerson

これで武装して、私たちはそれを決定することができます

  1. e = subコンパイルして正常に実行されます。[わかった]
  2. sub = e一方、コンパイルされません。is-aの関係を元に戻すことはできません。[!]
  3. sub = (Sandwich) e 上記を明示的なキャストでコンパイルするように強制します。さらに、eその時点でサンドイッチ(割り当て1から)が含まれているため、このキャストも実行時に成功します[わかった]
  4. sub = (Sandwich) cerealBox –からRectangleへの意味のある変換がないためSandwich、これはコンパイルに失敗します。[!]
  5. e = cerealBox–ほぼ同じ理由で、ここでも同じです。[!]
  6. e = (Edible) cerealBoxここで、Javaコンパイラーは要約します:に含まれるオブジェクトがcerealBox実装されていないために成功できないことを私たち(プログラマー)が知っていても、キャストを許可しますEdible–しかし、コンパイラーはこれを知ることができません:おそらく、含まれるオブジェクトその中で、から派生することができRectangle(したがって、に割り当てることができますcerealBox)、またを実装することができますEdible

    したがって、コンパイラは黙認します。ただし、実行時に。を取得しますClassCastException

    このステートメントが4とどのように異なるかに注意してください。そこで、コンパイラーは、をcerealBox含めることができないことを知っていましたSandwich。しかし、それは何かを含む可能性Edibleがあります。なんで?Javaは単一継承である(そしてRectangleから継承しないSandwich)が、複数のインターフェースから拡張できるため。[C]

  7. e = (Rectangle) cerealBoxキャストは実際には完全に無意味cerealBoxであり(すでにタイプRectangle)、残りのステートメントは5と同等であるため、失敗します。 [!]
  8. e = (Rectangle) nullオブジェクトに割り当てるnull ことができる場合でも、失敗しEdibleます。しかし、キャストは5が無効であるのと同じ理由でこれを無効にします。[!]
  9. e = (Edible) subは有効であり、1と同等です。ただし、Javaは継承階層で暗黙的に上向きのキャストを実行するため、キャストは完全に冗長です。[わかった]
  10. cerealBox = (Rectangle) new Object()コンパイルし、実行時にクラッシュします。理由は6に似ています:Objectの基本クラスですRectangle; したがって、オブジェクトにはインスタンス含まれている可能性がありRectangle、これによりこのステートメントが成功します(その例については3を参照してください)。

    確かに、コンパイラは一種の愚かです–キャストされているオブジェクト– <code> new Object()–は決して。ではないことわかりますRectangle。ただし、一般的なケースでは不可能であるため、コンパイラはこの分析を行いません。[C]

キー:[OK] =コンパイル、エラーなしで実行。[C] =コンパイル、クラッシュ。[!]=コンパイルされません。

ご覧のとおり、どのステートメントが「合法」であるかという質問は、それを完全にカットするものではありません。これらのステートメントの一部はコンパイルされますが、実行時に例外が発生します。彼らは合法ですか?

于 2012-05-14T18:28:22.980 に答える
1

6番目は機能しません。RectangleはEdibleを実装していないため、Edibleにキャストすることはできません。

編集:IDEで許可されている理由については、Vulcanのコメントを参照してください。ランタイムエラーが発生します。

于 2012-05-14T18:10:56.103 に答える