JAVA 反射之java.lang.reflect.Method

JAVA 反射之java.lang.reflect.Method

Scroll Down

Method介绍

继承的方法(包括重载、重写和隐藏的)会被编译器强制执行,这些方法都无法反射。
因此,反射一个类的方法时不考虑父类的方法,只考虑当前类的方法。

每个方法都由 修饰符、返回值、参数、注解和抛出的异常组成。

Method定义

Method 类位于java.lang.reflect包中,主要用于在程序运行状态中,动态地获取方法信息

Method方法

方法描述
boolean equals(Object obj)将此方法与指定的对象进行比较。
T getAnnotation(Class annotationClass)如果存在这样的注释,则返回该元素的指定类型的注释,否则返回null。
Annotation[] getDeclaredAnnotations()返回此元素上直接存在的所有注释。
Class getDeclaringClass()返回表示声明由此Method对象表示方法类的Class对象。
Object getDefaultValue()返回此Method实例表示的注释成员的默认值。
Class<?>[] getExceptionTypes()返回一个Class对象数组,该数组表示由此构造方对象表示的底层构造函数声明的异常类型。
Type[] getGenericExceptionTypes()返回一个Type对象的数组,表示声明为此Constructor对象抛出的异常。
Type[] getGenericParameterTypes()返回一个Type对象数组,它以声明顺序表示由此构造方法对象表示的方法的形式参数类型。
Type getGenericReturnType()返回一个Type对象,该对象表示此Method对象表示的方法的正式返回类型。
int getModifiers()返回由此Method对象表示的方法的Java语言修饰符,以整数形式返回。
String getName()以字符串形式返回此方法的名称。
Annotation[][] getParameterAnnotations()返回一个数组数组,它们以声明顺序表示由此Method对象表示的方法的形式参数的注释。
Class<?>[] getParameterTypes()返回一个Class对象数组,它们以声明顺序表示由此Method对象表示的构造函数的形式参数类型。
Class<?> getReturnType()返回一个Class对象,该对象表示此Method对象表示的方法的正式返回类型。
int hashCode()返回此构造函数的哈希码。
Object invoke(Object obj, Object…args)在具有指定参数的指定对象上调用此Method对象表示的底层方法。
boolean isBridge()如果此方法是桥接方法,则返回true; 否则返回false。
boolean isSynthetic()如果此方法是合成方法,则返回true; 否则返回false。
boolean isVarArgs()如果此方法被声明为使用可变数量的参数,则返回true; 否则返回false。
String toGenericString()返回描述此方法的字符串,包括类型参数。
String toString()返回描述此方法的字符串。

Method 类常用方法

getAnnotatedReturnType()

返回一个 AnnotatedType 对象,该对象表示使用类型来指定由该可执行文件表示的方法或构造函数的返回类型

public class MethodTest {
    public String test() {
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        AnnotatedType annotatedReturnType = method.getAnnotatedReturnType();
        System.out.println(annotatedReturnType.getType());
    }
}

结果:

class java.lang.String

getAnnotatedExceptionTypes()

返回一个 AnnotatedType 对象数组,这些对象表示使用类型来指定由该可执行文件表示的方法或构造函数声明的异常

    // getAnnotatedExceptionTypes()
    public void test() throws NullPointerException, ClassNotFoundException {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        AnnotatedType[] exceptionTypes = method.getAnnotatedExceptionTypes();
        for (AnnotatedType exceptionType : exceptionTypes) {
            System.out.println(exceptionType.getType());
        }
    }

结果

class java.lang.NullPointerException
class java.lang.ClassNotFoundException

getAnnotatedReceiverType()

返回一个 AnnotatedType 对象,该对象表示使用类型来指定该可执行对象表示的方法或构造函数的接收者类型

public class MethodTest {
    // getAnnotatedReceiverType()
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        AnnotatedType receiverType = method.getAnnotatedReceiverType();
        System.out.println(receiverType.getType());
    }
}

结果

class com.hb0730.test.MethodTest

getAnnotation(Class annotationClass)

  • 如果该方法对象存在指定类型的注解,则返回该注解,否则返回 null
  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotation() 方法与 getDeclaredAnnotation() 方法作用相同
public class MethodTest {
    // getAnnotation(Class<T> annotationClass)
    @MethodAnnotation(key = "key", value = "value")
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        MethodAnnotation annotation = method.getAnnotation(MethodAnnotation.class);
        System.out.println(annotation);
    }

}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MethodAnnotation {

    String key();

    String value();
}

结果

@com.hb0730.test.MethodAnnotation(key=key, value=value)

getDeclaredAnnotation(Class annotationClass)

  • 如果该方法对象存在指定类型的注解,则返回该注解,否则返回 null
  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotation() 方法与 getDeclaredAnnotation() 方法作用相同

