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

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

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

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

Java

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

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

解決済

KotlinからJavaのメソッドを呼ぶ際のジェネリクス変性について

mosa
mosa

総合スコア218

Generics

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

Java

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

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

1回答

0リアクション

2クリップ

344閲覧

投稿2018/04/15 08:18

編集2018/04/17 13:35

いつもありがとうございます。

http://jenetics.io/
こちらにあるJavaのコードをkotlinで記述しようと思っています。

Kotlin

// 2.) Definition of the fitness function. fun eval(gt: Genotype<BitGene>): Int { return gt.chromosome .`as`(BitChromosome::class.java) .bitCount() } fun main(vararg args: String) { // 1.) Define the genotype (factory) suitable for the problem. val gtf = Genotype.of(BitChromosome.of(10, 0.5)) // 3.) Create the execution environment. val engine = Engine.builder({ gf: Genotype<BitGene> -> eval(gf) }, gtf) // 4.) Start the execution (evolution) and collect the result. val result = engine.stream() .limit(100) .collect(EvolutionResult.toBestGenotype()) println("Hello World:\n$result") }

「3.」のEngine.builder の部分でコンパイルエラーとなっています。
エラーは以下の通りです。

エラー

呼び出し先のメソッドの定義は以下の通りです。

Java

public static <G extends Gene<?, G>, C extends Comparable<? super C>> Engine.Builder<G, C> builder(Function<? super Genotype<G>, ? extends C> ff, Factory<Genotype<G>> genotypeFactory) { return new Engine.Builder(genotypeFactory, ff); }

ラムダ式 { gf: Genotype<BitGene> -> eval(gf) } の型は (Genotype<BitGene>) -> Int) です。

JavaとKotlinのジェネリクス変性について私が理解できていないか、理解が誤っていることが原因だと思うのですが、何が問題でどう記述するのが正しいかがわかりません。
ちょっと複雑なので混乱しているだけかもしれません。
ご教示いただければと思います。

Kotlin: 1.2.31
Java: 1.8.0_152-release-1136-b27 amd64
IntelliJ IDEA 2018.1.1 (Ultimate Edition) Build #IU-181.4445.78
Windows10


###■追記1

「3.」の部分を以下のように書き換えたところ、コンパイルは通ったのですが、実行時に以下のエラーとなってしまいました。

Kotlin

val engine = Engine.builder(java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) }, gtf).build()

IDEが出力したエラー

Error:Kotlin: [Internal Error] org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: Error type encountered: (???..???) (FlexibleTypeImpl). Cause: Error type encountered: (???..???) (FlexibleTypeImpl). File being compiled at position: (26,3) in C:/Users/mosa/Documents/hoge/src/main/java/HelloWorld.kt The root cause was thrown at: KotlinTypeMapper.java:122 at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:328) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:372) at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1193) at org.jetbrains.kotlin.codegen.ExpressionCodegen.generateBlock(ExpressionCodegen.java:1138) at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:56) at org.jetbrains.kotlin.codegen.CodegenStatementVisitor.visitBlockExpression(CodegenStatementVisitor.java:22) at org.jetbrains.kotlin.psi.KtBlockExpression.accept(KtBlockExpression.java:44) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genQualified(ExpressionCodegen.java:307) at org.jetbrains.kotlin.codegen.ExpressionCodegen.genStatement(ExpressionCodegen.java:372) at org.jetbrains.kotlin.codegen.ExpressionCodegen.gen(ExpressionCodegen.java:338) at org.jetbrains.kotlin.codegen.ExpressionCodegen.returnExpression(ExpressionCodegen.java:1590) ・ ・ ・

###■追記2
「3.」の部分を以下のように書き換えたところ、追記1と同じ現象になってしましました。

Kotlin

val func: java.util.function.Function<Genotype<BitGene>, Int> = java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) } val engine = Engine.builder(func, gtf).build()

###■追記3

元の問題についてはだいぶわかりました。変性は関係ありませんでした。
当たり前なのかもしれませんが、 Java の Function を引数にとるメソッドに Kotlin のラムダ式を渡そうとしても型が違うのでコンパイルが通らない、ということを理解していませんでした。

