文章目录
前言
学习线程的过程,遇到了几个问题,而在几个问题,却是java的基础,同时也是经常用的地方。无所是优化代码还是看源码时,基本都能遇到,那就是**静态代理、reflect**
1. 什么是反射
java的反射机制是指在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个属性和方法;这种动态获取的类的信息,和动态调用对象的方法的功能就是反射机制。
从Java jdk1.1开始,专门提供了一个包:Java.lang.reflect,用于完成反射。
2. 作用
- 在运行时,构造任意一个类的对象
- 在运行时,判断任意一个类的完整结构,比如属性,方法,内部类,实现接口等
- 在运行时,判断任意一个对象所属的类
- 在运行时,调用任意一个对象的属性和方法
- 在运行时,生成动态代理
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);