getAnnotationsByType(Class annotationClass)

  • 如果该方法对象存在指定类型的注解,则返回该注解数组,否则返回 null
  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotationsByType() 方法与 getDeclaredAnnotationsByType() 方法作用相同
  • getAnnotationsByType() 方法与 getAnnotation() 方法的区别在于:getAnnotationsByType() 方法会检查修饰该方法对象的注解是否为可重复类型注解,如果是则会返回修饰该方法对象的一个或多个注解
  • @Repeatable 用于声明注解为可重复类型注解
  • 当声明为可重复类型注解后,如果方法注解仍为一个,则 getAnnotation() 方法会正常返回,如果方法注解为多个,则 getAnnotation() 方法会返回 null
public class MethodTest {
    // getAnnotationsByType
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Repeatable(RepeatableAnnotation.class)
    public @interface MethodAnnotation {

        String key();

        String value();
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface RepeatableAnnotation {
        MethodAnnotation[] value();
    }

    @MethodAnnotation(key = "key1", value = "value1")
    @MethodAnnotation(key = "key2", value = "value2")
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getDeclaredMethod("test");
        // null
        System.out.println(method.getAnnotation(MethodAnnotation.class));
        MethodAnnotation[] annotationsByType = method.getAnnotationsByType(MethodAnnotation.class);
        // [@lang.reflect.MethodAnnotation(value=value1, key=key1), @lang.reflect.MethodAnnotation(value=value2, key=key2)]
        System.out.println(Arrays.toString(annotationsByType));
    }
}

结果

null
[@com.hb0730.test.MethodTest$MethodAnnotation(key=key1, value=value1), @com.hb0730.test.MethodTest$MethodAnnotation(key=key2, value=value2)]

getDeclaredAnnotationsByType(Class annotationClass)

  • 如果该方法对象存在指定类型的注解,则返回该注解数组,否则返回 null

  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotationsByType() 方法与 getDeclaredAnnotationsByType() 方法作用相同

getAnnotations()

  • 返回该方法对象上的所有注解,如果没有注解,则返回空数组

  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotations() 方法与 getDeclaredAnnotations() 方法作用相同

public class MethodTest {
    // getAnnotations()
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MethodAnnotation {

        String key();

        String value();
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TestAnnotation {

        String key();

        String value();
    }

    @MethodAnnotation(key = "key1", value = "value1")
    @TestAnnotation(key = "key2", value = "value2")
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }


}

结果

@com.hb0730.test.MethodTest$MethodAnnotation(key=key1, value=value1)
@com.hb0730.test.MethodTest$TestAnnotation(key=key2, value=value2)

getDeclaredAnnotations()

  • 返回该方法对象上的所有注解,如果没有注解,则返回空数组

  • 只有类级别的注解会被继承得到,对于其他对象而言,getAnnotations() 方法与 getDeclaredAnnotations() 方法作用相同

getModifiers()

  • 返回修饰该方法对象修饰符的整数形式,使用 Modifier 类对其进行解码
public class MethodTest {

    // getModifiers()
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        int modifiers = method.getModifiers();
        System.out.println(Modifier.toString(modifiers));
    }


}

结果

public

getName()

返回方法对象名称

public class MethodTest {

    // getName()
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        System.out.println(method.getName());
    }


}

结果

test

isAnnotationPresent(Class<? extends Annotation> annotationClass)

如果该方法对象上有指定类型的注解,则返回 true,否则为 false

public class MethodTest {

    // isAnnotationPresent(Class<? extends Annotation> annotationClass)
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MethodAnnotation {

        String key();

        String value();
    }

    @MethodAnnotation(key = "key", value = "value")
    public void test() {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getDeclaredMethod("test");
        System.out.println(method.isAnnotationPresent(MethodAnnotation.class));
    }


}

结果

true

isVarArgs()

如果该方法对象的参数中存在 可变参,则返回 true,否则为 false

public class MethodTest {
    public void test(String... args) {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", String[].class);
        // true
        System.out.println(method.isVarArgs());
    }
}

结果

true

getDeclaringClass()

返回该方法对象表示的方法所在类的 Class 对象

public class MethodTest {

    // getDeclaringClass()
    public void test() {

    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        // class com.hb0730.test.MethodTest
        System.out.println(method.getDeclaringClass());
    }
}

结果

class com.hb0730.test.MethodTest

getAnnotatedParameterTypes()

返回一个 AnnotatedType 对象数组,这些对象表示使用类型来指定由该可执行文件表示的方法或构造函数的形式参数类型

public class MethodTest {
    // getAnnotatedParameterTypes()
    public void test(String name, Integer age) {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", String.class, Integer.class);
        AnnotatedType[] parameterTypes = method.getAnnotatedParameterTypes();
        for (AnnotatedType parameterType : parameterTypes) {
            //class java.lang.String
            //class java.lang.Integer
            System.out.println(parameterType.getType());
        }

    }
}

