天天看点

反射那点基础-Method

@

目录

  • 1 获取 Method
    • 1.1 方法
    • 1.2 实例
  • 2 Method 的方法
    • 2.1 Java 方法基础知识
    • 2.2 修饰符相关方法
      • 2.2.1 获取修饰符
      • 2.2.2 判断是否为 default 方法
      • 2.2.3 判断是否为 bridge 方法
      • 2.2.4 判断是否为 synthetic 方法
      • 2.3 获取返回值类型
    • 2.4 获取方法名
    • 2.5 获取返回值
      • 2.5.1 方法
      • 2.5.2 测试
      • 2.6 参数
    • 2.7 异常
      • 2.7.1 方法
      • 2.7.2 测试
    • 2.8 注解
    • 2.9 调用相关
      • 2.9.1 访问权限控制
      • 2.9.2 方法调用
      • 2.9.3 测试

Method

类描述的是类对象的方法信息。 其中包含了被反射方法的信息, 访问信息。在运行时, 我们可以通过该类进行方法的调用。

因为 Java 中的

java.lang.reflect

包下所有类的构造函数都不为 public, 同时类都是 final 类型的, 因此, 不能直接通过外部 new 来获取该方法。

获取所有的 public 方法,包括其父类, 接口的

public Method[] getMethods();
           

获取指定参数的 public 方法, 包括其父类, 接口的

public Method getMethod(String name, Class<?>... parameterTypes);
           

获取声明(public, private, protected, friendly)的所有普通方法

public Method[] getDeclaredMethods();
           

获取声明(public, private, protected, friendly)的指定参数的普通方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes);
           

该实例称为实例1。

定义父类

public class ParentClass {
    private String privateMethod(){
        return "ParentClass::privateMethod";
    }
    String defaultMethod(){
        return "ParentClass::defaultMethod";
    }
    protected String protectedMethod(){
        return "ParentClass::protectedMethod";
    }
    public String publicMethod(){
        return "ParentClass::public";
    }
}
           

定义子类

public class ChildClass extends ParentClass {
    private String childPrivateMethod(){
        return "ChildClass::childPrivateMethod";
    }
    String childDefaultMethod(){
        return "ChildClass::childDefaultMethod";
    }
    protected String childProtectedMethod(){
        return "ChildClass::childProtectedMethod";
    }
    public String childPublicMethod(){
        return "ChildClass::childPublicMethod";
    }
           

测试类

public class MethodTest {
    public static void main(String[] args) {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getMethods();
        System.out.println("============getMethods================");
        for (Method method:methods) {
            System.out.println(method.getName());
        }

        Method[] dMethods = childClass.getDeclaredMethods();
        System.out.println("============getMethods================");
        for (Method method:dMethods) {
            System.out.println(method.getName());
        }
    }
}

           

输出

反射那点基础-Method

Method

是存储方法相关的信息, 因此, 其方法及属性都跟这些相关。

下面是一个方法的属性:

  1. 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
  2. 返回值 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
  3. 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
  4. 参数:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
  5. 异常:方法中抛出的异常类型。
  6. 注解:方法上的注解。

在 Java 中, 修饰符以数字的形式存在, 通过 int 存储了32位的数字, 就可以存储多个数值, 此种存储方式在

Modifier

中会进行讲解。

public int getModifiers() {
        return modifiers;
    }
           

同样以之前 [实例1] 的代码进行测试, 重写写一个测试方法

public static void main(String[] args) {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getMethods();
        System.out.println("============getMethods================");
        for (Method method:methods) {
            System.out.println(method.getName()+"::"+Modifier.toString(method.getModifiers()));
        }
    }
           

结果

反射那点基础-Method

public boolean isDefault() {
        // Default methods are public non-abstract instance methods
        // declared in an interface.
        return ((getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) ==
                Modifier.PUBLIC) && getDeclaringClass().isInterface();
    }
           

这是 Java 8 中引入的概念:默认方法是在接口中声明的, public, 非 abstract 的实体方法(实体方法即不是 static 方法)。

在此处不展开。

public boolean isBridge() {
        return (getModifiers() & Modifier.BRIDGE) != 0;
    }
           

判断是否为桥接方法。

public boolean isSynthetic() {
        return super.isSynthetic();
    }
           

判断是否为 synthetic 方法。

public Class<?> getReturnType() {
        return returnType;
    }
           

public String getName() {
        return name;
    }
           

获取返回值的类型有两种:

获取到返回值的

Class

类型的对象

public Class<?> getReturnType() {
        return returnType;
    }
           

Type

public Type getGenericReturnType() {
      if (getGenericSignature() != null) {
        return getGenericInfo().getReturnType();
      } else { return getReturnType();}
    }
           

定义类

public class Animal {
    private Map<String,Animal> friends = new HashMap<>();

    public void addFriend(String name, Animal animal){
        friends.put(name,animal);
    }

    public Animal callFriend(String name){
        return friends.get(name);
    }

    public<T extends Animal> T callFriend(String name, T unusedTypeObj){
        return (T)friends.get(name);
    }

    public static void main(String[] args) {
        Class<Animal> clazz = Animal.class;
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method:methods) {
            System.out.println(method.getName()+"::"+method.getReturnType()+"::"+method.getGenericReturnType());
        }
    }
}
           
反射那点基础-Method

获取所有的参数, 返回值是

Class

数组

public Class<?>[] getParameterTypes()
           

获取所有参数, 返回值是

Type

public Type[] getGenericParameterTypes()
           

获取参数的所有注解

public Annotation[][] getParameterAnnotations()
           

获取所有的异常, 返回值是

Class

public Class<?>[] getExceptionTypes()
           

Type

public Type[] getGenericExceptionTypes()
           

获取注解异常

public AnnotatedType[] getAnnotatedExceptionTypes()
           

public class ExceptionExample {
    public static void main(String[] args) throws Exception {
        Method m = ExceptionExample.class.getMethod("method");
        System.out.println(m.getGenericExceptionTypes()[0]);
        System.out.println(m.getExceptionTypes()[0]);
    }   
    public static <T extends Throwable> void method() throws T {}
}
           
反射那点基础-Method

获取声明的所有注解

public Annotation[] getDeclaredAnnotations()
           

抑制Java的权限控制检查:在针对非public时方法时, 可以考虑这么用

public void setAccessible(boolean flag)
           

方法调用

public Object invoke(Object obj, Object... args)
           

使用示例1中的代码

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Class<ChildClass> childClass = ChildClass.class;
        Method[] methods = childClass.getDeclaredMethods();
        System.out.println("============getMethods================");
        ChildClass child = new ChildClass();
        for (Method method:methods) {
            method.setAccessible(true);
            System.out.println(method.invoke(child));
        }
           

如果注释权限控制, 输出如下

反射那点基础-Method

取消注释之后

反射那点基础-Method

作者:阿进的写字台

出处:https://www.cnblogs.com/homejim/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。