現在Java Silverの資格を取るために黒本を勉強しています。
そこでダウンキャストの理解についてつまづいてしまいました。
以下のコードは実行時に例外がスローされ、ClassCastExceptionが発生します。
そうなるのはわかったのですが、なぜそうなるかがわかりません。
java
1public class aa{ 2 3 public static void main(String[] args){ 4 5 cc c=new cc(){}; 6 bb b= (bb)c; 7 8 } 9} 10 11 12class bb extends cc{ 13} 14 15class cc{ 16 void b(){ 17 System.out.println("ccクラスです。"); 18 } 19}
黒本 p277にはbbインスタンスにはccインスタンスの差分が含まれていないため、例外が発生する。
といったようなことが書いています。
そうすると以下は差分がないため、例外が発生しないような気がするのです。
もしくはデフォルトコンストラクタがその差分に当たるのでしょうか?
もしそうなら継承の関係においてダウンキャスト時に例外がスローされないケースはあるのでしょうか?
そもそも私の黒本の解説の解釈に少し誤りがあるのでしょうか?
いまいちスッキリ理解できていないのでもし分かる方がいれば教えていただきたいです。
実際の試験時は「継承のダウンキャストは実行時に例外が発生する」ととりあえず解答しようと思いますが、このままだと腑に落ちないし、もしそうでないときもあるのならと思い、しっかり理解したいと思いました。
追記
java
1class A{ 2 void hello(){ 3 System.out.println("A"); 4 } 5} 6 7class B extends A{ 8 void hello(){ 9 System.out.println("B"); 10 } 11} 12 13public class Main{ 14 public static void main(String[] args){ 15 A a=new A(); 16 B b= (B)a; 17 b.hello(); 18 } 19}
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
黒本 p277にはbbインスタンスにはccインスタンスの差分が含まれていないため、例外が発生する。
[...]
そもそも私の黒本の解説の解釈に少し誤りがあるのでしょうか?
黒本とやらの解説は不正確、好意的に解釈しても誤解を与える表現になっています。
ダウンキャスト/アップキャストの動作を理解する際は、ソースコード上に記述されている「静的な型」と、プログラム実行時に決まるインスタンス自身の「動的な型」を区別して認識すべきです。
java
1// スーパークラスB を継承した サブクラスD を定義 2class B { /*...*/ } 3class D extends B { /*...*/ } 4 5D d1 = new D(); // OK 6// d1の静的な型D/動的な型D 7B b1 = d1; // OK: 暗黙のアップキャスト 8// b1の静的な型B/動的な型D 9D x = (D)b1; // OK: ダウンキャスト 10// xの静的な型D/動的な型D 11 12B b2 = new B(); 13// b2の静的な型B/動的な型B 14D y = (D)b2; // NG: ダウンキャスト → ClassCastException例外が送出される 15// yの静的な型D には 動的な型Bを持つインスタンスを保持できない
他回答コメントに書かれた内容から、該当文脈での"差分"という用語の使われ方を理解できました。
継承は「差分プログラミング」という手法で、サブクラスのインスタンスは、スーパークラス内に記述されている処理内容とサブクラス内に記述されている処理内容(差分)の両方を持っている。
上記の引用文それ自身は、概ね正しいことを言っています。もう少し詳細化するならば次の通りでしょうか。
継承とは「差分プログラミング」という考え方を、Java言語において実装する手法であり、サブクラスのインスタンスは、スーパークラス内に記述されている処理内容とサブクラス内に記述されている処理内容(差分)の両方を持っている。この実装手法によって、サブクラスではスーパークラスの処理内容を繰り返して記述する必要がなく、処理内容の追加/変更を行いたい差分だけを記述するという差分プログラミングを実現できる。
そして、この話と「ダウンキャストの成功可否」には直接的な関係はありません。ダウンキャスト操作に関係するのは「キャスト先の変数の型は何か?キャスト元のインスタンスの型は何か?」という2点だけです。
差分プログラミングはプログラムの設計思想や設計方針について述べたものであり、一方のダウンキャスト操作では単にJava言語仕様を対象とした議論をしています。
投稿2015/09/26 16:30
編集2015/09/27 01:52総合スコア6191
0
ベストアンサー
Java
1class bb extends cc{ 2 public bb(){ 3 super(); 4 } 5} 6 7class cc{ 8 public cc(){ 9 super(); 10 } 11 void b(){ 12 System.out.println("ccクラスです。"); 13 } 14}
コンストラクタを追記しました。
・ccのコンストラクタ:super()を呼ぶことでObjectクラスのコンストラクタを呼び出しています。
・bbのコンストラクタ:super()を呼ぶことでccクラスのコンストラクタを呼び出しています。
つまりccのコンストラクタは「Object型のインスタンス」+「cc型のインスタンス」を作ります。
一方でbbのコンストラクタは「cc型のインスタンス」+「bb型のインスタンス」を作ります。
それを踏まえると下記のようになります。
Java
1bb b = new bb(); 2cc c = (cc) b;//bb型として作られたインスタンスbはcc型のインスタンスと差分が無い部分が存在するためキャストできる。 3c = new cc(); 4bb b = (bb)c;//cc型として作られたインスタンスcはbb型のインスタンスと差分が無い部分が存在しないためキャストできない。
投稿2015/09/26 09:57
総合スコア18157
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/27 01:09

0
ダウンキャストで例外が発生しない例は以下の様なものがあります.
java
1public class aa{ 2 3 public static void main(String[] args){ 4 5 cc c=new bb(); //ccの代わりにbbのコンストラクタ 6 bb b= (bb)c; 7 8 } 9}
bbのインスタンスを生成してそのスーパークラス型のcc型の変数に入れる段階でアップキャストが発生します.その後bbへのダウンキャストを行っています.
この場合cの実体はbbクラスのインスタンス(アップキャストしようが実体は変わらない)なので,例外は発生せずキャストができます.
投稿2015/09/26 09:26
総合スコア20675
0
黒本を読んだことが無いので、その本で言っている「差分」の定義がどんなものかは分かりません。また、正確なJava言語仕様上の定義も分かりませんが、
bb
クラスは、「cc
クラスを継承した新しいクラス」という点が機能の差分となっていると考えられます。
本題とはあまり関係ないかもしれませんが、
new cc(){}
はcc
クラスの匿名サブクラスのインスタンス生成になっています。
これは意図的なものでしょうか?
(追記)
最初と言っていることが変わってしまいますが...
差分というのは、おそらくJava以外の言語(C++ とか?)の継承のケースのことを言っているのではないかと思いました。ただ、この辺はあまり詳しくないので自信はないです。
Java言語仕様のことではなく、たとえのような意味でいっているとしたらそれはそれで語弊があるような気もします。
言語仕様に拠れば、Javaの場合は、差分でなく、主に継承関係のチェックだけでダウンキャスト(Narrowing Reference Conversion)が可能かをチェックしています。
言語仕様の最新版(Java8)は英語ですが下記です。(5.1.6)
Chapter 5. Conversions and Contexts - Java Languate Specification
日本語版は少し古いですが、下記ページの「5.1.5 参照型の縮小変換」を参照して下さい。
Java言語規定 変換及び昇格
投稿2015/09/26 09:47
編集2015/09/26 14:44総合スコア9396
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/26 17:08
2015/09/27 01:25
2015/09/27 02:17 編集
2015/09/27 04:35
2015/09/28 05:03