结果

class java.lang.String
class java.lang.Integer

getParameterAnnotations()

返回一组注解数组,这些注解以声明顺序修饰该方法对象的参数

public class MethodTest {
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.PARAMETER)
    public @interface ParameterAnnotation {
        String key();

        String value();
    }

    public void test(@ParameterAnnotation(key = "key1", value = "value1") String name,
                     @ParameterAnnotation(key = "key2", value = "value2") Integer age) {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", String.class, Integer.class);
        Annotation[][] annotations = method.getParameterAnnotations();
        System.out.println(Arrays.deepToString(annotations));
    }
}

结果

[[@com.hb0730.test.MethodTest$ParameterAnnotation(key=key1, value=value1)], 
[@com.hb0730.test.MethodTest$ParameterAnnotation(key=key2, value=value2)]]

getParameterCount()

返回该方法对象的参数个数 (无论是显式声明的还是隐式声明的或不声明的)

public class MethodTest {

    //getParameterCount()
    public void test(String name, Integer age) {}

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getDeclaredMethod("test", String.class, Integer.class);
        // 2
        System.out.println(method.getParameterCount());
    }
}

结果

2

getParameters()

返回一个参数对象数组,该数组表示该方法对象的所有参数

public class MethodTest {
    // getParameters()
    public void test(String name, Integer age) {
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getDeclaredMethod("test", String.class, Integer.class);
        Parameter[] parameters = method.getParameters();
        for (Parameter parameter : parameters) {
            // java.lang.String name
            // java.lang.Integer age
            System.out.println(parameter);
        }
    }
}

结果

java.lang.String name
java.lang.Integer age

getDefaultValue()

  • 返会该注解方法对象表示的成员默认值

  • 如果成员属于基本数据类型,则返回对应的包装类实例

  • 如果没有默认值或者该方法实例不表示注解方法,则返回 null

public class MethodTest {
    // getDefaultValue()
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MethodAnnotation {

        String key() default "default key";

        String value() default "default value";
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method key = MethodAnnotation.class.getMethod("key");
        Method value = MethodAnnotation.class.getMethod("value");
        Object defaultValue1 = key.getDefaultValue();
        Object defaultValue2 = value.getDefaultValue();
        // default key
        System.out.println(defaultValue1);
        // default value
        System.out.println(defaultValue2);
    }
}

结果

default key
default value

getParameterTypes()

返回一个 Class 对象数组,该数组以声明顺序表示该方法对象的参数对象 (擦除泛型)

public class MethodTest<T> {

    public void test(T t, LinkedList<Integer> list) {}

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", Object.class, LinkedList.class);
        Class<?>[] parameterTypes = method.getParameterTypes();
        // [class java.lang.Object, class java.util.LinkedList]
        System.out.println(Arrays.toString(parameterTypes));
    }
}

結果

[class java.lang.Object, class java.util.LinkedList]

getReturnType()

返回一个 Class 对象,该 Class 对象表示该方法对象的返回对象 (擦除泛型)

public class MethodTest<T> {

    // getReturnType()
    public T test(T t) {
        return t;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", Object.class);
        Class<?> returnType = method.getReturnType();
        // class java.lang.Object
        System.out.println(returnType);
    }
}

結果:

class java.lang.Object

getGenericReturnType()

返回一个 Type 对象,该 Type 对象表示该方法对象的返回类型 (保留泛型)

public class MethodTest<T> {
    // getGenericReturnType()
    public T test(T t) {
        return t;
    }
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test", Object.class);
        Type genericReturnType = method.getGenericReturnType();
        // T
        System.out.println(genericReturnType);
    }
}

結果:

T

getExceptionTypes()

返回一个 Class 对象数组,该数组表示由该方法对象抛出的异常对象 (擦除泛型)

public class MethodTest<T> {
    // getExceptionTypes()
    public <T extends Exception> void test() throws T, NullPointerException {}

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        Class<?>[] exceptionTypes = method.getExceptionTypes();
        // [class java.lang.Exception, class java.lang.NullPointerException]
        System.out.println(Arrays.toString(exceptionTypes));
    }
}

結果

[class java.lang.Exception, class java.lang.NullPointerException]

getGenericExceptionTypes()

返回一个 Type 对象数组,该数组表示由该方法对象抛出的异常类型 (保留泛型)

public class MethodTest<T> {
    //getGenericExceptionTypes()
    public <T extends Exception> void test() throws T, NullPointerException {}
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        Type[] genericExceptionTypes = method.getGenericExceptionTypes();
        // [T, class java.lang.NullPointerException]
        System.out.println(Arrays.toString(genericExceptionTypes));
    }
}

