如何使用java反射从接口中找到"default"方法?



我想通过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
如果我的解释有误,请指正。

不要那样依赖Modifier.toString。在过去,类、字段和方法的修饰符被赋予唯一的不同值,这样您就可以解释它们,而不必像该方法所建议的那样查看拥有修饰符的实体的类型。

但是随着Java的发展,增加了更多的修饰符位,无法保持该属性。特别是,当不加修改地将方法的修饰符位传递给Modifier.toString时,您将得到以下令人惊讶的行为:

  • a 桥接方法将打印为volatile
  • a varargs方法将打印为transient

因此你应该过滤比特。Java 7引入了一个提供正确掩码的方法,这样您就可以使用Modifier.toString(m.getModifiers()&Modifier.methodModifiers())

但是这仅仅是因为旧的Java关键字映射到唯一的修饰符位,而新的修饰符位与关键字没有关联。对于较新的Java版本,即使这样也可能不够。

对于default关键字,它甚至更简单:没有与关键字关联的修饰符位。如果在 interface 中出现public、非abstract、非static方法,则该方法一定是default方法。这就是Method.isDefault()如何确定一个方法是否是default方法。Modifier.toString(…)没有机会知道声明类是否为interface,因此永远不会打印default

在最近版本的java8更新中,我们在java.lang.reflect.Method类中添加了isDefault(),这就实现了这个功能。
将前面的代码稍微修改一下就得到了结果。

代码:

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更新20

中测试了这个

相关内容

  • 没有找到相关文章

最新更新