如何在java 8 lambda表达式中获取方法参数名称?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了如何在java 8 lambda表达式中获取方法参数名称?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3664字,纯文字阅读大概需要6分钟。
内容图文
![如何在java 8 lambda表达式中获取方法参数名称?](/upload/InfoBanner/zyjiaocheng/822/aefbfea123ba4e5cadcd555c37dc2fa7.jpg)
从How to get Method Parameter names in Java 8 using reflection?
我知道使用javac -parameters参数可以将参数名保存在* .class文件中.
但它在lambda表达式中无效?
例:
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyTest {
public static void main(String[] args) {
for(Method m : Test.class.getDeclaredMethods()) {
System.out.println(m.getName());
for(Parameter p : m.getParameters()) {
System.out.println(" => " + p.getName());
}
}
}
}
interface MyInterface {
Object doSomething(int a, int b);
}
class Test {
private void bar(MyInterface iface) {
}
public void foo() {
bar((x, y) -> null);
}
}
当我做
javac -parameters MyTest.java
java MyTest
它打印
bar
=> iface
foo
lambda$foo$0
=> arg0
=> arg1
我尝试做javap -c -p -verbose测试:
{
Test();
descriptor: ()V
flags:
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 21: 0
private void bar(MyInterface);
descriptor: (LMyInterface;)V
flags: ACC_PRIVATE
Code:
stack=0, locals=2, args_size=2
0: return
LineNumberTable:
line 24: 0
MethodParameters:
Name Flags
iface
public void foo();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokedynamic #2, 0 // InvokeDynamic #0:doSomething:()LMyInterface;
6: invokespecial #3 // Method bar:(LMyInterface;)V
9: return
LineNumberTable:
line 27: 0
line 28: 9
private static java.lang.Object lambda$foo$0(int, int);
descriptor: (II)Ljava/lang/Object;
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=2, args_size=2
0: aconst_null
1: areturn
LineNumberTable:
line 27: 0
}
我可以找到参数名称iface,但找不到x或y
解决方法:
这似乎不是lambda表达式本身的问题:
interface MyInterface {
void doSomething(int a, int b);
}
class Test {
private void bar(MyInterface iface) {
iface.doSomething(0, 0);
}
public void foo() {
bar((x, y) -> System.out.println(x));
}
}
使用单个lambda表达式来保持简单.使用-parameters选项编译后,我们可以使用javap -c -p -verbose Test来了解更多信息:
private static void lambda$foo$0(int, int);
descriptor: (II)V
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iload_0
4: invokevirtual #6 // Method java/io/PrintStream.println:(I)V
7: return
LineNumberTable:
line 15: 0
MethodParameters:
Name Flags
x synthetic
y synthetic
参数名称(x和y)在那里!迭代这样的方法
for(Method m : Test.class.getDeclaredMethods()) {
System.out.println(m.getName());
for(Parameter p : m.getParameters()) {
System.out.println(" => " + p.getName());
}
}
正确显示参数名称:
lambda$foo$0
=> x
=> y
而不是lamdbas的问题,实际上很难确定正确的方法.如果您尝试在传递给该方法的接口实例上使用getDeclaredMethods()获取参数名称(如注释中建议的@Didier L),则会遇到问题.例如,使用
iface.getClass().getDeclaredMethods()
在bar()中将无法正常工作.如果您检索该类的名称,例如像iface.getClass().getName(),你会看到这样的东西:
Test$$Lambda$1/834600351
这是一个动态创建的类,你可以争论它是否存在.由于它不是由编译器生成的,因此它不会公开有关局部变量或其名称的任何信息,因为接口实现的方法与lambda不同.这是一个重要的区别.
该“虚拟类”提供了一种方法,例如, doSomething(int,int),用于实现给定的接口(MyInterface),但是这个公开的方法与你创建的定义lambda(lambda $foo $0)的方法不同.
因此,生成的“虚拟类”的方法doSomething不携带参数信息.动态创建的类“隐藏”您的实现.
你的第二个例子不会遇到这个问题:
map("bibi", new A() {
@Override
public JSONObject exec(String u, String s, String b) {
return null;
}
});
您明确定义了一个实现接口A的类,并且您明确地提供了一个方法exec,因此存在所有信息.
内容总结
以上是互联网集市为您收集整理的如何在java 8 lambda表达式中获取方法参数名称?全部内容,希望文章能够帮你解决如何在java 8 lambda表达式中获取方法参数名称?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。