zoukankan      html  css  js  c++  java
  • [01] 反射的基本概念和常用类


    1、什么是反射

    在了解反射之前,我们都是如何使用一个Java类的?
    • 已知一个类的类名,以及类中的方法、属性和构造方法等
    • 调用构造方法创建对象
    • 使用对象调用方法或者属性

    那么问题来了,如果我们只知道一个类的类名,能否动态得到类的信息,包括其方法和属性?
    • 通过反射

    所以反射的概念是:在运行状态中,对任意类都可知道其所有属性和方法,对任意对象都可调用其方法和属性。这种动态获取信息以及动态调用对象方法的功能,称之为Java的反射机制。

    如Spring框架只需要通过xml文件描述类的基本信息,就可以利用反射机制动态装配对象。

    2、反射的相关类

    和反射相关的类主要包括 Class、Constructor、Method、Field等,除了Class,其他的类都位于java.lang.reflect包中。其中最重要的类是Class,可以说,反射的使用都是从Class开始的。

    2.1 Class类

    2.1.1 Class实例的获取
    把一个类封装成为Class类,Class实例主要有三种方式获取:
    • //使用对象名获取
    • String str = "hello";
    • Class clazz = str.getClass();

    • //使用类名获取,在类名加后缀 .class
    • Class clazz = String.class;

    • //使用类名获取,通过Class的静态方法forName()
    • Class clazz = Class.forName("java.lang.String");

    2.1.2 Class类的主要方法
    Class类中的主要方法有:
    • getMethod:返回类中某个方法的实例
    • getMethods:返回类中所有方法的实例
    • getField:返回类中某个属性的实例
    • getFields:返回类中所有属性的实例
    • getConstructor:返回类中的一个构造方法的实例
    • getXXX:Class中还有若干get方法,获取类的基本信息

    需要注意的是,以上涉及的获取Method或Field实例的方法,实际上还有一个类似的方法,不过名字中多个词Declared,如getDeclaredMethods(),区别在于:
    • 包含Declared:它仅获取自身类声明的方法,包括公开的、私有的、保护的等
    • 没有Delcared的普通get方法:会获取某个类所有的公开(public)成员,包括自己定义的和继承下来的

    简单示例:
    public static void main(String[] args) { 
        Class clazz_str = String.class;
        Method[] methods = clazz_str.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
    }

    2.2 Constructor类

    2.2.1 实例的获取
    Constructor类的对象是由Class对象获取,Class类中定义了如下方法:
    • Constructor<T> getConstructor(Class... parameterTypes):通过指定参数类型,返回构造方法实例
    • Constructor[] getConstructors():返回该类的所有构造方法实例

    这里所说的指定的参数类型,是指实际构造方法的形参。比如有构造方法 public Student(String name),那么需要:
    Class stuClazz = Student.class;
    Constructor stuCon = stuClazz.getConstructor(String.class);

    2.2.2 实例的基本信息获取
    该类可以通过getXXX的方法,获取构造方法的基本信息,如:
    • getName:返回构造方法的名字
    • getParameterTypes:返回构造方法的参数类型

    2.2.3 创建对象
    除了构造方法的基本信息,也可以通过该Constructor的实例创建对象:
    • newInstance(Object... initargs);

    示例:
    Class stuClazz = Student.class;
    Constructor stuCon = stuClazz.getConstructor(String.class);
    Student stu = (Student)stuCon.newInstance("zhangsan");

    2.3 Method类

    2.3.1 Method的获取
    Method类的实例由Class对象获取:
    • Method getMethod(String name, Class... parameterTypes):通过指定方法名,参数类型,返回Method实例
    • Method[] getMethods():返回该类中所有方法的Method实例

    2.3.2 Method获取基本信息
    Method封装了类中的方法,可以动态获取方法的信息,如:
    • getReturnType:获取方法的返回值类型
    • getName:获得方法名
    • getParameterTypes:获得方法参数类型

    2.3.3 Method动态调用方法
    除了动态获得方法信息,Method类还可以动态调用某个对象的具体方法:
    • invoke(Object obj, Object... args);

    示例:
    public static void main(String[] args) throws Exception {
        Class stuClazz = Student.class;
        Constructor stuCon = stuClazz.getConstructor(String.class);
        Student student = (Student)stuCon.newInstance("zhangsan");
    
        Method study = stuClazz.getMethod("study");
        study.invoke(student);
    
        Method studyWithOne = stuClazz.getMethod("studyWithOne", String.class);
        studyWithOne.invoke(student, "lisi");
    }

    2.4 Field类

    2.4.1 Field的获取
    获得Field实例,都是通过Class中的方法实现的:
    • public Field getField(String name)  
    • 通过指定Field的名字,返回Field实例
    • 注意Field的访问权限

    之前提到过,如果单纯地使用getField那么获取到的方法实例都是public的,如果要获取private方法,需要使用诸如getDeclaredField方法:
    //如有Student类,有private权限的属性name
    Class stuClazz = Student.class;
    Field name = stuClazz.getField("name"); // NG,报异常,找不到该方法
    Field name = stuClazz.getDeclaredField("name"); // OK

    备注:
    Java Field.get()取得对象的Field属性值,即field.get(Class clazz)可以获取对象属性的值,类似于调用无限制的getter方法

    3、反射的重要说明

    反射实际上将所有的类成分映射成为对应的的Class对象,这里的Class对象其实可以堪称是一种类型。并不知只有类才能转换成Class对象。

    也即是说,如果真的需要(比如某些方法中要求参数是Class类型),像基本的数据类型(boolean、byte、char、short、int、long、float、double)甚至关键字如 void 也可以表示为Class对象(形如 int.class)

    比如某些方法,如果你要用反射表示,可能参数可能会写成如 (String.class, int.class) 这种形式,这是sun公司定义的规则,不需要深刻去理解为什么。

    例如 getConstructor(Class<?>... parameterTypes):
    Class stuClazz = Student.class;
    Constructor stuCon = stuClazz.getConstructor(String.class);

  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/deng-cc/p/7462557.html
Copyright © 2011-2022 走看看