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

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

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

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

Java

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

Q&A

1回答

3682閲覧

総称型を、別の総称型に変換するメソッドのコンパイルエラーを解消したい

crescendocres

総合スコア12

Generics

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

Java

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

1グッド

2クリップ

投稿2017/05/24 09:12

編集2017/05/25 01:37

###前提・実現したいこと
ここに質問したいことを詳細に書いてください

下記のようなOrgクラスを、インターフェースと実装クラスに分割したいと考えております。
ここで、IBar::mapメソッドに問題を抱えています。

java

1 /** 2 * オリジナルのクラス。 3 * これを、下記のインターフェースと実装クラスに分割したい。 4 */ 5 public static class Org<E> 6 extends java.util.ArrayList<E> { 7 8 /** 9 * Foo<E>を、Foo<O>に変換する。 10 */ 11 public <O> Org<O> map(final Function<E,O> mapper) { 12 return 13 super 14 .stream() 15 .map(mapper) 16 .collect(Collectors.toCollection(Org::new)); 17 } 18 19 /** 20 * Bar<E>の要素をフィルターする。 21 * ※質問の趣旨とは直接関係なし 22 */ 23 public Org<E> filter(final Predicate<E> filter) { 24 /* ロジックを簡略 */ 25 return this; 26 } 27 28 /** 29 * Bar<E>の重複する要素を削除する。 30 * ※質問の趣旨とは直接関係なし 31 */ 32 public <K> Org<E> distinct(final Function<E,K> keySelector) { 33 /* ロジックを簡略 */ 34 return this; 35 } 36 37 /** 38 * Bar<E>の要素を昇順に並べる。 39 * ※質問の趣旨とは直接関係なし 40 */ 41 public Org<E> orderBy(final Function<E, Integer> keySelector) { 42 /* ロジックを簡略 */ 43 return this; 44 } 45 46 }

java

1 /** 2 * インターフェース 3 */ 4 public interface IBar<E, L extends IBar<E, L>> 5 extends java.util.List<E>{ 6 7 /** 8 * Bar<E>をBar<O>に変換する。 9 */ 10 default 11 <O, OL extends IBar<O, OL>> 12 OL map(final Function<E,O> mapper){ 13 try { 14 Constructor<OL> con = (Constructor<OL>) this.getClass().getConstructor(); 15 OL ol = con.newInstance(); 16 17 this.stream().map(mapper).forEach(value -> ol.add(value)); 18 19 return ol; 20 } 21 catch (Exception e) { 22 return null; 23 } 24 } 25 26 /** 27 * Bar<E>の要素をフィルターする。 28 * ※質問の趣旨とは直接関係なし 29 */ 30 default L filter(final Predicate<E> filter) { 31 /* ロジックを簡略 */ 32 return (L) this; 33 } 34 35 /** 36 * Bar<E>の重複する要素を削除する。 37 * ※質問の趣旨とは直接関係なし 38 */ 39 default <K> L distinct(final Function<E,K> keySelector) { 40 /* ロジックを簡略 */ 41 return (L) this; 42 } 43 44 /** 45 * Bar<E>の要素を昇順に並べる。 46 * ※質問の趣旨とは直接関係なし 47 */ 48 default L orderBy(final Function<E, Integer> keySelector) { 49 /* ロジックを簡略 */ 50 return (L) this; 51 } 52 53 } 54 55 /** 56 * IBar実装クラス。 57 */ 58 public static class Bar<E> 59 extends java.util.ArrayList<E> 60 implements IBar<E, Bar<E>> { 61 /** 62 * ここには何も書きたくない 63 */ 64 } 65 66 /** 67 * IBar実装クラス。 68 */ 69 public static class Foo<E> 70 extends java.util.LinkedList<E> 71 implements IBar<E, Foo<E>> { 72 /** 73 * ここには何も書きたくない 74 */ 75 }

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

型の不一致: IBar<Object,IBar<Object,OL>> から Foo<Foo<Integer>> には変換できません

###該当のソースコード

java

