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

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

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

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

Q&A

解決済

1回答

736閲覧

staticメソッドとインスタンスメソッドで継承についての違いがあるのか知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

0クリップ

投稿2023/02/23 01:37

実現したいこと

実行結果がなぜ
Super : x
Super : y
Sub:methodA()
Sub : methodB()
でなく
Super : x
Super : y
Super:methodA() //ここがわからない
Sub : methodB()
になるか知りたい

前提

スーパークラスのメソッドを呼び出した時、継承関係にある場合は子クラスのメソッドが使用されると思って思っていたのですがそもそもそれが間違っているかも。
staticメソッドとインスタンスメソッドで継承についての違いがあるんですかね

発生している問題・エラーメッセージ

The static field Super.x should be accessed in a static way The static method methodA() from the type Super should be accessed in a static way

該当のソースコード

class Super { static String x = "Super : x"; String y = "Super : y"; static void methodA() { System.out.println("Super:methodA()"); } void methodB() { System.out.println("Super:methodB()"); } } class Sub extends Super { static String x = "Sub: x"; String y = "Sub: y"; static void methodA() { System.out.println("Sub : methodA()"); } void methodB() { System.out.println("Sub : methodB()"); } } public class Main { public static void main(String[] args) { Super obj = new Sub(); System.out.println(obj.x); System.out.println(obj.y); obj.methodA(); obj.methodB(); } } 実行結果 Super : x Super : y Super:methodA() Sub : methodB()

初めてで至らない点もありますがよろしくお願いいたします。
徹底攻略Java SE 11 Silver問題集 P.341

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

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

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

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

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

jimbe

2023/02/23 05:59

実際に実装上で問題になっているのでなければ、QAより意見交換に書かれたほうが良いかもしれません。
guest

回答1

0

ベストアンサー

staticメソッドというのは

どのメソッドが実行されるかがコンパイル時点で 静的に(=static) 決まる

からそう呼ばれるのです。


Foo.bar() の形の式で、bar がstaticメソッドなのか非staticメソッドなのかはコンパイル時点でチェックされます。

非staticメソッドであれば、この呼び出しによって最終的にどのクラスのメソッドが実行されるかはコンパイル時点では決まりません。質問の例で (Super型の式).methodB()の呼び出しがSubの実装を実行しているのでこちらは理解されていると思います。

staticメソッドであれば、この呼び出しによって最終的にどのクラスのメソッドが実行されるかがFoo式の型だけで、コンパイル時点で、静的に、決まります。

質問の例だと、objという式がSuper型だからSuper.methodAが呼び出されることがコンパイル時に決まったのです。

その性質があるからstaticという形容がされているのです。


staticメソッド呼び出しでは、式の値(実行時に式を評価した値)は関係なく、式の型だけを見ているということは下のようなmainメソッドを試すとわかるでしょう。

public static void main(String[] args) { Super sup = null; Sub sub = null; sup.methodA(); sub.methodA(); ((Super)sub).methodA(); }

「値の型」と「式の型」を、別のものとして捉える力(考え方)が必要になってきます。


(追記)
上記のように「値の型」と「式の型」の区別がついてないと話がややこしくなるため(と私は思っているだけなのですが)、staticメソッドの呼び出しは式.メソッド名()ではなくクラス名.メソッド()と書くのが普通です。
コンパイル時点で呼び出し先が決定する以上、あえて式.メソッド名()という書き方をする理由がありません。

(勉強の最中だと思ってスルーして書かなかったのですが一応追記でした)

投稿2023/02/23 02:19

編集2023/02/23 03:39
quickquip

総合スコア11029

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

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

退会済みユーザー

退会済みユーザー

2023/02/23 14:05

質問の例だと、objという式がSuper型だからSuper.methodAが呼び出されることがコンパイル時に決まったのです。 その性質があるからstaticという形容がされているのです。 ここまで理解できました。ありがとうございます! その後のstaticメソッドの呼び出しを試してみたところ Super:methodA() Sub : methodA() Super:methodA() と表示されました 一つ目はスーパークラスのstaticだからSuper:methodA() 二つ目はスーパークラスのstaticだからSuper:methodB() 三つ目は((Super)sub)としてキャストしていて変換するとスーパークラスのstaticだからSuper:methodA() という考えでよろしいでしょうか? キャストを使用した参照型の型変換は あるクラスのインスタンス化→ インスタンス化されたオブジェクトのスーパークラスやインターフェースの型に代入→ 元のクラス(型)に戻す という風に使わないとClassCastExceptionのエラーになってしまうと思ったのでそこだけ気になりました。 よければご教授ください。とてもわかりやすく説明していただけて助かっております。
xebme

2023/02/24 05:45 編集

Super obj = new Sub(); Sub obj1 = (Sub) obj; <-- ダウンキャスト成功(objがSub型でなければ失敗する) obj1.methodA(); methodAはobj1の型宣言に依存 以下は予想どおりの結果になりますが、動的なキャストと静的な型の決定は切り離して考えてください。 ((Sub) obj).methodA(); ((Super)((Sub) obj)).methodA(); コンパイラがどんなバイトコードを生成したかは、javapでinvokestaticを見れば分かります。
quickquip

2023/02/24 06:47

「式の型」という概念を持っていただきたいと思ってキャストを例として書きました。 プリミティブ型でない式のキャストは、「式」の型を変更するだけです。 子クラス型の「式」を親クラス型にキャストするのは、実行時にClassCastExceptionを起こさないことが分かっているのでなにも問題ありません。 親クラス型の「式」を子クラス型にキャストするのは、実行時にClassCastExceptionを起こすかもしれません。実行時に値として何が入っているかに依ります。 まったく継承関係がない型にキャストするのは、(nullでない限り)実行時に失敗すると分かっているのでコンパイル時点で失敗します。 こんな整理でいかがでしょうか。深掘りしたければもう少し例を書くことは出来るでしょうが質問から離れるのでコメントにしました。
退会済みユーザー

退会済みユーザー

2023/02/24 13:20

なるほど理解できました。とてもわかりやすかったです!わざわざ時間を取っていただきありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問