Kotlin

// これの型は (Genotype<BitGene>) -> Int val hoge = { gf: Genotype<BitGene> -> eval(gf) } // これの型は java.util.function.Function<Genotype<GitGene>, Int> val piyo = java.util.function.Function { gf: Genotype<BitGene> -> eval(gf) }

###■追記4

KSwordOfHasteさんに教えていただいた結果、動作するようにできました。
ご指摘のとおり、kotlinのコンパイラのバグのようです。
Collectorのメソッド型引数を明示的にすることで CompilationException 発生しなくなりました。

Kotlin

// 2.) Definition of the fitness function. fun eval(gt: Genotype<BitGene>): Int { return gt.chromosome .`as`(BitChromosome::class.java) .bitCount() } fun main(vararg args: String) { // 1.) Define the genotype (factory) suitable for the problem. val gtf = Genotype.of(BitChromosome.of(10, 0.5)) // 3.) Create the execution environment. val engine = Engine.builder(java.util.function.Function<Genotype<BitGene>, Int> { eval(it) }, gtf).build() // 4.) Start the execution (evolution) and collect the result. val result = engine.stream() .limit(100) .collect(EvolutionResult.toBestGenotype<BitGene, Int>()) println("Hello World:\n$result") }

ちなみに結果は以下のようになり、遺伝的アルゴリズムにより10個体100世代で10bitのうち最もビットが立つものを探索する、というものでした。

Hello World: [00000011|11111111]

ありがとうございました。

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

KSwordOfHaste

2018/04/15 12:13 編集

関係ないかもしれませんが、JDKのバージョンとKotlinのバージョンを一応明記しておいた方がよいかも知れません。
mosa

2018/04/15 11:57

ありがとうございます。 Kotlin 1.2.31、 Java 1.8.0 です。
KSwordOfHaste

2018/04/15 12:16 編集

当方Kotlin 1.2.31-release-95, JDK 1.8.0_162 IntelliJ IDEA 2018.1(Community Ed.)ですが追記1の現象が再現しませんでした。 (追記:Kotlin-stdlibのMANIFEST.MFの中身がImplementation-Version: 1.2.31-release-95, Build-Jdk: 1.8.0_151,...となっていたという意味です。自分もバージョンの見方がわかりませんでした><)
mosa

2018/04/15 12:54

検証ありがとうございます。「3.」以降を記述しました。表示されますでしょうか。追記1のエラーはまた別問題な気がしてきました。IntelliJ で Rebuild Project をしただけで同じエラーが発生しました。Invalidate Cache → Maven clean をした後でも同様です。
KSwordOfHaste

2018/04/15 13:32 編集

追記1は当方ではおきませんね・・・。元々の型エラーは型推論にまかせずに変数の型を意図したものに明示的に宣言したりbuilderメソッドに型引数を明記したりすればどこが推論できてないか(推論結果と不一致か)が絞れないでしょうか?
mosa

2018/04/15 14:34

ありがとうございます。「追記2」を追加しました。変数の型を明示するとやはりコンパイルは通りますが、org.jetbrains.kotlin.codegen.CompilationException が発生してしまいます。org.jetbrains.kotlin.codegen.CompilationException はコードそのものの問題ではなさそうに思えます。明日、別のPCで検証可能ですので検証してみます。
mosa

2018/04/16 11:08

もうちょっとかかります。すみません。
mosa

2018/04/17 08:11

別のPCで「追記1」「追記2」を実行してみましたが、同じようにCompilationExceptionが発生してしまいました。 元の問題についてはご指摘いただいたように型を詳しく調べたらだいぶ理解できてきました。ありがとうございます。 「追記3」に記載しました。私のところだけPCを変えてもCompilationExceptionが発生してしまう理由はまだわかりません。
mosa

2018/04/17 13:41

追記4を記載しました。ありがとうございました。

まだ回答がついていません

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

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

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Generics

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

Java

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

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。