1 public static void main(final String[] args) { 2 try { 3 // (1)このケースは問題なく動作する。 4 Bar<String> strBar = new Bar<>(...); 5 Bar<Integer> intBar = strBar.map(item -> item.length()); 6 7 // (2)このケースはコンパイルエラー 8 Foo<Foo<String>> strFooFoo = new Foo<>(...); 9 Foo<Foo<Integer>> intFooFoo = strFooFoo.map(bar -> bar.map(item -> item.length())); /* 型の不一致! */ 10 11 // (3)このケースは問題なく動作するが、こんな書き方をさせたくない 12 Foo<Foo<String>> strFooFoo2 = new Foo<>(...); 13 Foo<Foo<Integer>> intFooFoo2 = strFooFoo2.<Foo<Integer>, Foo<Foo<Integer>>>map(foo -> foo.<Integer, Foo<Integer>>map(item -> item.length())); 14 15 // (4)オリジナルのクラスでも、問題なく動作する。 16 Org<Org<String>> strOrgOrg = new Org<>(...); 17 Org<Org<Integer>> intOrgOrg = strOrgOrg.map(org -> org.map(item -> item.length())); 18 19 } 20 catch (Exception e) { 21 e.printStackTrace(); 22 } 23 }

イメージ説明

###ご質問
「型の不一致」エラーが出ている(2)について、
ソースコード側ではなく、IBarインターフェース側に何らかの手を加えて、コンパイルエラーを解消できないでしょか?

###補足情報(言語/FW/ツール等のバージョンなど)
言語:Java8(JDK1.8)
IDE:Eclipse 4.5
実行環境:Windows 10

yohhoy👍を押しています

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

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

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

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

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

swordone

2017/05/25 00:34

IBarのジェネリクスのLってどこかで使ってるんですか?
crescendocres

2017/05/25 01:33

はい、IBar別メソッドの戻り値の型として利用しています。 質問文に、そのインターフェースを追記しました。(質問の趣旨とは異なる例ですが…)
guest

回答1

0

訂正とお詫び:本件、自分はIntelliJ IDEA & Javacでビルドできたことをもって以下の回答をしましたが、eclipse 4.5.2でコンパイルエラーになることを確認しました。質問者さんに失礼な回答をしてしまった点、訂正してお詫びいたします。

以下、元の回答です

質問が成立していないような気がします。

最初に挙げておられたコードは単にthrows句のシグナチャーの問題でコンパイルエラーになっていただけですが、回答しようとしたらコードが編集されていました・・・

編集後の実装では(2)はコンパイルエラーにならないのですが・・・


なんとなくですが、明示されていない部分の文法(or 意味)エラーに引きずられてエラーが起こっているだけではないかと推測します。

自分は以下のコードで試してみましたがコンパイルエラーにはなりません。

java

1import java.lang.reflect.Constructor; 2import java.util.function.Function; 3 4public class Test1 { 5 public interface IBar<E, L extends IBar<E, L>> 6 extends java.util.List<E>{ 7 default 8 <O, OL extends IBar<O, OL>> 9 OL map(final Function<E,O> mapper){ 10 try { 11 Constructor<OL> con = (Constructor<OL>) this.getClass().getConstructor(); 12 OL ol = con.newInstance(); 13 14 this.stream().map(mapper).forEach(value -> ol.add(value)); 15 16 return ol; 17 } 18 catch (Exception e) { 19 return null; 20 } 21 } 22 } 23 24 public static class Bar<E> 25 extends java.util.ArrayList<E> 26 implements IBar<E, Bar<E>> { 27 } 28 29 public static class Foo<E> 30 extends java.util.LinkedList<E> 31 implements IBar<E, Foo<E>> { 32 } 33 34 public static void main(final String[] args) { 35 // (1)このケースは問題なく動作する。 36 Bar<String> strBar = new Bar<>(); 37 Bar<Integer> intBar = strBar.map(item -> item.length()); 38 39 // (2)このケースは問題ない。 40 Foo<Foo<String>> strFooFoo = new Foo<>(); 41 Foo<Foo<Integer>> intFooFoo = strFooFoo.map(bar -> bar.map(item -> item.length())); 42 43 // (3)このケースはIDE(IntelliJ IDEA)に「型引数の明示は冗長」と警告されます 44 Foo<Foo<String>> strFooFoo2 = new Foo<>(); 45 Foo<Foo<Integer>> intFooFoo2 = strFooFoo2.<Foo<Integer>, Foo<Foo<Integer>>>map(foo -> foo.<Integer, Foo<Integer>>map(item -> item.length())); 46 } 47}

なお、コードの編集が中途半端です。最初のコードにあったmapメソッドのthrows句を取ったのですからmainメソッドのtry-catchに意味がありません。
また、本件とは関係ありませんがmapメソッドでチェック例外を握りつぶしnullをreturnしているのはいただけません。

投稿2017/05/24 10:51

編集2017/05/24 13:33
KSwordOfHaste

総合スコア18394

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

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

crescendocres

2017/05/24 11:34 編集

ご回答ありがとうございます。 検証していただいた最中に、質問内容を更新してしまいまして、申し訳ございません。 不慣れにつき、手直ししてしまいました。 ご提示いただいたコードを、そっくりそのまま私の環境に配置してみましたが、 やはり(2)でのみコンパイルエラーとなってしまいます。 コンパイルエラーの内容は、やはり >[型の不一致: IBar<Object,IBar<Object,OL>> から Foo<Foo<Integer>> には変換できません] というものです。 EclipseとIntelliJ IDEAでは、コンパイラの仕様が違うのでしょうか…
KSwordOfHaste

2017/05/24 11:46 編集

そういうことはないと思いますが・・・なんででしょう?自分にも分かりません。 javac -Xlint:unchecked Test1.java でJDKでコンパイルするとmapの実装の方へ警告がでますが、それは本件とは関係ないと思います。 mainメソッドの方ではエラーは出ませんね・・・
swordone

2017/05/24 12:41

あ、私もEclipse使ってますが、Streamでラムダ式を使ったこの手の型推測でエラーになります。 Eclipseだと総称型がネストされると推測できないのかもしれません。
KSwordOfHaste

2017/05/24 13:27

自分もeclipse4.5.2で再現することを確認しました。javacと結果が違う理由はeclipseエディター上でのインクリメンタルコンパイラーがjavacと振る舞いが違うためと予測しましたがeclipseをバッチ的にビルドしたことがないので「こうすればビルドできる」というのを確認できませんでした。eclipse最新版ではこれが対策されてないか気になります。いずれにせよeclipse側の問題として対処するか回避コードを工夫するかで対処がかわってくると思います。
KSwordOfHaste

2017/05/24 13:42

「eclipse bug report generics compile error」で検索してみたところ、本件のようにjavacとeclipseでコンパイルエラーになるかどうかが不一致という問題がいろいろあることがわかりました。やはりeclipseのコンパイラーは独自のようです。本件そのものは見つけられてませんが、もし「本来コンパイルがOKになるはずのコードがeclipseでコンパイルできない」点を対処したい場合は最新版を試すことを検討してみてはいかがでしょうか?eclipseはレジストリーを汚さないので複数バージョンを入れてもそれほど面倒ではないと思いますので。
koko_u

2017/05/24 14:01

こんなコードを書くかどうかはさて置き、特にエラーにはなりませんねぇ。 いちおう Intellij IDEA(2017.1)と Eclipse (4.6.3)で試した。 何か設定があるのかも知れんけど、もう Eclipse の使い方を忘れた。
swordone

2017/05/24 14:43

先ほどのエラーの話は前のPCでの話でした。 今入れているEclipse4.6.2ではエラーになりませんでした。
crescendocres

2017/05/30 07:40 編集

皆様、検証していただいたうえで、ご回答ありがとうございます。 残念ながら、客先を含めた開発環境要件がEclipse 4.5.2で固まってしまっています。 ご質問に挙げたクラス(Org)は、ライブラリ(Jar)として提供しているものですが、それを利用している既存コードがコンパイルされる環境はEclipse4.5.2ですので、私の端末でのみEclipseのバージョンを上げたとしても、問題は解消されない見込みです。 ご質問に挙げたクラス(IBar、Bar、Foo等)、またはプロジェクト固有設定をどうにかする方法を考えてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問