Java高级-04.反射-获取成员变量和方法对象并使用
目录
Java高级-04.反射-获取成员变量和方法对象并使用
一.获取类的成员变量
package com.njau.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY = "中国";
private String name;
private int age;
public Cat(String name, int age) {
System.out.println("有参数构造器执行了!");
this.name = name;
this.age = age;
}
public Cat() {
System.out.println("无参构造器执行了!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
* public Field[] getFields() 获取类的全部成员变量(只能获取public修饰的) * public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到) * public Field getField() 获取类的某个成员变量(只能获取public修饰的) * public Field getDeclaredField() 获取类的全部成员变量(只要存在就能拿到)
返回回来的是一个Filed类型的对象。可以使用数组接收多个。
package com.njau.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
/**
* 目标:掌握获取类的成员变量
* 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,表示禁止检查访问控制(暴力反射)
*/
public class Test3Field {
@Test
public void testGetFields() throws Exception {
// 1、反射第一步:首先获取到类Class对象
Class c = Cat.class;
// 2、public Field[] getFields() 获取类的全部成员变量(只能获取public修饰的)
// Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields(); // 获取类的全部成员变量(只要存在就能拿到)
for (Field field : fields) {
System.out.println(field.getName() + "--->" + field.getType());
}
// 3、public Field getField(String name) 获取类的某个成员变量(只能获取public修饰的)
Field fName = c.getDeclaredField("name");
System.out.println(fName.getName() + "--->" + fName.getType()); // name--->class java.lang.String
// 4、public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)
Field fAge = c.getDeclaredField("age");
System.out.println(fAge.getName() + "--->" + fAge.getType()); // age--->int
}
}
获取成员变量的作用:依然是赋值、取值
使用set进行赋值,但是赋值时必须要创建出该类的实例化对象,否则这个值又赋给谁呢?同样的,使用get方法时也要传入该类的实例化对象,否则不知道获取哪个对象的成员变量值。
注意:我们在获得构造器和成员变量的时候均不用setAccessible方法,而是在 使用 构造器实例化对象和使用成员变量赋值的时候,对于私有的构造器和成员变量才要使用setAccessible方法。成员方法也和上述一样。
package com.njau.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
/**
* 目标:掌握获取类的成员变量
* Class提供了从类中获取成员变量的方法
* public Field[] getFields() 获取类的全部成员变量(只能获取public修饰的)
* public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
* public Field getField() 获取类的某个成员变量(只能获取public修饰的)
* public Field getDeclaredField() 获取类的全部成员变量(只要存在就能拿到)
* 获取到成员变量的作用:依然是赋值,取值
* void set(Object obj,Object value) 赋值
* Object get(Object obj) 取值
* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
*/
public class Test3Field {
@Test
public void testGetFields() throws Exception {
// 1、反射第一步:首先获取到类Class对象
Class c = Cat.class;
// 2、public Field[] getFields() 获取类的全部成员变量(只能获取public修饰的)
// Field[] fields = c.getFields();
Field[] fields = c.getDeclaredFields(); // 获取类的全部成员变量(只要存在就能拿到)
for (Field field : fields) {
System.out.println(field.getName() + "--->" + field.getType());
}
// 3、public Field getField(String name) 获取类的某个成员变量(只能获取public修饰的)
Field fName = c.getDeclaredField("name");
System.out.println(fName.getName() + "--->" + fName.getType()); // name--->class java.lang.String
// 4、public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)
Field fAge = c.getDeclaredField("age");
System.out.println(fAge.getName() + "--->" + fAge.getType()); // age--->int
}
@Test
public void testSetAndGet() throws Exception {
Class c = Cat.class;
Cat cat = new Cat();
// 获取某个类的成员变量
Field fName = c.getDeclaredField("name");
// public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
fName.setAccessible(true); // 禁止访问控制权限
// void set(Object obj,Object value) 赋值
fName.set(cat, "招财猫");
// Object get(Object obj) 取值
String name = (String) fName.get(cat);
System.out.println(name);
System.out.println(cat);
Field fAge = c.getDeclaredField("age");
// public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
fAge.setAccessible(true);
// void set(Object obj,Object value) 赋值
fAge.set(cat,3);
// Object get(Object obj) 取值
int age = (int) fAge.get(cat);
System.out.println(age);
System.out.println(cat);
}
}
调用get方法时并不知道返回的成员变量类型,因此java官方为我们设定了Object类型。但是我们要将其进行强制转换。
二.获取类的成员方法
package com.njau.d2_reflect;
public class Cat {
public static int a;
public static final String COUNTRY = "中国";
private String name;
private int age;
public Cat(String name, int age) {
System.out.println("有参数构造器执行了!");
this.name = name;
this.age = age;
}
public Cat() {
System.out.println("无参构造器执行了!");
}
public String getName() {
return name;
}
private void run() {
System.out.println("🐱跑的贼快~~");
}
public void eat() {
System.out.println("🐱爱吃猫粮~~");
}
// 方法的重载
private String eat(String name) {
return "🐱爱吃" + name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
* Method[] getMethods() 获取类的全部成员方法(只能获取public修饰的) * Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能获取) * Method[] getMethod(String name,Class … parameterTypes) 获取类的某个成员方法(只能获取public修饰的) * Method[] getDeclaredMethod(String name,Class … parameterTypes) 获取类的某个成员方法(只要存在就能获取)
首先我们要获取类的成员方法,就要先获取类对象。因此反射的第一步永远都是获取类对象。
package com.njau.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
/**
* 目标:获取类的成员方法
* Method[] getMethods() 获取类的全部成员方法(只能获取public修饰的)
* Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能获取)
* Method[] getMethod(String name,Class<?> ... parameterTypes) 获取类的某个成员方法(只能获取public修饰的)
* Method[] getDeclaredMethod(String name,Class<?> ... parameterTypes) 获取类的某个成员方法(只要存在就能获取)
* 成员方法的作用:依然是执行
* public Object invoke(Object obj, Object ... args) 出发某个对象的该方法执行 Object obj代表类的某个实例对象
* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
*/
public class Test4Method {
@Test
public void testGetDeclaredMethods() throws Exception {
// 1、反射第一步:首先获取Class对象
Class c = Cat.class;
// 2、获取类的全部成员方法
Method[] methods = c.getDeclaredMethods();
// 3、对所有成员方法进行遍历
for (Method method : methods) {
System.out.println(method.getName() + "--->" + method.getParameterCount()
+ "--->" + method.getReturnType());
}
// 4、获得某个成员方法
Method run = c.getDeclaredMethod("run");
System.out.println(run.getName() + "--->" + run.getParameterCount()
+ "--->" + run.getReturnType()); // run--->0--->void
Method eat = c.getDeclaredMethod("eat",String.class);
System.out.println(eat.getName() + "--->" + eat.getParameterCount()
+ "--->" + eat.getReturnType()); // eat--->1--->class java.lang.String
}
}
我们使用getDeclaredMethods()方法来获取类中的全部实例对象。然后用Method类型的数据对其进行封装。封装后我们进行遍历,在遍历时我们可以使用:
1.getName()方法获得该方法的方法名
2.getParameterCount()方法获得该方法的参数个数
3.getReturnType()方法获得该方法的返回值类型
我们使用getDeclaredMethod(String name,Class … parameterTypes)方法来获取类中的指定的实例对象。其中要获得指定的方法吗,就要在name字段指定方法名,在Class … parameterTypes字段指定参数类型。
通过反射获得成员方法的作用依然是执行
* public Object invoke(Object obj, Object … args) 出发某个对象的该方法执行 Object obj代表类的某个实例对象 * public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
我们可以在获得成员方法对象后通过invoke方法执行该成员方法。但是在使用invoke方法之前,我们首先要new一个该方法所在类的实例化对象,因为这个成员方法是该类的成员方法,是通过该类的实例化对象进行调用的。因此要先将该类实例化对象出来,再将该对象传入invoke方法里才能够进行调用。
package com.njau.d2_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
/**
* 目标:获取类的成员方法
* Method[] getMethods() 获取类的全部成员方法(只能获取public修饰的)
* Method[] getDeclaredMethods() 获取类的全部成员方法(只要存在就能获取)
* Method[] getMethod(String name,Class<?> ... parameterTypes) 获取类的某个成员方法(只能获取public修饰的)
* Method[] getDeclaredMethod(String name,Class<?> ... parameterTypes) 获取类的某个成员方法(只要存在就能获取)
* 成员方法的作用:依然是执行
* public Object invoke(Object obj, Object ... args) 出发某个对象的该方法执行 Object obj代表类的某个实例对象
* public void setAccessible(boolean flag) 设置为true,表示禁止检查访问控制(暴力反射)
*/
public class Test4Method {
@Test
public void testGetDeclaredMethods() throws Exception {
// 1、反射第一步:首先获取Class对象
Class c = Cat.class;
// 2、获取类的全部成员方法
Method[] methods = c.getDeclaredMethods();
// 3、对所有成员方法进行遍历
for (Method method : methods) {
System.out.println(method.getName() + "--->" + method.getParameterCount()
+ "--->" + method.getReturnType());
}
// 4、获得某个成员方法
Method run = c.getDeclaredMethod("run");
System.out.println(run.getName() + "--->" + run.getParameterCount()
+ "--->" + run.getReturnType()); // run--->0--->void
Method eat = c.getDeclaredMethod("eat",String.class);
System.out.println(eat.getName() + "--->" + eat.getParameterCount()
+ "--->" + eat.getReturnType()); // eat--->1--->class java.lang.String
Cat cat = new Cat(); // 创建一个猫对象
run.setAccessible(true); // 表示禁止检查访问控制(暴力反射)
Object object = run.invoke(cat); // 🐱跑的贼快~~
System.out.println(object); // null 没有返回值,就是null
eat.setAccessible(true);
String food = (String) eat.invoke(cat, "鱼儿");
System.out.println(food);
}
}