- PR -

キャストについて

投稿者投稿内容
ゴングラッチェ
常連さん
会議室デビュー日: 2006/03/03
投稿数: 36
投稿日時: 2006-03-30 16:54
引用:
どうやら、箱(変数宣言)と中身(インスタンス生成)以外にも、配列そのものと配列の中身を同一視しているらしい・・・


ぶざいくろうさんの指摘は当たってそうですね。
OZさんは「配列の中身がStringならば、その配列はStringの配列である。」と思っているのではないでしょうか。これが違います。正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。

混乱の基かもしれませんが、ここで理解の糸口になりそうな問題をだしてみます。『Javaの配列は、配列そのものがインスタンスとして存在します。』さて、Object配列のインスタンスをString配列にダウンキャストできるでしょうか?
ヒント:ObjectのインスタンスをStringにダウンキャストできないのは実験済みですね。
OZ
常連さん
会議室デビュー日: 2006/02/27
投稿数: 45
投稿日時: 2006-03-30 17:31
皆様、ながながとありがとうございます。

引用:

Edossonさんの書き込み (2006-03-30 16:36) より:
さて性懲りもなく(^ ^;
引用:

OZさんの書き込み (2006-03-30 15:33) より:

obj instanceof String[])はtrueとなっていますし。


本当に?



すみません、激しくうそをついていました。falseです・・・。
(obj[n] instanceof String)と勘違いしていました

引用:

というわけで、こういうのは自分で叩いて身につけるのが、一番速いですよ。
コード:
Object[] obj = null;
String[] str = null;

obj = new String[3];
obj[0] = new String();
obj[1] = new String();
obj[2] = new String();
System.out.println("obj is instance of String[] : " + (obj instanceof String[]));
str = (String[])obj;// <-- さて、ここではClassCastExceptionは発生する?

obj = new Object[3];
obj[0] = new String();
obj[1] = new String();
obj[2] = new String();
System.out.println("obj is instance of String[] : " + (obj instanceof String[]));
str = (String[])obj;


今回は、実際に走らせてみました。m(_ _)m



指摘された場所ではClassCastExceptionは発生せず、一番最後で発生しました。

引用:

ゴングラッチェさんの書き込み (2006-03-30 16:54) より:
引用:
どうやら、箱(変数宣言)と中身(インスタンス生成)以外にも、配列そのものと配列の中身を同一視しているらしい・・・


ぶざいくろうさんの指摘は当たってそうですね。
OZさんは「配列の中身がStringならば、その配列はStringの配列である。」と思っているのではないでしょうか。これが違います。正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。



これは、配列の場合だけでしょうか?

引用:

正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。



が理由でキャストできないのであれば、

引用:

コード:
1 : Object obj = new String(); 
2 : Object obj2 = new Object(); 
3 : obj = new String("文字1"); 
4 : obj2 = new String("文字2"); 
5 : String str = (String)obj; 
6 : String str2 = (String)obj2;


4の時点でobj2はStringになってるだろ。(格納してる方じゃなく実体の方)
つまり、Object obj2 = new String("文字2");と結果同じなんだよ。



の場合も、5,6でエラーになるはずでは???
何か根本的に勘違いしているでしょうか・・・。

引用:

混乱の基かもしれませんが、ここで理解の糸口になりそうな問題をだしてみます。『Javaの配列は、配列そのものがインスタンスとして存在します。』さて、Object配列のインスタンスをString配列にダウンキャストできるでしょうか?
ヒント:ObjectのインスタンスをStringにダウンキャストできないのは実験済みですね。



ひょっとして、「できない」でしょうか?

■配列ではない場合
コード:
1 : Object obj = new Object();
2 : obj = new String("hoge");


1:当然、Object型
2:ここでインスタンスはString型に変更
よって、キャスト可能。

■配列の場合
コード:
1 : Object[] obj = new Object[3];
2 : 
3 : obj[0] = new String("hoge1");
4 : obj[1] = new String("hoge2");
5 : obj[2] = new String("hoge3");


1のイメージ
obj<------------------ Object[]型
|---obj[0]<---------- Object型
|---obj[1]<---------- Object型
|---obj[2]<---------- Object型

3,4,5のイメージ
obj<------------------ Object[]型
|---obj[0]<---------- String型
|---obj[1]<---------- String型
|---obj[2]<---------- String型

従って、個々の要素はインスタンスがString型に変わっているからキャスト可能だけど
配列自体はObject[]型のままなのでString[]からObject[]へのキャストはできないという事でしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-03-30 18:02
あれ? 何か長引いてますね。

引用:

OZさんの書き込み (2006-03-30 17:31) より:

従って、個々の要素はインスタンスがString型に変わっているからキャスト可能だけど
配列自体はObject[]型のままなのでString[]からObject[]へのキャストはできないという事でしょうか?


「配列自体」というと、どちらなのかわかりませんよね。
入れ物は Object[] でも問題ないですから。

配列の実際のインスタンスの型などと表現すれば良いのかな。
(配列の中身と書くと要素になるので)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2006-03-30 18:15
引用:

OZさんの書き込み (2006-03-30 17:31) より:

指摘された場所ではClassCastExceptionは発生せず、一番最後で発生しました。


感想はそれだけですか?
自分でいうのもなんですが。
引用:

引用:

ゴングラッチェさんの書き込み (2006-03-30 16:54) より:

ぶざいくろうさんの指摘は当たってそうですね。
OZさんは「配列の中身がStringならば、その配列はStringの配列である。」と思っているのではないでしょうか。これが違います。正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。



