从匿名 class 到 lambda 表达式
From Anonymous class to lambda expression
在下面使用匿名 class 时,我们调用变量 x
没有问题
interface Age {
int x = 21;
void getAge();
}
class AnonymousDemo {
public static void main(String[] args) {
Age oj1 = new Age() {
@Override
public void getAge() {
// printing age
System.out.print("Age is "+x);
}
};
oj1.getAge();
}
}
但是当我将相同的代码与下面的 lambda 表达式一起使用时,发生了异常:
interface Age {
int x = 21;
void getAge();
}
class AnonymousDemo {
public static void main(String[] args) {
Age oj1 = () -> { System.out.print("Age is "+x); };
oj1.getAge();
}
}
这里会有什么问题?知道lambda表达式只是实现匿名classes.
的缩写
x
未被识别为来自 Age
界面的字段。您必须执行静态导入 (import static Age.x
) 或指定 x
的来源:
Age oj1 = () -> System.out.print("Age is "+ Age.x);
实际上 lambda 表达式不是 "just an abbreviation to implement anonymous classes"。使用 lambda 表达式的好处是它可以直接访问 this
class 的实例(调用它的 class ),而匿名 class 则不能(它有自己的 this
实例)。
In other words, anonymous classes introduce a new scope. so that names
are resolved from their superclasses and interfaces and can shadow
names that occur in the lexically enclosing environment. For lambdas,
all names are resolved lexically.
还有
Lambda performance with Anonymous classes
When application is launched each class file must be loaded and
verified.
Anonymous classes are processed by compiler as a new subtype for the
given class or interface, so there will be generated a new class file
for each.
Lambdas are different at bytecode generation, they are more efficient,
used invokedynamic instruction that comes with JDK7.
For Lambdas this instruction is used to delay translate lambda
expression in bytecode untill runtime. (instruction will be invoked
for the first time only)
As result Lambda expression will becomes a static method(created at
runtime). (There is a small difference with stateles and statefull
cases, they are resolved via generated method arguments)
例如:
interface Supplier {
void foo();
}
class A {
private String name;
public void doSome() {
baz(() -> System.out.println(this.name));
}
private void baz(Supplier sup){
sup.foo();
}
}
或
class A {
private String name;
public void doSome() {
baz(new Supplier() {
void foo() {
System.out.println(A.this.name);
}
});
}
private void baz(Supplier sup){
sup.foo();
}
}
我推荐阅读这篇文章:Java8 Lambdas vs Anonymous classes。
在下面使用匿名 class 时,我们调用变量 x
没有问题
interface Age {
int x = 21;
void getAge();
}
class AnonymousDemo {
public static void main(String[] args) {
Age oj1 = new Age() {
@Override
public void getAge() {
// printing age
System.out.print("Age is "+x);
}
};
oj1.getAge();
}
}
但是当我将相同的代码与下面的 lambda 表达式一起使用时,发生了异常:
interface Age {
int x = 21;
void getAge();
}
class AnonymousDemo {
public static void main(String[] args) {
Age oj1 = () -> { System.out.print("Age is "+x); };
oj1.getAge();
}
}
这里会有什么问题?知道lambda表达式只是实现匿名classes.
的缩写x
未被识别为来自 Age
界面的字段。您必须执行静态导入 (import static Age.x
) 或指定 x
的来源:
Age oj1 = () -> System.out.print("Age is "+ Age.x);
实际上 lambda 表达式不是 "just an abbreviation to implement anonymous classes"。使用 lambda 表达式的好处是它可以直接访问 this
class 的实例(调用它的 class ),而匿名 class 则不能(它有自己的 this
实例)。
In other words, anonymous classes introduce a new scope. so that names are resolved from their superclasses and interfaces and can shadow names that occur in the lexically enclosing environment. For lambdas, all names are resolved lexically.
还有
Lambda performance with Anonymous classes
When application is launched each class file must be loaded and verified.
Anonymous classes are processed by compiler as a new subtype for the given class or interface, so there will be generated a new class file for each.
Lambdas are different at bytecode generation, they are more efficient, used invokedynamic instruction that comes with JDK7.
For Lambdas this instruction is used to delay translate lambda expression in bytecode untill runtime. (instruction will be invoked for the first time only)
As result Lambda expression will becomes a static method(created at runtime). (There is a small difference with stateles and statefull cases, they are resolved via generated method arguments)
例如:
interface Supplier {
void foo();
}
class A {
private String name;
public void doSome() {
baz(() -> System.out.println(this.name));
}
private void baz(Supplier sup){
sup.foo();
}
}
或
class A {
private String name;
public void doSome() {
baz(new Supplier() {
void foo() {
System.out.println(A.this.name);
}
});
}
private void baz(Supplier sup){
sup.foo();
}
}
我推荐阅读这篇文章:Java8 Lambdas vs Anonymous classes。