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

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

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

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

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

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Q&A

解決済

1回答

905閲覧

javaの型パラメータで継承元指定の変数に代入できない言語仕様?の理由がわからない

yamagish

総合スコア2

Generics

Genericsはパラメトリックなポリモーフィズムの形態であり、.NET やJavaなど、様々な言語に実装されています。C++のテンプレートと同等の機能を持ち合わせています。

Java

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

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

0グッド

1クリップ

投稿2021/08/31 11:56

初めての質問です。よろしくおねがいします。

知りたいこと

添付のソースコードで、「map3 = map1」がコンパイルエラーになります。
やりたいことを実現する解決策はあるのですが、
そもそも、これをコンパイルエラーで弾く理由がわからなくて困っています。

特化型のオブジェクトは、
インタフェースや継承元クラスのインタフェースでアクセスする場合、
インタフェースや継承元クラスの型の変数に保持できます。
(「これは出来る」の部分が該当)

この考えで、「map3 = map1」を弾く理由が理解できません。
何か、腑に落ちる理由があると思っています。

該当のソースコード

java

1import java.util.HashMap; 2import java.util.Map; 3 4public class TestTypeParameter { 5 6 public static void main(String[] args) { 7 Child child = new Child(); 8 Parent parent = child; // これは出来る。 9 Map<String, Child> map1 = child.hoge(); 10 print(map1); 11 12 Map<String, Parent> map2 = new HashMap<String, Parent>(); 13 map2.putAll(map1); 14 print(map2); 15 16 // Map<String, Parent> map3 = map1; // コンパイルエラー★ 17 Map<String, ? extends Parent> map4 = map1; // これなら出来る。 18 print(map4); 19 20 Map map5 = map1; 21 Map<String, Parent> map6 = map5; 22 print(map5); 23 print(map6); 24 } 25 static void print(Map<String, ? extends Parent> map) { 26 for (Map.Entry<String, ? extends Parent> entry : map.entrySet()) { 27 String key = entry.getKey(); 28 Parent val = entry.getValue(); 29 System.out.println(key + " : " + val); 30 } 31 System.out.println(); 32 } 33 static class Parent { 34 public Map<String, ? extends Parent> hoge() { 35 Map<String, Parent> map = new HashMap<String, Parent>(); 36 map.put("1", new Parent()); 37 map.put("2", new Parent()); 38 map.put("3", new Parent()); 39 return map; 40 } 41 } 42 static class Child extends Parent { 43 44 @Override 45 public Map<String, Child> hoge() { 46 Map<String, Child> map = new HashMap<String, Child>(); 47 map.put("1", new Child()); 48 map.put("2", new Child()); 49 map.put("3", new Child()); 50 return map; 51 } 52 } 53}

試したこと

コンパイルエラー部分以外は、異常発生なくmainが終了する確認はしています。

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

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

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

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

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

guest

回答1

0

ベストアンサー

このようなコードを書けば、型安全性が破綻します。

java

1Map<String, Child> map1 = child.hoge(); 2// 仮にできたとして 3Map<String, Parent> map3 = map1; 4 5map3.put("foo", new Parent()); 6// map1の型から言えばChildになるが、 7// 上の行で、実際にはParentのインスタンスを入れてしまっている 8Child invalid = map1.get("foo");

同様のことをMap<String, ? extends Parent>でやろうとしても、putの引数型に?が入るので、そちらで失敗するようになります。

投稿2021/08/31 12:05

maisumakun

総合スコア145121

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

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

yamagish

2021/08/31 12:28

なるほど… 更新について考慮が抜け落ちていました。 ワイルドカード指定した場合、型指定できなくなることで、追加の更新ができなくなるのですね… ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問