結果

 [T, class java.lang.NullPointerException]

getTypeParameters()

返回一个 TypeVariable 对象数组,该数组表示该方法对象声明列表上的类型变量数组

public class MethodTest<T,V> {
    // getTypeParameters()
    public <T, V> void test() {}
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        TypeVariable<Method>[] typeParameters = method.getTypeParameters();
        // [T, V]
        System.out.println(Arrays.toString(typeParameters));
    }
}

結果

[T, V]

toString()

返回该方法对象的字符串表示形式 (擦除泛型)

public class MethodTest<T,V> {
    // toString()
    public <T, V> void test() {}
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        // public void com.hb0730.test.MethodTest.test()
        System.out.println(method.toString());
    }
}

結果

public void com.hb0730.test.MethodTest.test()

toGenericString()

返回该方法对象的字符串表示形式 (保留泛型)

public class MethodTest<T,V> {
    // toGenericString()
    public <T, V> void test() {}
    public static void main(String[] args) throws NoSuchMethodException {
        Method method = MethodTest.class.getMethod("test");
        // public <T,V> void com.hb0730.test.MethodTest.test()
        System.out.println(method.toGenericString());
    }
}

結果

public <T,V> void com.hb0730.test.MethodTest.test()

isAccessible()

获取该方法对象的可访问标志

class Test{
    private void test() {}
}
public class MethodTest {

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test.class.getDeclaredMethod("test");
        // false
        System.out.println(method.isAccessible());
    }
}

結果

false

setAccessible(boolean flag)

  • 设置该方法对象的可访问标志
  • 在其他类里调用该方法对象时,如果该方法为私有方法,需要设置访问标志为 true,否则会报异常
//setAccessible(boolean flag)
class Test{
    private void test() {}
}
public class MethodTest {

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Test.class.getDeclaredMethod("test");
        method.setAccessible(true);
        //test
        System.out.println(method.getName());

    }
}

結果

test

isDefault()

判断该方法对象是否为默认方法,如果是则返回 true,否则为 false

// isDefault()
interface Interface {
    default void test() {
        System.out.println("这是一个默认方法");
    }
}

public class MethodTest {

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = Interface.class.getMethod("test");
        // true
        System.out.println(method.isDefault());

    }
}

結果

true

isSynthetic()

  • 判断该方法对象是否为合成方法,如果是则返回 true,否则为 false
  • 在内部类 InnerClass 中,name 是一个私有属性,而我们在外部类 MethodTest 中,直接引用了这个属性,因此编译器会生成一个合成方法,用于绕开 private 私有属性的限制
public class MethodTest {
    private class InnerClass {
        private String name = "小明";
    }

    public static void main(String[] args) throws NoSuchMethodException {
        InnerClass innerClass = new MethodTest().new InnerClass();
        // name: 小明
        System.out.println("name: " + innerClass.name);
        Method[] declaredMethods = innerClass.getClass().getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            // 【static java.lang.String lang.reflect.MethodTest$InnerClass.access$100(lang.reflect.MethodTest$InnerClass)】 isSynthetic(): true
            System.out.println("【" + declaredMethod + "】" + " isSynthetic(): " + declaredMethod.isSynthetic());
        }
    }
}

結果

name: 小明
【static java.lang.String com.hb0730.test.MethodTest$InnerClass.access$100(com.hb0730.test.MethodTest$InnerClass)】 isSynthetic(): true

isBridge()

  • 判断该方法对象是否桥接方法,如果是则返回 true,否则为 false
  • 桥接方法: 是 JDK1.5 引入泛型后,为了使 Java 的泛型方法生成的字节码和 1.5 版本前的字节码相兼容,由编译器自动生成的方法
public interface Interface<T> {

    T test(T t);
}

public class MethodTest implements Interface<String> {

    @Override
    public String test(String str) {
        return str;
    }

    public static void main(final String[] arguments) {
        Method[] declaredMethods = MethodTest.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            //【public static void lang.reflect.MethodTest.main(java.lang.String[])】 isBridge(): false
            //【public java.lang.String lang.reflect.MethodTest.test(java.lang.String)】 isBridge(): false
            //【public java.lang.Object lang.reflect.MethodTest.test(java.lang.Object)】 isBridge(): true
            System.out.println("【" + declaredMethod + "】" + " isBridge(): " + declaredMethod.isBridge());
        }
    }
}

系列

  1. Class
  2. Field
  3. Method

Thanks

  1. 作者:Gene Xu
    链接:https://blog.xujun.pro/2018/11/17/class-10-method%E7%B1%BB%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95%E8%A7%A3%E6%9E%90/
    来源:个人博客

  2. 作者: 易百教程
    链接: https://www.yiibai.com/javareflect/java_reflect_method.html
    来源: 易百教程