【Java】Lambda式で「ambiguous(あいまい)」になるケースについて
ちょっとハマったのでメモ。
java.util.Functionやjava.util.ConsumerなどのFunctionalInterfaceなクラスのインスタンスを引数に取るメソッドに対して、Lambda式を与えると「ambiguous(あいまい)」としてコンパイルエラーになるケースが存在する。
例えば以下のクラスはコンパイルエラーになる。
例: Demo1.java
import java.util.function.Consumer;
import java.util.function.Function;
public class Demo {
public static void main(String... args) {
doHoge(e -> {
throw new RuntimeException();
});
}
public static void doHoge(Function<Object, Object> function) {
System.out.println("function");
}
public static void doHoge(Consumer<Object> consumer) {
System.out.println("consumer");
}
}
これはthrow戻りが関係していて、Lambda式をjava.util.Functionとして解釈すべきかjava.util.Consumerとして解釈すべきか分からなくなってしまうため。
これはFunctionalInterfaceとして用意されたメソッドの引数や返り値の型が被っているクラス(例えばjava.util.Function<Object, Boolean>とjava.util.Predicate<Object>など)をoverloadとして作成した場合も発生する。
また返り値が存在するメソッドを使用する場合に、ブロック及びreturnを省略した場合もコンパイルエラーになる。
例: Demo2.java
import java.util.function.Consumer;
import java.util.function.Function;
public class Demo2 {
public static void main(String... args) {
doHoge(e -> System.getProperties());
}
public static void doHoge(Function<Object, Object> function) {
System.out.println("function");
}
public static void doHoge(Consumer<Object> consumer) {
System.out.println("consumer");
}
}
これらの問題の解決方法としては、明確にreturnを書いてやるかLambda式にキャストを追加してやれば良い。
(当たり前だがoverloadの型被りの場合はreturnでは解決しない)
例: Demo3.java
import java.util.function.Consumer;
import java.util.function.Function;
public class Demo3 {
public static void main(String... args) {
try {
doHoge((Function<Object, Object>) e -> { // Functionとして認識される
throw new RuntimeException();
});
} catch (RuntimeException ignore) {
}
try {
doHoge((Consumer<Object>) e -> { // Consumerとして認識される
throw new RuntimeException();
});
} catch (RuntimeException ignore) {
}
doHoge(e -> { // Functionとして認識される
return System.getProperties();
});
doHoge(e -> { // Consumerとして認識される
System.getProperties();
});
}
public static void doHoge(Function<Object, Object> function) {
System.out.println("function");
}
public static void doHoge(Consumer<Object> consumer) {
System.out.println("consumer");
}
}
実行結果: Demo3.java
function
consumer
function
consumer
【Python】文字列から数値へパースする際の落とし穴
備忘録がてらメモ。
pythonにおいて文字列→数値へパースする際、使用できる文字はちょっと特殊で全角の「1」なども含まれる。
ただ当たり前だが、それを更に文字列に変換すると半角数字になるので注意。
例: demo.py
raw_value = "1" # 全角の「1」を与える
value = int(raw_value) # intへ変換
print(str(value)) # 半角の「1」が出力される
結果: demo.py
1
ちなみに余談だが[string.isdigit()]という関数は文字列が数字であるかどうかを返し、今回のような全角の「1」などでもちゃんとTrueを返す。
ただこの関数は残念なことに、正負の記号(+や-)が含まれるとFalseを返す。
(なんでやねん)
なのでバリデーションに使用する場合には、しっかりこの辺を考慮しなければならない。