これは、配列の場合だけでしょうか?


参照型の変数はすべてです。
引用:

引用:

正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。



が理由でキャストできないのであれば、

引用:

コード:
1 : Object obj = new String(); 
2 : Object obj2 = new Object(); 
3 : obj = new String("文字1"); 
4 : obj2 = new String("文字2"); 
5 : String str = (String)obj; 
6 : String str2 = (String)obj2;


4の時点でobj2はStringになってるだろ。(格納してる方じゃなく実体の方)
つまり、Object obj2 = new String("文字2");と結果同じなんだよ。



の場合も、5,6でエラーになるはずでは???
何か根本的に勘違いしているでしょうか・・・。


すでに他の方が指摘してますが、3,4で、参照変数を両方とも、
Stringインスタンスへの参照に、上書きしてます。
1,2で代入した参照先なんか、吹っ飛んでますよ。
引用:

引用:

混乱の基かもしれませんが、ここで理解の糸口になりそうな問題をだしてみます。『Javaの配列は、配列そのものがインスタンスとして存在します。』さて、Object配列のインスタンスをString配列にダウンキャストできるでしょうか?
ヒント:ObjectのインスタンスをStringにダウンキャストできないのは実験済みですね。



ひょっとして、「できない」でしょうか?


私の先ほどのサンプルそのものです。
引用:

■配列ではない場合
コード:
1 : Object obj = new Object();
2 : obj = new String("hoge");


1:当然、Object型
2:ここでインスタンスはString型に変更
よって、キャスト可能。


何で「変更」なんて表現しているのかが不明。
この辺が、鍵かもしれません。
「犬」は「動物」ですが、「動物」と呼んだところで、「動物」そのものに変化するわけではありません。
「動物」として取り扱うのに、なんの支障もない、というだけで、「犬」には変わりない。
だから、ダウンキャストもできるわけで。
引用:

■配列の場合


考えることは、1度にひとつだけにしましょう。
OZ
常連さん
会議室デビュー日: 2006/02/27
投稿数: 45
投稿日時: 2006-03-30 18:46
皆様、ご丁寧にありがとうございます。

引用:

引用:

■配列ではない場合
コード:
1 : Object obj = new Object();
2 : obj = new String("hoge");


1:当然、Object型
2:ここでインスタンスはString型に変更
よって、キャスト可能。


何で「変更」なんて表現しているのかが不明。
この辺が、鍵かもしれません。



申し訳ございません。正確な言い回しができていませんで。
1:Object型の参照変数にObject型のインスタンスへの参照が設定される
2:参照変数の型はObject型のままだが、参照先はnewされたString型へ変更
という言い方であっているでしょうか?

配列ではない場合は理解できていると思います。(・・・多分)

皆様の説明を読んでいるうちに、自分では
引用:

どうやら、箱(変数宣言)と中身(インスタンス生成)以外にも、配列そのものと配列の中身を同一視しているらしい・・・

OZさんは「配列の中身がStringならば、その配列はStringの配列である。」と思っているのではないでしょうか。これが違います。正しくは「Objectの配列の中身にStringが入っているだけで、配列はObjectの配列である。」となります。配列の型は中身によって変わることはありません。


が、やはり理解できていないように思います。

これですと、
コード:
Object obj = new Object();
obj = String("hoge");


も、「Object変数の中身が、ObjectインスタンスからStringインスタンスへ参照先が変わっただけで変数はObjectのままだからキャストはできない」と受け取れるのですが、これは間違いというのは実証済みですよね。

とすると、違いは「配列か、配列ではないか」に行き着いてしまうのですが。
ぶさいくろう
ぬし
会議室デビュー日: 2005/11/22
投稿数: 1232
お住まい・勤務地: 川崎市(は俺も含めてロクな人間が住んでないよw)
投稿日時: 2006-03-30 18:53
すまねぇ、みんな。
オラ、なんか頭痛くなってきたぞ・・・orz
OZ
常連さん
会議室デビュー日: 2006/02/27
投稿数: 45
投稿日時: 2006-03-30 19:01
引用:

ぶさいくろうさんの書き込み (2006-03-30 18:53) より:
すまねぇ、みんな。
オラ、なんか頭痛くなってきたぞ・・・orz



申し訳ございません!!
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-03-30 19:44
型については、やや極端に言えばどうすればコンパイルが通るようになるか、というコツを知っていれば不自由することはありません。
#例外処理についてはとりあえずコンパイルが通ればいい、って考え方は危険かもしれません

建設的でないかもしれませんが、ひとまずは "Javaのクセ" 程度に考えてしまってはいかがでしょうか。
言語によっては OZ さんの考えるとおりのコーディングで実行できる種類のもあります。(よね?)
当面はコンパイルが通って、ClassCastException が発生しない「感覚」をつかめればいいと思います。
コーディングを重ねるうちに自ずと仕組みがわかってくるかと。
それなりにJava のプログラミング経験がある人でも、String[] strArray = (String[])objArray; なんて表記はしょっちゅうしてしまうのではないでしょうか。
でも、間違いはコンパイラやIDEが即座に指摘してくれます。
「正しくはどう書くべきか」というルールは知っておく必要がありますが。

文法や言語のルールについてはコンパイラに考えて貰って、我々はアルゴリズムや設計にフォーカスすることをオススメします。

もちろん探求するのも大事なことですので、「このままではなんだか気が済まない!」という気分であればがんばってください!

[ メッセージ編集済み 編集者: インギ 編集日時 2006-03-30 19:46 ]

スキルアップ/キャリアアップ(JOB@IT)