为什么Java8和Scala2.12 lambda缓存有区别?
Java代码
package lambda_cache_example_java;
interface Semigroup1<A> {
public A append(A a1, A a2);
}
interface Semigroup2<A> {
public A append(A a1, A a2);
public interface Foo{}
public class Bar{}
}
class Main {
static Semigroup1<Integer> intSemigroup1() {
return (a1, a2) -> a1 + a2;
}
static Semigroup2<Integer> intSemigroup2() {
return (a1, a2) -> a1 + a2;
}
public static void main(String[] args) {
Semigroup1<Integer> x1 = intSemigroup1();
Semigroup1<Integer> x2 = intSemigroup1();
System.out.println(x1);
System.out.println(x2);
System.out.println(x1 == x2); // same instance
Semigroup2<Integer> y1 = intSemigroup2();
Semigroup2<Integer> y2 = intSemigroup2();
System.out.println(y1);
System.out.println(y2);
System.out.println(y1 == y2); // same instance as well
}
}
Scala代码(版本2.12.0)
package lambda_cache_example_scala
trait Semigroup1[A] {
def append(a1: A, a2: A): A
}
trait Semigroup2[A] {
def append(a1: A, a2: A): A
trait Foo
}
object Main {
def intSemigroup1(): Semigroup1[Int] =
(a1, a2) => a1 + a2
def intSemigroup2(): Semigroup2[Int] =
(a1, a2) => a1 + a2
def main(args: Array[String]): Unit = {
val x1 = intSemigroup1()
val x2 = intSemigroup1()
println(x1)
println(x2)
println(x1 eq x2) // same instance
val y1 = intSemigroup2()
val y2 = intSemigroup2()
println(y1)
println(y2)
println(y1 eq y2) // not same
}
}
结果
$ sbt "runMain lambda_cache_example_java.Main" "runMain lambda_cache_example_scala.Main"
[info] Running lambda_cache_example_java.Main
lambda_cache_example_java.Main$$Lambda$9/1908283686@44939bb7
lambda_cache_example_java.Main$$Lambda$9/1908283686@44939bb7
true
lambda_cache_example_java.Main$$Lambda$10/2119574930@7f206457
lambda_cache_example_java.Main$$Lambda$10/2119574930@7f206457
true
[success] Total time: 0 s, completed 2016/11/24 15:09:56
[info] Running lambda_cache_example_scala.Main
lambda_cache_example_scala.Main$$$Lambda$11/2085010450@7b408c6e
lambda_cache_example_scala.Main$$$Lambda$11/2085010450@7b408c6e
true
lambda_cache_example_scala.Main$$anonfun$intSemigroup2$2@c5329e5
lambda_cache_example_scala.Main$$anonfun$intSemigroup2$2@752d3cd9
false
[success] Total time: 0 s, completed 2016/11/24 15:09:57
斯卡拉有路径依赖类型。 虽然从你的例子并不明显,一个可以构建嵌套的特征,其中性状Foo
之一的实例内Semigroup2
是不符合的,在所有兼容Foo
从另一个实例Semigroup2
。 这篇文章和这个答案看起来像路径依赖类型的很好的解释。
这意味着Semigroup2
一个实例也是由其内部特征定义的,所以在引用它的一个方法时必须进行闭包。 由于每次我们尝试引用该方法时都会重新进行关闭,因此匿名功能不同也就不足为奇了。
在Java中,情况并非如此。 Semigroup2<A>.Foo
是一种类型(与Scala中不同,您需要一个Semigroup2<A>.Foo
Semigroup[A]
实例来标识类型Foo
)。
上一篇: Why is there a difference between Java8 and Scala2.12 lambda cache?