夜中に8/15頃のツイートが回ってきた。
Java 8u60 adds reflection on lambda param names
DSLs https://t.co/cflxFK468e
Hash-Literals https://t.co/5rOCrrckcB pic.twitter.com/NEzj4X3Bt1
— Benjamin Weber (@benjiweber) 2015, 8月 16
曰く
Java8u60でラムダのパラメーターの名前に対してリフレクションができるようになってるよ
というわけで
早速、件のツイートにあったレポジトリーをダウンロードして(mavenレポジトリーにはない…(´・ω・`))、プロジェクトに追加して、試してみた。
コード
import com.benjiweber.typeref.NamedValue; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Optional; import static java.util.Arrays.stream; public final class HashLiteral { private HashLiteral() {} // めっちゃ感覚的にマップが構築できる!!! private static final Map<String, String> map = map( hello -> "world", john -> john, bill -> "not paid", うほっいいオトコ -> うほっいいオトコ ); public static Optional<String> get(String key) { return Optional.ofNullable(map.get(key)); } @SafeVarargs public static <T> Map<String, T> map(NamedValue<T>... kvPair) { Map<String, T> m = new HashMap<>(); stream(kvPair) .forEach(kv -> m.put(kv.name(), kv.value())); return Collections.unmodifiableMap(m); } }
テストコード
import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import java.util.NoSuchElementException; import java.util.Optional; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class HashLiteralTest { @Rule public TestName testName = new TestName(); @Test public void hashLiteralTest() { Optional<String> opValue = HashLiteral.get("hello"); opValue.ifPresent(v -> assertThat(v, is("world"))); opValue.orElseThrow(NoSuchElementException::new); } @Test public void うほっいいオトコ() { Optional<String> opValue = HashLiteral.get(testName.getMethodName()); opValue.ifPresent(v -> assertThat(v, is(testName.getMethodName()))); opValue.orElseThrow(() -> new NoSuchElementException(testName.getMethodName())); } @Test(expected = NoSuchElementException.class) public void そんなキーはなかった() { HashLiteral.get(testName.getMethodName()).get(); } }
テストコードの方は、多少遊びが入っています(´・ω・`)
なお、IDEでテストを実行するときには多少注意が必要です。
この写真のように、Build, Execution, Deployment
> Compiler
> Java Compiler
のAdditional command line parameters
に-parameters
を入れておかないと落ちます。
Caused by: java.lang.IllegalStateException: You need to compile with javac -parameters for parameter reflection to work; You also need java 8u60 or newer to use it with lambdas at com.benjiweber.typeref.NamedValue.checkParametersEnabled(NamedValue.java:13) at com.benjiweber.typeref.NamedValue.name(NamedValue.java:8)
Gradleでテスト…
compileJava { sourceCompatibility = jdkLevel targetCompatibility = jdkLevel options.encoding = encoding options.compilerArgs << '-parameters' }
コンパイラーオプションに-parameters
を渡しておいたんですけど…
$ gradle test ... :test Picked up _JAVA_OPTIONS: -Dfile.encoding=UTF-8 org.mikeneck.sample.HashLiteralTest > うほっいいオトコ FAILED java.lang.ExceptionInInitializerError at HashLiteralTest.java:42 Caused by: java.lang.IllegalStateException at HashLiteralTest.java:42 org.mikeneck.sample.HashLiteralTest > そんなキーはなかった FAILED java.lang.Exception Caused by: java.lang.NoClassDefFoundError at HashLiteralTest.java:49 org.mikeneck.sample.HashLiteralTest > hashLiteralTest FAILED java.lang.NoClassDefFoundError at HashLiteralTest.java:35 3 tests completed, 3 failed :test FAILED ... BUILD FAILED Total time: 4.028 secs $
落ちた(´・ω・`)
なんでだろうorz
おわり???
後でGradle Forumで聞いてみます