java基础:反射(Reflect)

前言

学习线程的过程,遇到了几个问题,而在几个问题,却是java的基础,同时也是经常用的地方。无所是优化代码还是看源码时,基本都能遇到,那就是**静态代理、reflect**

1. 什么是反射

java的反射机制是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个属性和方法;这种动态获取的类的信息,和动态调用对象的方法的功能就是反射机制。

从Java jdk1.1开始,专门提供了一个包:Java.lang.reflect,用于完成反射。

2. 作用

  1. 在运行时,构造任意一个类的对象
  2. 在运行时,判断任意一个类的完整结构,比如属性,方法,内部类,实现接口等
  3. 在运行时,判断任意一个对象所属的类
  4. 在运行时,调用任意一个对象的属性和方法
  5. 在运行时,生成动态代理

3. 关键的类

  • Class类是反射类的基础,在java.lang包下(java.lang.Class),有四种方式可以获取Class类对象
  • Field,Method,Constructor 都在java.lang.reflect包下
  • Field是获取Class对象中的属性
  • Method是获取Class对象中的方法(不包含构造方法)
  • Construct是获取Class对象中的构造函数

4.代码测试

可以说是对以上4个部分,用代码的方式实现出来。

4.1 获取Class

package com.feng.springboottest.other.reflect;

