戻り値とキャスト
以下のようなメソッドがある
Object getObject()
String getString()
それに対してそれぞれを呼び出してみた結果ひとつだけ
エラーが出た
1. Object obj = getObject();
2. String str = getObject();
3. obj = getString();
4. str = getString();
答えは2番である
オブジェクト指向では
親クラスの変数に子クラスのインスタンスを入れれる
子クラスの変数に親クラスのインスタンスは入れれない
これは常識であると思いたい
JavaではすべてのクラスがObjectクラスを継承しているので
String → Object
であるため2番以外は問題ない
ここで、Objectの変数の中にはStringのインスタンスを入れれると
いう性質を利用して
getObject()内でStringのインスタンスをObjectとして扱っていた場合を考える
この場合戻ってきた値はObjectとして扱われているが
実際にはStringが入っているため
Stringの変数に入れても問題ない気がする
そこでそういう場合にはキャストをするのは常識であると思いたい
× String str = getObject();
○ String str = (String)getObject();
実はここまでが序章である
ここから本題に入る
実に長い…
int i = (int)getObject();
このプログラムはどうなるか?
答えはエラーである
intはプリミティブ型なのでObjectを継承していない
整数型が帰ってくるのだとしたらそれは
Integer型であるので
Integer i = (Intger)getObject();
int ii = i.getInt();
のような形となる
ラッパークラスと利用することになる
今回は値を取得するだけだったが
値を格納したり、それを取得したりって操作が
多くなると実際には様々なクラスのインスタンスが格納される場合がある
注意が必要である
ちなみにJava1.5以降のバージョンでは
ラッパークラスとプリミティブ型を暗黙的に変換してくれるので
int i = (Intger)getObject();
と書ける
ただし、特に理由がない場合は総称型を使うようにしよう
if(hoge() == true)
見つけてしまったこんなもの
if(hoge() == true) {
・・・
・・・
}
hoge()はtrueかfalseを返す関数である
これは
if(hoge()) {
と同等である
if文のカッコの中では一通りの処理が行われたあと
最終的にtrueかfalseを残せばそれを評価して分岐する
要するに
if(true)は常に処理され
if(true == true)はtrueがtureと同値なので常に処理される
ここで上の例だが
hoge()はtrueかfalseを返すのでこのif文は
if(true == true)
if(false == false)
のどちらかとなる
これは
== true
がなくても同じ結果となるのは見ていただければわかると思う
というわけで
tureまたはfalseで値が帰る場合は
そのままif文に書くこと
以上
無駄なnewをしない
こんなプログラムを見かけた
List
list = getList();
getList()は別な場所で定義されているものとする
一方私の書くプログラムはこんな感じ
List
上のプログラムを書いた人は
下のプログラムを見てなぜ初期化せずに動くのか?
という疑問をもったらしい
今日はなぜかについて語ることにしよう
まず上のプログラムについて考える
new ArrayList
でArrayListのインスタンスを生成し
その参照先をlist変数に格納する
次にgetList()について考える
このクラスはList
メソッド内部でListのインスタンスが生成される
次に考えるのgetListでreturnされるものである
メソッド内では生成したインスタンスの参照先を
格納した変数が用意され、それがreturnされる
したがって戻ってくる値は参照先がどこにあるかという情報で
実際のインスタンスは同一のものを参照することになる
さて、ここで戻り値を格納する変数である
呼び出し元のlist変数を利用している
ここに参照先が格納される
その結果、listの値が書き換えられすでにnewしたArrayListを参照する
変数がなくなる
ここまでおわかりいただけただろうが
ArrayListは無駄な変数となってしまったわけである
めでたしめでたし〜〜
値渡しと参照渡しについて
関数に引数を渡す時の話
値渡しとか参照渡しとかって話はプログラマなら
多分きいたことがあるのではないかと思われる
今日はこの違いについて語る
このカテゴリでは変数の値がメモリ上にどのように確保されるかを
たびたび話しているので特に前触れなくそういう話を使わせてもらう
変数に値を格納する時、直接値を確保する、別な場所に確保して
そこを参照するの2パターンのどちらかであることが多い
C/C++の場合普通の変数とポインタ
Javaの場合プリミティブ型と参照型
みたいな感じである
さて、関数に値を渡す時の話だが
この時、変数の値をコピーしてそれを引数として与える
さて、この結果どうなるかというと
直接値を確保する場合、値がコピーされてそれが関数に渡される
その結果、値こそ一緒だが、
元の変数とは何ら関係のない新しい変数となるわけである
なのでどんなに値を変更しても元の値には影響がない
(C++でクラスの変数を渡したりすると問題が起こるがそれはまた別の機会に書かせてもらうことにしよう)
一方、別な場所に確保してそこを参照する場合
前者と同様、変数の中の値をコピーして渡すため、どこを参照しているか
という情報がわたる
その結果、中の値は同じものを見ることになる
なので関数の中で値を変えたりすると元の値も変わってしまうので注意が必要である
この話題に関してはまだまだ書きたい事や、補足事項が割とあるが、
長くなるので今回はこの辺にしておこう
浦島太郎と竜宮城の時間の流れ方について
皆さん、浦島太郎はご存じだろうか?
知らないといわれるとこの後の話が続かないのでこの記事を読んでる人はみんな知ってる前提とさせてもらう
さて、この浦島太郎では、竜宮城に行っている間にものすごい時間が流れていたことになっている。しかし、竜宮城の中ではそれほど時間は経っていない
なぜ、このような現象が起きたのか?
今回はこれについて考えたいと思う
皆さん、相対性理論はご存じだろうか?
これについては私もあまり詳しくない
詳しくないが、今回はこの理論を使う必要がある
あるのだが、私は詳しくないのでこの話が間違っているかもしれない
という前振りの元、始める
相対性理論では光の速さは常に一定である
普通の物理の理論だと、時速60キロで走っている車の中で
時速40キロで走ると外から見ると時速100キロで走っていることになる
(ちなみに時速40キロは100メートル走の世界レベル)
しかし、光は静止した人が懐中電灯を照らしても
動いている物体から懐中電灯を照らしても変わらない
さて、ここからは私がよくわかっていない領域に入る
たぶん内容はかなり分かりづらいです。ご了承ください
静止している状態から光を照射する、これをAとする
光速に近い速度で移動している物体の中から光を照射する、これをBとする
あるα地点でA,Bともに照射を始めた時、β地点に到着する時間は
先ほどの光の速度が常に一定であるはずなので一致する
しかし、Bは光速に近い速度で移動してるのでAから見たBの光速がAを移動した光より遅いことになってしまう
この矛盾を解消するため、Bの中のほうがAより時間の流れが遅いことになる
たぶんこれが相対性理論だったはず
(誰かもっと詳しい人やわかりやすく書ける人がいたらコメントとかでお願いします)
さて、よくわかりずらいが要するに光速に近い速度で移動していうる物体の中は外より時間の流れが遅いのだ
ここで竜宮城の話に戻る
竜宮城は外の世界より時間の流れが遅い
この理由を解き明かすわけだったが、ここまでくればおわかりいただけるだろう
竜宮城はなんと光速に近い速度で移動していたのだ!!
さて、今回は頭を使いすぎて、知恵熱が出そうな気がしたのでこの辺にしておこう