我有以下方法调用,我在其中传递了一个 lambda 表达式。一个类在这里被隐式实例化了吗?
printStudents(
roster,
(Student s) -> s.getGender() == Student.Sex.MALE
&& s.getAge() >= 18
&& s.getAge() <= 25
);
方法签名:
printStudents(List<Student> roster, CheckStudent checkstudet)
interface CheckStudent {
boolean test(Student s);
}
编辑
你们中的一些人建议我重构代码,但出现了同样的问题。
CheckStudent checkStudent = (Student s) -> s.getGender() == Student.Sex.MALE && s.getAge() >= 18 && s.getAge() <= 25;
是否在赋值的右侧实例化了一个类(我指的不是类 Student
)?
lambda 表达式的值是对类实例的引用。因此,实际上,是的,正在创建一个类的实例。查看文档怎么说:
At run time, evaluation of a lambda expression is similar to
evaluation of a class instance creation expression, insofar as normal
completion produces a reference to an object.
但是,我们“看不到”的远不止这些。引擎盖下运行着许多优化。例如,根据某些因素,可以再次使用先前创建的对象。这意味着不需要在每次对 lambda 表达式求值时都分配一个新对象。让我们看一下文档:
Evaluation of a lambda expression is distinct from execution of the
lambda body. Either a new instance of a class with the properties below is
allocated and initialized, or an existing instance of a class with the
properties below is referenced.
[...]
These rules are meant to offer flexibility to implementations of the
Java programming language, in that:
A new object need not be allocated on every evaluation.
Objects produced by different lambda expressions need not belong to different classes (if the bodies are identical, for example).
Every object produced by evaluation need not belong to the same class (captured local variables might be inlined, for example).
If an "existing instance" is available, it need not have been created at a previous lambda evaluation (it might have been allocated
during the enclosing class's initialization, for example).
您可能已经注意到,这是一个复杂的主题。要更深入地了解,请查看 Java® 语言规范,第 “15.27.4. Run-time Evaluation of Lambda Expressions” 章.