public class ReflectTest01 {
    public static void main(String[] args) {
        Person p = new Person();
        // 方法一 : 调用运行时类的.class属性
        Class c1 = Person.class;
        System.out.println("方法一 : 调用运行时类的.class属性: "+c1.toString());
        // 方法二 : 通过运行时类的对象,调用getClass()方法
        Class c2 = p.getClass();
        System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c2.toString());
        // 方法三 : 调用Class的静态方法forName
        Class c3 = null;
        try {
            c3 = Class.forName("com.feng.springboottest.other.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("方法三 : 调用Class的静态方法forName: "+c3.toString());
        // 方法四 :通过类的加载器
        ClassLoader classLoader = Person.class.getClassLoader();
        Class c4 = null;
        try {
            c4 = classLoader.loadClass("com.feng.springboottest.other.reflect.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("方法四 :通过类的加载器: "+c4.toString());
    }
}

在这里插入图片描述

4.2 创建 类的对象(运行时)

System.out.println("----------------------------创建对应的类的对象(运行时)----------------------------------");

//方法一:调用Class的newInstance方法创建运行时类的对象
Class c5 = person.getClass();
Person person1 = (Person)c5.newInstance();
System.out.println("方法一:调用Class的newInstance方法创建运行时类的对象  --person: "+person1);

//方法二:调用指定的构造器创建运行时类的对象
//我们指定public类型的构造方法Person(String name,int age,int id)来创建对象
Constructor constructor1 = c5.getDeclaredConstructor(int.class, String.class);
person1 = (Person) constructor1.newInstance(1,"22");
System.out.println("方法二:调用指定的构造器(public)创建运行时类的对象 --person: "+person1);

//我们指定private类型的构造方法Person(String name)来创建对象
constructor1 = c5.getDeclaredConstructor(int.class);
constructor1.setAccessible(true);
person1 = (Person) constructor1.newInstance(22);
System.out.println("方法三:调用指定的构造器(private)创建运行时类的对象 --person: "+person1);

在这里插入图片描述

4.3 获取构造方法

System.out.println("----------------------------获取类 public 的构造方法----------------------------------");
Class c6 = Person.class;
System.out.println("getConstructors 为获取类的 public 的构造方法 ");// 无法获取私有的
Constructor[] constructors1 = c6.getConstructors();
for(int i=0;i<constructors1.length;i++){
    System.out.println("constructors ["+i+"] :"+constructors1[i]);
}

System.out.println("----------------------------获取类的 所有 的构造方法, 包括私有的----------------------------------");

System.out.println("getDeclaredConstructors 获取类的 所有的 构造方法 ");
Constructor[] constructors2 = c6.getDeclaredConstructors();
for(int i=0;i<constructors2.length;i++){
    System.out.println("constructors ["+i+"] :"+constructors2[i]);
}

在这里插入图片描述

4.4 根据构造方法创建对象

System.out.println("----------------------------获取类的 指定的构造方法,并使用 public 和private 构造方法 创建对象----------------------------------");
Class c7 = Person.class;

//调用指定的构造器创建运行时类的对象
//我们指定public类型的构造方法Person(String name)来创建对象
Constructor<?> constructor = c7.getDeclaredConstructor(int.class,String.class);
Person person01 = (Person) constructor.newInstance(1,"xl");
System.out.println("调用指定的构造器(public)创建运行时类的对象 --person: "+person01);

//我们指定private类型的构造方法Person(String name)来创建对象
constructor = c7.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
person = (Person) constructor.newInstance("15");
System.out.println("调用指定的构造器(private)创建运行时类的对象 --person: "+person);

在这里插入图片描述

4.5 获取本类方法

System.out.println("----------------------------获取Class中 public 方法,包括 父类的 public:----------------------------------");

Person person2 = new Person();
Class<? extends Object> c8 = person2.getClass();
//getMethods此方法为获取类的 public 方法,包括父类的public方法
System.out.println("getMethods此方法为获取类的public方法,包括父类的 public方法 ");
Method[] methods = c8.getMethods();
for (int i = 0; i< methods.length; i++){
    System.out.println("method1 ["+i+"] :"+methods[i]);
}
System.out.println("----------------------------获取Class类本身声明的所有方法,包括private :----------------------------------");

Person person3 = new Person();
Class<? extends Object> c9 = person3.getClass();
//getDeclaredMethods此方法为获取类本身声明的所有方法,包括private
System.out.println("getDeclaredMethods此方法为获取类本身声明的所有方法,包括private ");
Method[] method2 = c9.getDeclaredMethods();
for(int i=0;i<method2.length;i++){
    System.out.println("method2 ["+i+"] :"+method2[i]);
}

在这里插入图片描述

4.6 调用类方法(以私有方法为例)

System.out.println("----------------------------获取并调用类本身声明的方法,包括private类型的方法,以 write (私有)方法为例 :----------------------------------");

Person person4 = new Person();
Class<? extends Object> c10 = person4.getClass();
//1.对private类型的方法进行操作
System.out.println("getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以 write (私有)方法为例:");
Method m1 = c10.getDeclaredMethod("write", int.class);
System.out.println("方法的完整路径 toGenericString:"+m1.toGenericString());
System.out.println("方法的完整路径 toString:"+m1.toString());
System.out.println("方法的名称(仅有名称) toString:"+m1.getName());
m1.setAccessible(true);
Object invoke = m1.invoke(person4, 22);
System.out.println("执行 write 方法后 :"+invoke);

在这里插入图片描述

4.7 获取类属性

System.out.println("----------------------------获取Class类本身声明的所有方法,包括父类的public属性:----------------------------------");

Person person5 = new Person();
Class<? extends Object> c11 = person5.getClass();

System.out.println("getFields此方法为获取类的public属性,包括父类的public属性 ");
Field[] field1 = c11.getFields();
for(int i=0;i<field1.length;i++){
    System.out.println("field1 ["+i+"] :"+field1[i]);
}
System.out.println("----------------------------获取类的本身声明的所有属性,包括private:----------------------------------");
Class<? extends Object> c12 = Person.class;
System.out.println("getDeclaredFields此方法为获取类的本身声明的所有属性,包括private ");
Field[] field2 = c12.getDeclaredFields();
for(int i=0;i<field2.length;i++){
    System.out.println("field2 ["+i+"] :"+field2[i]);
}

在这里插入图片描述

4.8 操作类属性

System.out.println("----------------------------对本类属性进行操作,以类本身的private属性name为例 :----------------------------------");

Person person6 = new Person("feng");
Class<? extends Object> c13 = person6.getClass();

System.out.println("对public类型的属性进行操作,以类本身的private属性name为例");
Field field3 = c13.getDeclaredField("name");
field3.setAccessible(true);
String name = (String)field3.get(person6);
System.out.println("修改前 person 对象name:"+name);

field3.set(person6, "fenganchen");
name = (String)field3.get(person6);
System.out.println("修改后person对象的name:"+name);

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java冯坚持

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值