Reflection 如何找到;“违约”;使用java反射的接口中的方法?

Reflection 如何找到;“违约”;使用java反射的接口中的方法?,reflection,java-8,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

我想通过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
public abstract  iterator
public  default spliterator
public  default forEach
这里,spliterator()和forEach()应该已经打印了
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  spliterator
public  forEach
public abstract  iterator
public  default spliterator
public  default forEach


注意:我已经在jdk8更新20中测试了这一点不要以那种方式依赖于
修饰符。在过去,类、字段和方法的修饰符被赋予了唯一的不同值,因此您可以解释它们,而无需像该方法所建议的那样查看拥有修饰符的实体的类型

但是,随着Java的发展,添加了更多的修饰符位,不可能保留该属性。特别是,当将方法的修饰符位传递给未修改的
modifier.toString
时,您将获得以下令人惊讶的行为:

  • 桥接方法将打印为
    volatile
  • varargs方法将打印为
    transient
因此,您应该过滤位。Java7,这样您就可以使用
Modifier.toString(m.getModifiers()&Modifier.methodModifiers())

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

对于
default
关键字,它甚至更简单:没有与关键字关联的修饰符位。如果
公共
、非
抽象
、非
静态
方法出现在
界面
中,则它必须是
默认
方法。这就是确定方法是否为默认方法的方法
Modifier.toString(…)
没有机会知道声明类是否是
接口
,因此永远不会打印
默认值