zoukankan      html  css  js  c++  java
  • 反射那点基础-Method

    @

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

    1 获取 Method

    1.1 方法

    因为 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.2 实例

    该实例称为实例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());
            }
        }
    }
    
    

    输出
    获取方法

    2 Method 的方法

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

    2.1 Java 方法基础知识

    下面是一个方法的属性:

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

    2.2 修饰符相关方法

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

    2.2.1 获取修饰符

        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()));
            }
        }
    

    结果

    获取方法修饰符

    2.2.2 判断是否为 default 方法

    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 方法)。

    在此处不展开。

    2.2.3 判断是否为 bridge 方法

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

    判断是否为桥接方法。

    2.2.4 判断是否为 synthetic 方法

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

    判断是否为 synthetic 方法。

    2.3 获取返回值类型

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

    2.4 获取方法名

        public String getName() {
            return name;
        }
    

    2.5 获取返回值

    2.5.1 方法

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

    获取到返回值的 Class类型的对象

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

    获取到返回值的 Type类型的对象

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

    2.5.2 测试

    定义类

    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());
            }
        }
    }
    

    输出
    返回值类型

    2.6 参数

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

     public Class<?>[] getParameterTypes()
    

    获取所有参数, 返回值是 Type 数组

    public Type[] getGenericParameterTypes()
    

    获取参数的所有注解

    public Annotation[][] getParameterAnnotations()
    

    2.7 异常

    2.7.1 方法

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

    public Class<?>[] getExceptionTypes()
    

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

    public Type[] getGenericExceptionTypes()
    

    获取注解异常

    public AnnotatedType[] getAnnotatedExceptionTypes()
    

    2.7.2 测试

    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 {}
    }
    

    输出

    运行结果

    2.8 注解

    获取声明的所有注解

    public Annotation[] getDeclaredAnnotations()
    

    2.9 调用相关

    2.9.1 访问权限控制

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

    public void setAccessible(boolean flag)
    

    2.9.2 方法调用

    方法调用

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

    2.9.3 测试

    使用示例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));
            }
    

    如果注释权限控制, 输出如下
    结果
    取消注释之后

    结果

  • 相关阅读:
    静态工具类中使用注解注入service
    赵伟国:芯片不像互联网 不能一招鲜吃遍天(发展芯片制造业已拥有三个纵深:市场纵深、资本纵深、人才纵深)
    将grub写入mbr
    Linux下Qt5.6 Fcitx无法输入中文输入解决办法
    为 Mac Finder 增加右键文件打包压缩(免费)
    Obtaining Directory Change Notifications(微软的例子,使用FindFirstChangeNotification,FindNextChangeNotification,FindCloseChangeNotification API函数)
    C#开发Linux守护进程
    排序算法比较与分析
    Mvc+Dapper+存储过程分页10万条数据
    RabbitMQ
  • 原文地址:https://www.cnblogs.com/homejim/p/10135256.html
Copyright © 2011-2022 走看看