Featured image of post java反射

java反射

本文阅读量

反射

是什么

加载类,并允许以编程的方式解剖列中的各种成分(成员变量、方法、构造器等)

反射学什么

  1. 反射第一步:加载类,获取类的字节码:Class对象

    Student.java -> 编译成Student.class -> 解析成 字节码文件 -> 加载到内存中去

  2. 获取类的构造器:Constructor对象

  3. 获取类的成员变量:Field对象

  4. 获取类的成员方法:Method对象

获取Class对象

获取Class对象有三种方式:

  1. Class c1 = 类名.class
  2. 调用Class提供方法:public static Class forName(String package)
  3. Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 方式1:类名.class
Class c1 = Student.class;
System.out.println(c1); // class cn.snailsir.reflect.Student cn.snailsir.reflect包下的Student类


// 方式2:Class.forName(全类名)
// public static Class forName(String package)
Class c2 = Class.forName("cn.snailsir.reflect.Student");
System.out.println(c2); // class cn.snailsir.reflect.Student


// 方式3:对象.getClass()
// public Class getClass();
Student s1 = new Student();
Class c3 = s1.getClass();
System.out.println(c3); // class cn.snailsir.reflect.Student

System.out.println(c1 == c2);// true
System.out.println(c2 == c3);// true

获取类构造器

Class提供了从类中获取构造器的方法

获取类构造器作用

返回初始化对象

常用方法

方法 说明
Constructor[] getConstructors() 获取全部构造器(只能获取public修饰的)
Constructor[] getDeclaredConstructors() 获取全部构造器(只要存在就能拿到)
Constructor<T> getConstructor(Class… parameterTypes) 获取某个构造器(只要获取public修饰的)
Constructor<T> getDeclaredConstructor(Class… parameterTypes) 获取全部构造器(只要存在就能拿到)

案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Test
public void testGetCOnstructors(){
  // 获取类的Class对象
  Class c = Cat.class;
  // 获取类的全部构造器
  // Constructor[] constructors = c.getConstructors();
  Constructor[] constructors = c.getDeclaredConstructors();
  // 遍历构造器
  for(COnstructor con:constructors){
    System.out.println(con.getName() + "==>" + con.getParameterCount());
  }
}



@Test
public void testGetCOnstructor() throws Exception{
  // 获取类的Class对象
  Class c = Cat.class;
  // 获取类的某个构造器:无参构造器
  // Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
  Constructor con1 = c.getDeclaredConstructor();// 定位无参构造器
  Constructor con2 = c.getDeclaredConstructor(String.class,int.class); // 定位有参构造器
  // 遍历构造器
  for(COnstructor con:constructors){
    System.out.println(con.getName() + "==>" + con.getParameterCount());
  }
  // 初始化对象
  // T newInstance(Object... initargs)
  Cat c1 = (Cat) con1.newInstance();
  System.out.println(c1);
  
  con2.setAccessible(true); // 禁止检查访问权限(暴力反射)
  Cat c2 = (Cat) con2.newInstance("叮当猫",30); // 如果con2.setAccessible(true)不加,私有的有参构造器则无法初始化,加上了,则可以初始化
  System.out.println(c2);
}

获取类的成员变量

Class提供了从类中获取成员变量的方法

获取类成员变量作用

依然是赋值、取值

常用方法

方法 说明
Public Field[] getFields() 获取类的全部成员变量(只能获取public修饰的)
Public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
Public Field getField(String name) 获取类的某个成员变量(只要获取public修饰的)
Public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)
方法 说明
void set(Object obj,Object value) 赋值
Object get(Object obj) 取值
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Class c = Cat.class;
// 获取类的全部成员变量
// Public Field[] getDeclaredFields()
Field[] fields = c.getDeclaredFields();
for(Field field:fields){
  System.out.println(field.getType()+"==>"+field.getName());
}
// 定位某个成员变量
Field fname = c.getDeclaredField("name");
// 取值
Cat cat = new Cat();
fname.setAccessible(true);// 暴力反射
fname.set(cat,"多啦A梦");
String name = (String)fname.get(cat);
System.out.println(name);

获取类的成员方法

Class提供了从类中获取成员方法的API

获取类成员变量作用

依然是执行

常用方法

方法 说明
Method[] getMethods() 获取类的全部成员方法(只能获取public修饰的)
Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能拿到)
Method getMethod(String name,Class… parameterTypes) 获取类的某个成员方法(只要获取public修饰的)
Method getDeclaredMethod(String name,Class… parameterTypes) 获取类的某个成员方法(只要存在就能拿到)
Method提供的方法 说明
public Object invoke(Object obj,Object… args) 触发某个对象的该方法执行
public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)

案例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Class c = Cat.class;
// 获取类的全部成员方法
Method[] methods = c.getDeclaredMethods();

for(Method method:methods){
  System.out.println(method.getName()+" "+method.getParameterCount());
}

// 定位单个方法
Method eat1 = c.getDeclaredMethod("eat");
Method eat2 = c.getDeclaredMethod("eat",String.class);

// 定位方法的目的:依然是执行它
Cat cat = new Cat();
Object result = eat1.invoke(cat); // 无参

eat2.setAccessible(true);
Object result2 = eat2.invoke(cat,"鱼儿"); // 有参
System.out.println(result2);

作用

基本作用:可以得到一个类的全部成分然后进行操作(Idea提示)

可以破坏封装性

最重要的用途:适合做java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能

使用 Hugo 构建
主题 StackJimmy 设计