第一个参数是带有一个方法的类时,不能用lambda替换SAM构造函数

我困惑于SAM构造函数,我有这个Java类:

public class TestSam<T> { public void observe(ZeroMethods zero, Observer<T> observer) { } public void observe(OneMethod one, Observer<T> observer) { } public void observe(TwoMethods two, Observer<T> observer) { } public interface Observer<T> { void onChanged(@Nullable T t); } public interface ZeroMethods { } public interface OneMethod { First getFirst(); } public interface TwoMethods { First getFirst(); Second getSecond(); } public interface First { } public interface Second { } } 

而这个Kotlin代码:

 fun testSam( test: TestSam<String>, zero: TestSam.ZeroMethods, one: TestSam.OneMethod, two: TestSam.TwoMethods ) { test.observe(zero) { println("onChanged $it") } // 1. compiles test.observe(zero, TestSam.Observer { println("onChanged $it") }) // 2. Redundant SAM-constructor test.observe(one) { println("onChanged $it") } // 3. doesn't compile test.observe({ one.first }) { println("onChanged $it") } // 4. compiles test.observe(one, TestSam.Observer { println("onChanged $it") }) // 5. compiles test.observe(two) { println("onChanged $it") } // 6. compiles test.observe(two, TestSam.Observer { println("onChanged $it") }) // 7. Redundant SAM-constructor } 

这里的交易是什么? Kotlin为什么不能找出3.(并提供了特殊的变种4.),但处理所有其他情况?


此代码的基本原理是LiveData<T>.observe(LifecycleOwner owner, Observer<T> observer)方法,其中LifecycleOwner具有一个方法getLifecycle()

我在编译器中发现了一个规则:如果Java方法调用需要SAM接口的类型,那么可以用lambdas(或函数)替换它们, 但是可以不使用所有这些参数, 也可以不使用它们。

所以,你有方法: public void observe(OneMethod one, Observer<T> observer) 。 这两个参数都是SAM候选项。 你可以打电话给:
observer(object1, object2)
要么:
observer(function1, function2)

不是
observer(object1, function2)
不是
observer(function1, object2)

在3个或更多参数的情况下,相同的行为将是均匀的。 造成这种情况的原因是编译器设计的技术难度。

对不起,如果我不是很清楚,我英文不太好。