我想通过java反射找出方法是否为"默认方法" 。我尝试打印java.lang.Iterable
的方法。
代码段:
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectionTest {
public static void main(String[] args) {
Class c = Iterable.class;
for(Method m : c.getDeclaredMethods())
{
System.out.print(Modifier.toString(m.getModifiers()));
System.out.println(" "+m.getName());
}
}
}
结果:
public abstract iterator
public spliterator
public forEach
这里,spliterator()和forEach()应该打印default
如果我的解释错误,请纠正我。
答案 0 :(得分:5)
在最新版本的java8更新中,我们在isDefault()
类中有java.lang.reflect.Method
,这就是诀窍。
稍微修改我之前的代码会产生结果。
<强>代码:强>
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectionTest {
public static void main(String[] args) {
Class c = Iterable.class;
for(Method m : c.getDeclaredMethods())
{
System.out.print(Modifier.toString(m.getModifiers()));
System.out.println(" "+(m.isDefault()?"default ":"")+m.getName());
}
}
}
的输出:强>
public abstract iterator
public default spliterator
public default forEach
注意:我在jdk8 update 20
答案 1 :(得分:5)
不要以这种方式依赖Modifier.toString
。在过去,类,字段和方法的修饰符被赋予唯一的不同值,因此您可以在不查看拥有修饰符的实体类型的情况下解释它们,就像该方法所暗示的那样。
但是随着Java的发展,添加了更多的修饰符位,并且无法保存该属性。特别是,当方法的修饰符位未经修改地传递给Modifier.toString
时,您将得到以下令人惊讶的行为:
volatile
transient
因此你应该过滤这些位。 Java 7 introduced a method providing the right mask以便您可以使用Modifier.toString(m.getModifiers()&Modifier.methodModifiers())
。
但这只能起作用,因为旧的Java关键字映射到唯一的修饰符位,而较新的修饰符位不与关键字相关联。对于较新的Java版本,即使这可能还不够。
对于default
关键字,它甚至更简单:没有与关键字关联的修饰符位。如果public
,非abstract
,非static
方法出现在 interface
中,则必须采用default
方法。这就是Method.isDefault()
确定方法是否为default
方法的方式。 Modifier.toString(…)
无法知道声明类是interface
,因此永远不会打印default
。