Vâng, biểu thức lambda được khử đường vào phương pháp trong biên soạn và chừng nào họ không nắm bắt this
(không truy cập không static
thành viên), các phương pháp này sẽ là static
. Phần khó khăn là để có được các phương thức này vì không có kết nối có thể kiểm tra giữa thể hiện giao diện chức năng và phương thức đích của nó.
Để minh họa điều này, đây là trường hợp đơn giản nhất:
public class LambdaToMethod {
public static void legacyCaller(Object arg, Method m) {
System.out.println("calling Method \""+m.getName()+"\" reflectively");
try {
m.invoke(null, arg);
} catch(ReflectiveOperationException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws URISyntaxException
{
Consumer<String> consumer=s -> System.out.println("lambda called with "+s);
for(Method m: LambdaToMethod.class.getDeclaredMethods())
if(m.isSynthetic() && m.getName().contains("lambda")) {
legacyCaller("a string", m);
break;
}
}
}
này hoạt động trơn tru như chỉ có một biểu thức lambda và do đó, một phương pháp ứng cử viên. Tên của phương pháp đó là trình biên dịch cụ thể và có thể chứa một số số serial hoặc mã băm vv
On kludge là làm cho biểu thức lambda serializable và kiểm tra hình thức tuần tự của nó:
static Method lambdaToMethod(Serializable lambda) {
for(Class<?> cl=lambda.getClass(); cl!=null; cl=cl.getSuperclass()) try {
Method m=cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
try {
SerializedLambda sl=(SerializedLambda)m.invoke(lambda);
return LambdaToMethod.class.getDeclaredMethod(sl.getImplMethodName(),
MethodType.fromMethodDescriptorString(sl.getImplMethodSignature(),
LambdaToMethod.class.getClassLoader()).parameterArray());
} catch(ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
} catch(NoSuchMethodException ex){}
throw new AssertionError();
}
public static void main(String[] args)
{
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("first lambda called with "+s)));
legacyCaller("a string", lambdaToMethod((Consumer<String>&Serializable)
s -> System.out.println("second lambda called with "+s)));
}
này hoạt động, tuy nhiên lambdas tuần tự có giá cao.
Giải pháp đơn giản nhất sẽ có thêm một chú thích để một tham số của biểu thức lambda để được tìm thấy khi lặp lại so với phương pháp này, tuy nhiên, hiện nay, javac
không lưu trữ các chú thích đúng cách, xem thêm this question về vấn đề này đề tài.
Nhưng bạn cũng có thể xem xét việc tạo các phương thức bình thường static
giữ mã thay vì biểu thức lambda.Lấy đối tượng Method
cho một phương thức thẳng về phía trước và bạn vẫn có thể tạo một thể hiện giao diện chức năng trong số chúng bằng cách sử dụng tham chiếu phương thức…
Không có gì giống như một thể hiện 'Method' cho biểu thức lambda. Lambda là cú pháp cho các hàm ẩn danh. Họ cung cấp cho bạn một ví dụ, nhưng bạn không thể tạo ra một phương thức ra khỏi nó – Jatin
@Jatin Rõ ràng, sự suy giảm giao diện chức năng tổng hợp vẫn chỉ là một đối tượng bình thường với các phương thức bình thường, mà bạn có thể sử dụng sự phản chiếu bình thường để truy cập. Tôi chỉ tự hỏi làm thế nào để có được clousure được bao bọc là tốt. –