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

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

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

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

Q&A

解決済

3回答

3126閲覧

Consumerのラムダ式とExecutorService#submit

dbfreak

総合スコア20

Java

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

0グッド

0クリップ

投稿2017/02/22 23:16

編集2017/02/23 00:00

###前提・実現したいこと
以下のコードのコンパイルが通ってしまう理由がよく分かりません。
stream#foreachの定義は、

forEach(Consumer<? super T> action)

です。
一方でラムダ式で使用しているsubmitの定義は以下の通りFuture<?>型の戻り値を持ちます。

Future<?> submit(Runnable task)

Consumer#acceptは、
void accept(T t)なのでsubmitのような戻り値を持つメソッドを使用できないと思っていたのですがなぜかコンパイルが通ってしまいます。
なぜなのか理由をご教示いただけないでしょうか。

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

エラーメッセージ

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

package practice; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.DoubleStream; public class Pall { public static void main(String[] args) { ExecutorService service = Executors.newScheduledThreadPool(5); //★ DoubleStream.of(10.9, 2.3).forEach(s->service.submit( () -> System.out.print(s + " "))); } }

実行結果

2.3 10.9

###試したこと

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

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

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

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

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

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

ozwk

2017/02/22 23:45

実行しましたか? 実行するとどうなりました? その結果は意図通りでしたか? (コンパイル通るというのは飲み込んだものとして)
dbfreak

2017/02/23 00:01

ご回答ありがとうございます。実行結果を追記しました。想定どおりの結果にはなりました。
guest

回答3

0

そもそもラムダ式は、返り値があるメソッドの場合は

java

1(引数群) -> { 2;必要なだけ 3 return 返り値; 4}

の形であり、voidの場合は最後のreturnが省略された

java

1(引数群) -> { 2;必要なだけ 3}

という形になります。さらに中身の文が一つだけの場合に

java

1(引数群) ->

と書けるというものです。この単文の形で値をreturnするかどうかはインタフェースの戻り値型が支配するので、voidなら(何も返さないreturnをするため)値を返す文であろうと関係ないことになります。

投稿2017/02/23 01:38

swordone

総合スコア20649

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

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

0

ベストアンサー

java

1forEach(s -> hoge(s) )

java

1.forEach(new DoubleConsumer(){ 2 @Override 3 public void accept(double s) { 4 hoge(s); 5 } 6})

と同等に解釈されるようです。

hoge()が何を返そうとaccept()内で戻り値を捨てているので
結果型が合ってコンパイルが通っています。

また、

java

1forEach(s -> {return hoge(s);} )

と書くと、DoubleConsumerとして扱えなくなるので
型が合わないとしっかり怒ってくれます。

投稿2017/02/23 01:02

編集2017/02/23 01:21
ozwk

総合スコア13512

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

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

dbfreak

2017/02/23 01:48

納得です。ご親切にありがとうございました。
guest

0

本回答は質問意図を取り違えていました。失礼しました。


ラムダ式を見落としておられるような気がします・・・

forEach(Consumer<? super T> action)

このConsumerに対応する実引数は以下のラムダ式になります。

s -> service.submit(() -> System.out.print(s + " ")

これは「何かの型を一つ受け取って結果を何も返さないラムダ式」と解釈できるので、Consumer<? super Double>に適合しコンパイルが通りますということなのですが・・・

Consumerに対応する実引数がsubmitである解釈されていたようですが上記のように実引数はsubmitではなくそれを包むラムダ式であると理解できれば疑問は解けると思います。

投稿2017/02/23 01:04

編集2017/02/23 04:40
KSwordOfHaste

総合スコア18392

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

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

ozwk

2017/02/23 01:12 編集

forEachの引数は double -> Void となるラムダ式のはずだが、 s -> service.submit(() -> System.out.print(s + " ") つまり double -> Future<Void> を引数にしてもコンパイルが通る。 これは型が合っていないのでは?ってことだと思います。
KSwordOfHaste

2017/02/23 01:45

自分の回答は質問者さんの疑問を外してましたね。コメントありがとうございます。
dbfreak

2017/02/23 01:45

service.submit(…); return; なのか return service.submit(…); なのかはコンパイラーがよしなに解釈してくれるということなんですね。 省略記法を使っているので暗黙でreturnが補完されるのだと思い込んでいました。 ご回答ありがとうございました。
KSwordOfHaste

2017/02/23 01:59 編集

ラムダ式本体のbrace={}の省略についての話だったのですね。そこを勘違いしてました!コメントありがとうございました。swordoneさんが網羅的な回答をしてくださいましたね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問