Javaの言語仕様(?)についてお教え下さい。
参照変数の型がインスタンスのスーパークラスの型の時、クラス変数/メソッドとインスタンス変数/メソッドの見え方が納得いかずに困っています。
以下のような条件の時です。
・クラスが2つあり、1つはもう1つのクラスを継承しています。
それぞれを「スーパー」「サブ」と以下で呼びます。
・インスタンスは"サブ"の型です。
・上記インスタンスへの参照変数は"スーパー"のクラスの型です。
・"スーパー"、"サブ"ともに【同名】の「クラス」変数/メソッド、「インスタンス」変数/メソッドがあります。
この場合に、"サブ"のインスタンスを参照している"スーパー"の型の変数を介し、それらにアクセスしたらどれが見えるか?という疑問です。
実験結果では以下のようになりました。
[フィールド] [メソッド]
[1.static ] スーパーの スーパーの
[2.非static] スーパーの サブの
納得いかないのは「2.非static」で「フィールド」が、「スーパーの」になるところです。
これも「サブの」になると思っていました。
なぜサブクラスのが見えないのでしょうか?
同名の変数なのでスーパークラスのはサブクラスので隠れされ、サブクラスのが見えると思っていたのですが。
参考書には以下のように書いてありました。
フィールドの場合、参照変数の型のものが見える。
メソッドの場合、インスタンスの型のものが見える。
私には不自然に感じられるのですが、「こういう仕様だから。」と納得するしか無いのでしょうか?
「なぜこうなるか」について説明がある文献、サイトなどありましたらお教えください。
参考までに以下が実験したサンプルコードと結果です。長くて申し訳ありません。
「サンプルコード」
public class Super {
static int staticField = 10;
int instanceField = 100;
static void staticMethod() {
System.out.println( "staticField = " + staticField );
}
void instanceMethod() {
System.out.println( "instanceField = " + instanceField );
}
}
public class Sub extends Super {
static int staticField = 90;
int instanceField = 900;
static void staticMethod() {
System.out.println( "staticField = " + staticField );
}
void instanceMethod() {
System.out.println( "instanceField = " + instanceField );
}
}
public class TestStatic {
public static void main(String[] args) {
// インスタンスはSub、参照変数もSub、という状態。
Sub sub = new Sub();
System.out.println( "実験1" );
System.out.println( "1.クラス変数 " + sub.staticField );
System.out.print( "2.クラスメソッド " );
sub.staticMethod();
System.out.println( "3.インスタンス変数 " + sub.instanceField );
System.out.print( "4.インスタンスメソッド " );
sub.instanceMethod();
// インスタンスはSub、参照変数はSuper、という状態。
Super sup = new Sub();
System.out.println( "実験2" );
System.out.println( "5.クラス変数 " + sup.staticField );
System.out.print( "6.クラスメソッド " );
sup.staticMethod();
System.out.println( "7.インスタンス変数 " + sup.instanceField );
System.out.print( "8.インスタンスメソッド " );
sup.instanceMethod();
}
}
「結果」
実験1
1.クラス変数 90
2.クラスメソッド staticField = 90
3.インスタンス変数 900
4.インスタンスメソッド instanceField = 900
実験2
5.クラス変数 10
6.クラスメソッド staticField = 10
7.インスタンス変数 100
8.インスタンスメソッド instanceField = 900
納得が行かないのは7のところです。
以上よろしくお願いいたします。
No.3ベストアンサー
- 回答日時:
この辺りは「なんで?」、「どうして?」とかって考え出すと、かなり難解な所ですね。
私自身、SJC-Pを受験する際も「『親 new 子』はOK。」みたいな感じで機械的に覚えていましたからね。(コバリアント[共変戻り値]とかも、何となしには分かるけど、未だに使いこなすレベルまでにはなってないなあ。)>「なぜこうなるか」について説明がある文献、サイトなどありましたらお教えください。
取り敢えずは、いつものようにお勧め過去ログ。
Javaのメモリの管理
http://oshiete1.goo.ne.jp/qa1797536.html
staticのメリット、デメリット
http://oshiete1.goo.ne.jp/qa1355755.html
ただ、文章ばかりだと何がなんだかいまいち分からないと思うので、イラスト付きのはこっち。
HOME > Java開発Tips > Technology & Programming
よくある誤解、あやふやな知識をQ&A形式で総整理!
Javaの“常識”、“非常識”
第2回 言語仕様編
http://www.itarchitect.jp/technology_and_program …
JVM のメモリ構造
http://www.nextindex.net/java/perform/storage.html
用は、サブクラスによるオーバーライド(メソッドの再定義)っていうのは、具体的にはJVMスタックによって実現されているわけですね。
で、私の方はどうかというと、以下のサイトでも見ながら何か面白いものが作れるかなあと考えていたのでしたが、全然ダメでした。(まだまだ修行が足りないなあ・・。)
com.sun.jdi
インタフェース StackFrame
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/ …
参考URL:http://www.gihyo.co.jp/books/syoseki-contents.ph …
ご回答ありがとうございます。
おかげさまで
・メソッドがオーバーライドされる
・フィールドはオーバーライドされない
というメカニズムは良く分かりました。
ただ、「フィールドはオーバーライドされない」の理由というか「思想」がやっぱりしっくりきません。
メソッドはポリモルフィズムの実現のためにオーバーライドされるのは自然だと思いますし、
ついでと言ってはなんですが、フィールドも同様にすればいいのにと感じてしまうので・・・
これはもうとりあえず「そういうもの」と受け入れることにします。
今までもオブジェクト指向で
「ルールは分かったが、なんでこんな?」
というのは色々ありました。
ですが「ある日突然腑に落ちた。納得できた。」という瞬間が来ました。
今回もそのうちそういう瞬間が来ることを信じてみます。
色々とご教示ありがとうございました。
No.2
- 回答日時:
Java言語仕様によると、
・同名のフィールド宣言によってスーパークラスのフィールド宣言は隠蔽される
・参照式の型によって示されるクラス内のフィールドにアクセスする
とあります。
要するにフィールドはオーバーライドしないということです。
サブクラスのフィールドにアクセスするためには
System.out.println( "7.インスタンス変数 " + ((Sub)sup).instanceField );
とする必要があります。
get/setメソッドを用意してフィールドに直接アクセスできないようにするのがよろしいわけです。
参考URL:http://www.y-adagio.com/public/standards/tr_x_00 …
ご回答ありがとうございます。
やっぱり結論としては「そういうもの」と受け入れるしか無いようですね。
言語仕様として明確に規定されているということで納得(諦め?)できました。
ありがとうございます。
それと私は「隠蔽される」と「オーバーライドされる」を混同し、同一視していたようです。
これも勉強になりました。
>get/setメソッドを用意してフィールドに直接アクセスできないようにするのがよろしいわけです。
アクセサという奴ですよね?
今回の件の仕様が正直納得いかない以上、罠にハマらないようにするためにこのアクセサを使うということを徹底したいと思います。
色々と情報・アドバイスをありがとうございました。
No.1
- 回答日時:
supにSubクラスのインスタンスを入れているようにみえるけど、
実際はSuperクラスのインスタンスになっているため。
「Super sup = new Sub()」という書き方はSubクラスからSuperクラスの定義だけを抜き出したインスタンスを作っている、というイメージを持つと不自然には見えないと思います。
この回答への補足
ご回答ありがとうございます。
ですが、
>supにSubクラスのインスタンスを入れているようにみえるけど、
>実際はSuperクラスのインスタンスになっているため。
は違うのでは?
そうだとすると以下の結果の説明がつかない気がします。
8.インスタンスメソッド instanceField = 900
これはSubクラスのインスタンス中のインスタンス変数を出力しているのだと思うのですが。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/17 18:41
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/06 09:28
- その他(プログラミング・Web制作) このプログラミングをどう組みますか? Googlecolabでやってるんですが、出来る方お願いします 1 2022/07/13 10:52
- Java インスタンス ダウンキャストについて以下の解釈であっているか教えて欲しいです。 サブクラスをスーパー 1 2022/03/27 18:53
- その他(プログラミング・Web制作) pythonのプログラムについての質問です。 1 2023/05/26 10:31
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- Visual Basic(VBA) マクロVBA 1シートをまとめる 閉じ方 初心者 SOS! 1 2022/06/17 14:54
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
インスタンス参照でアクセスで...
-
複数の変数を宣言する時、同時...
-
private static という変数の修飾
-
変数名の付け方
-
VB.NET getとsetの概念がわかり...
-
変数の参照でエラーが出てしま...
-
C# インスタンスの破棄
-
抽象クラスのインスタンス生成...
-
オブジェクト参照がオブジェク...
-
他のファイルの変数参照
-
クラス型がインスタンス化され...
-
エクセル(複数インスタンス)...
-
C#において、同じインスタンス...
-
VB6.0のクラスで、自分自身のイ...
-
マルチスレッドでのインスタン...
-
文字列を日付に変換でParseExce...
-
String型もしくはint型をIntege...
-
VC#での24ビットbmp形式での保...
-
newしないインスタンス?実体化...
-
生成したインスタンスを削除す...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
変数名の付け方
-
インスタンス参照でアクセスで...
-
複数の変数を宣言する時、同時...
-
private static という変数の修飾
-
VB.NET getとsetの概念がわかり...
-
C#において、同じインスタンス...
-
生成したインスタンスを削除す...
-
C# インスタンスの破棄
-
newしないインスタンス?実体化...
-
SQLを連続発行する時の正しい(?...
-
「インスタンス」の意味をわか...
-
文字列を日付に変換でParseExce...
-
変数の参照でエラーが出てしま...
-
フォームの存在をチェックする方法
-
javaのクラスの作り方、エラー...
-
オブジェクト参照がオブジェク...
-
String a = "a"; と String b =...
-
エクセル(複数インスタンス)...
-
C#「オブジェクト参照が必要で...
-
他のファイルの変数参照
おすすめ情報