如何使用java反射从界面中找到"默认"方法?

Sur*_*san 5 reflection java-8

我想通过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());
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


结果:

public abstract  iterator
public  spliterator
public  forEach
Run Code Online (Sandbox Code Playgroud)

这里,spliterator()和forEach()应该打印出来default.
如果我的解释错误,请纠正我.

Sur*_*san 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());
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


输出:

public abstract  iterator
public  default spliterator
public  default forEach
Run Code Online (Sandbox Code Playgroud)


注意:我在jdk8 update 20中测试了这个


Hol*_*ger 5

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

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

  • 一个方法将被打印为volatile
  • 一个可变参数的方法将被打印为transient

因此,您应该过滤这些位.Java 7 引入了一种提供正确掩码的方法,以便您可以使用Modifier.toString(m.getModifiers()&Modifier.methodModifiers()).

但这只能起作用,因为旧的Java关键字映射到唯一的修饰符位,而较新的修饰符位不与关键字相关联.对于较新的Java版本,即使这可能是不够的.

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