栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

8-java反射-基础反射知识

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

8-java反射-基础反射知识

java反射-基础反射知识

文章目录
  • java反射-基础反射知识
  • 反射
    • 1. 反射示意图
    • 2. 获取 Class对象 的方法
      • 2.1 getClass方法
      • 2.2 class属性
      • 2.3 forName方法
    • 3. CLass对象的创建时间
    • 4. 使用Class对象创建类的对象
    • 5. 获取CLass对象的内容
      • 5.1 获取构造方法
        • 面试小技巧
      • 5.2 获取成员变量
      • 5.3 获取方法


反射

反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。

主要用在企业级框架底层,可以动态根据 IO 读到的一些类、接口、枚举、注解等的信息,进而让其中的成员变量、方法、构造方法运行起来

  • 目的:不使用 new 关键字创建对象,还能让其中的变量、方法执行
  • 核心:1. 获取到某个 class 文件;2. 动态分析 class 中的内容
1. 反射示意图

任何 class文件 都是一个个体。
以下图为例,我们写了几个自定义类,它们编译后生成的 class文件, 本质上都是 Class类的一个实例。
也即如果程序中可得到 Class对象,也即一定获取到一个具体的 class文件。

这也是 java OO思想的体现,任何事物都是一个对象,包括编译生成的 class文件

2. 获取 Class对象 的方法 2.1 getClass方法

在 Object类 中定义了getClass方法。

Person p = new Person();
Class clazz = p.getClass();// class reflection.Person

int[] arr = new int[3];
Class clazz2 = arr.getClass();// class [I
2.2 class属性

任何类型,java 均配了一个class属性

Class clazz = Person.class;// class reflection.Person

Class clazz2 = int[].class;// class [I
2.3 forName方法

常用方法,前两种方法实际上已经知道是什么类了,有些多此一举。使用 Class类 的静态方法可以得到 Class对象

Class.forName("com.mysql.jdbc.Driver")获取到Driver的class类对象,参数必须写全路径。

3. CLass对象的创建时间

Class对象(.class文件) 是 JVM 将 class文件加载至方法区时,会自动在堆中创建出当前这个class文件对应的唯一对象,实际上 new对象时,不是通过方法区的class文件创建的,而是根据堆中这个 class对象创建的。

4. 使用Class对象创建类的对象

newInstance方法要求被反射的class文件中,一定有默认的公开构造,即无参数公开构造

CLass clazz = CLass.forName("reflection.Person");
Object obj = clazz.newInstance();// 注意该方法在JDK9后弃用
// newInstance方法要求被反射的class文件中,一定有默认的公开构造,即无参数公开构造
System.out.println(obj);//reflection.Person@6833ce2c

但是 newInstance 方法只能构造公开无参的,不方便,所以还是获取到其中的构造方法,再去使用会更加方便

5. 获取CLass对象的内容

对于一个类而言,重要的就是 成员变量、构造方法、成员方法。反射解析出这些成员后,再封装成不同的对象。

  • 成员变量: Field
  • 构造方法: Constructor
  • 成员方法: Method

以Person为例来获取其中内容

public class Person {
    private int id;
    public String name;
    public Person(){

    }
    public Person(int id){
        this.id = id;
    }
    private Person(int id, String name){
        this.id = id;
        this.name = name;
    }
    private void say(){
        System.out.println("say");
    }
    public int hi(String name){
        System.out.println("hi" + name);
        return 0;
    }
}
5.1 获取构造方法

getConstructor(参数类型)获取某个特定的构造函数

Class clazz = Class.forName("reflection.Person");
Constructor cons = clazz.getConstructor(int.class);
System.out.println(cons); // public reflection.Person(int)
Object obj = cons.newInstance(123);
// obj就是创建的Person对象,依据的构造是仅有一个int参数的构造

getConstructores()获取所有的公开的构造方法

Class clazz = Class.forName("reflection.Person");
Constructor[] cons = clazz.getConstructors(int.class);
for(Constructor c:cons){
    System.out.println(c);
}

getDeclaredConstructor()获取所有构造函数,包括私有构造。仅仅获取私有构造是不能用的,必须修改权限。Constructor继承了AccessibleObject,可以修改权限。

Class clazz = Class.forName("reflection.Person");
Constructor cons = clazz.getDeclaredConstructor(int.class, String.class);
cons.setAccessible(true); // 修改权限
System.out.println(cons); // private reflection.Person(int,java.lang.String)
Object obj1 = cons.newInstance(123, "321");
System.out.println(obj1); // reflection.Person@6833ce2c
面试小技巧

面试如果问到 private、public等的时候,说private是私有的,不能让外界访问的,可以说但是通过反射技术可以取消访问控制,然后将话题转向反射

5.2 获取成员变量

使用的场景较少, 使用 getField 获取成员变量,然后利用 set 方法设置某个对象该成员变量的值, 也可以利用 get 方法获取值

小细节如果是静态成员变量,那么传入的参数是null就可以正常获取了

Field field = clazz.getField("name");
field.set(obj, "jack");
System.out.println(obj); // reflection.Person@2aaf7cc2
System.out.println(field.get(obj));// jack
5.3 获取方法
  • getMethod:获取特定方法,
  • getDeclaredMethod:获取包含私有的方法,使用时需要取消权限检查
  • getMethods:获取所有public方法,包含它所有父类的方法
  • getDeclaredMethods: 获取当前类的所有方法,含私有,不含父类的
  • 如果反射静态方法,传入的对象写为null即可
Class clazz = Class.forName("...");
// 依靠方法名与参数列表来反射方法
Method method = clazz.getMethod("say", String.class);
Object obj = clazz.newInstance();
// invoke方法是是method方法运行,参数:运行该方法的对象,该方法的参数,返回值:被反射的方法的返回值
Object ret = method.invoke(obj);

Method method = clazz.getMethod("hi", null);
method.setAccessible(true);
method.invoke(obj);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/310069.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号