質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java EE

Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

764閲覧

Javaで例外になる理由について(問題集のとある問題)

yusuke1818

総合スコア10

Java EE

Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

2クリップ

投稿2023/02/26 05:19

Javaの問題集を解いていた時のとある問題なんですが、

public interface A{ //any code }
public class B implements A{ //any code }
public class C extends B{ //any code }
public class Main{ public static void main (String[] args){ B b = new B(); A a = b; C c = (C) a; } }

というコードがあった時に、結果としてはMainクラスの5行目で例外がスルーされるという結果なのですが、その理由がわかりません。
Mainクラスの4行目でアップキャストが自動で行われて、5行目で明示的にダウンキャストしているのでコンパイルエラーにならないのまでは分かります。
ただ、その後の回答では
「プログラムを実行すると実際に動作しているのはB型のインスタンスであり、C型としての差分を持ちません。そのため5行目で実行時に例外が発生します。」と書いてあります。
--実際に動作しているのはB型のインスタンスであり、C型としての差分を持たない--
というのはどういう意味なのでしょうか?初歩的な問題かもしれませんが教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dameo

2023/02/26 06:01

書いてあるとおりなので、何が分からないのか分からないですが、他人が実行すると結果が変わる話なので、環境については明示すべきかと思います。 paiza.ioで以下のコードを試すと、 interface A{ } class B implements A{ } class C extends B{ } public class Main { public static void main(String[] args) throws Exception { B b = new B(); A a = b; C c = (C) a; } } // Exception in thread "main" java.lang.ClassCastException: class B cannot be cast to class C (B and C are in unnamed module of loader 'app') // at Main.main(Main.java:11) コメントのような例外が発生します。書いてあるとおりクラスB(のインスタンス)は、クラスCにキャストできません、ということです。クラスBもクラスCもインターフェースAを実装しているので、Aにキャストすることはできますが、aの実体はクラスBのインスタンスなので、クラスCにはキャストできないというだけです。 例えば、 interface A{ } class C implements A{ } class B extends C{ } public class Main { public static void main(String[] args) throws Exception { B b = new B(); A a = b; C c = (C) a; } } であればBはAを実装しているBの派生クラスになるので、aをCにキャストすることができます。 言い換えると、実体としてクラスBのインスタンスであるaは、インターフェースAを実装しているだけでなく、クラスCとして振る舞えるだけのメンバを使用できる、ということです。差分と言っているのはインターフェースAとクラスCの差分という意味だと思います。
xebme

2023/02/26 07:50 編集

C型とB型の違いが差分です。差分には何が含まれますか。 メソッド、フィールド、... 差分がないとどんな不都合が生じますか。 (「差分」という言葉の解釈は私個人のものですが、想像力があれば理解できると思いました) ( 自分で考えるヒントになればと思ってのコメントです。すべてを説明するつもりはありません)
jimbe

2023/02/26 06:31

要は「 B は C では無い」ということですが、継承関係からの違いを "差分" と言うのは著者の表現ですので、真意(?) は著者に聞くしか無いかもしれません。
dameo

2023/02/26 06:40

@xembe さん 解釈なので読み手次第ではありますが、Bクラスのインスタンスがその「差分を持っている」ことでCクラスとして振る舞うことができる(キャストできる)と解釈できるようにしないと駄目だと思いますよ
xebme

2023/02/26 20:31

dameoさん ダウンキャストキャストCがコンパイルエラーにならず、実行例外が発生するは何故か、の説明は必要かもしれないと思いました。
dameo

2023/02/27 02:11

@xembe さん 質問者さんは「5行目で明示的にダウンキャストしているのでコンパイルエラーにならないのまでは分かります」と言っているので、コンパイルエラーにならないことに説明は不要だと思いますよ。単純に「差分」という部分に違和感や疑問が残ったように見えますが、その部分の解釈が不可能になるとかえって質問者さんが混乱するかと思い、意見させて頂きました。 質問者さんからコメントはないものの解決してるみたいなので、まあこの辺で・・・
yusuke1818

2023/02/27 03:06 編集

沢山のコメントありがとうございます。 Mainクラスが単純に 「B b = new B(); C c = (C) b;」 だとしても子クラスのcに親クラスのインスタンスのbを入れても無理やり明示的にコンパイルまではできても実行はできないということであっていますでしょうか? ※問題なのであり得るが、そもそも実行出来ないこんなコンパイルなんて普通はしないという感じでしょうか? 勉強したてで理解が遅く申し訳ありません。
jimbe

2023/02/27 03:33

B は C では無いのですから、実行出来無いのは java では当然です。
yusuke1818

2023/02/27 03:36 編集

では逆であれば 「C c = new C(); B b = (B) C;」 であれば CはBなので実行は可能ということですね
jimbe

2023/02/27 03:42 編集

>逆であれば ~ 実行は可能 はい。キャストも要りません。
dameo

2023/02/27 05:32

@質問者さん 最後まで疑問のポイントがよくわかりませんでしたが、例えば interface A {} class B implements A {} class C extends B {} public class Main { public static void main(String[] args) { if (args.length == 0) throw new RuntimeException("引数がありません"); A a = null; if ("B".equals(args[0])) a = new B(); else a = new C(); C c = (C)a; } } このようにプログラム引数として渡すだけでコンパイルエラーに出来ないケースがあるのは分かるかと思います。なので問題だからというわけではありません。 ただ一度アップキャストしたら、以降(明示的であれ)原則ダウンキャストしないのが普通です。またダウンキャストする場合もinstanceofなどを挟んでExceptionの発生を抑えます。 なお今回のケースはC extends BでCにキャストするというやや意地悪なケースでのキャストなのでコンパイルエラーになっていないだけで、Javaは割とコンパイルエラーになりますよ。環境にも依りますが・・・ とりあえず突然解決後にコメントがあったようなので、補足のような話をしましたが、今度こそこの辺で・・・
guest

回答1

0

ベストアンサー

--実際に動作しているのはB型のインスタンスであり、C型としての差分を持たない--

 C型の変数を定義したが、Cのメソッドを扱えるか否か。中身は、Bのインスタンス。それはCのメソッドを継承していないので、否である。

投稿2023/02/26 12:06

logres_Fan

総合スコア164

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問