反射总是记不住,那还是得多练
获得Class(字节码文件)的有三种方法:
例如有一个Student类:
class Student {
private int age;
private String name;
private char gender;
private double height;
private String hobby;
public Student(String name, int age, char gender, double height, String hobby) {
this.age = age;
this.name = name;
this.gender = gender;
this.height = height;
this.hobby = hobby;
}
}
三种方法:
// 1.直接通过 类名.class就可以获得字节码文件
Class clazz1 = Student.class;
// 2.通过Class.forName("包名.类名") 获得字节码文件
Class clazz2 = Class.forName("Student"); // 在一个包里,会抛出一个 ClassNotFoundException 异常
// 3.先new 一个对象再获得字节码文件
Student student = new Student("小A", 23, '女', 167.5, "睡觉");
Class s3 = student.getClass();
获得构造方法:
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
Constructor getConstructor(Class<?>… parameterTypes) | 获取指定构造(只能public修饰) |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定构造(包含private修饰) |
创建对象通过newInstance()
方法:
// 主函数里面的代码
Student student = new Student("小A", 23, '女', 167.5, "睡觉");
Class s = student.getClass();
Constructor[] constructors = s.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("构造方法" + constructor);
Parameter[] parameters = constructor.getParameters();
for (Parameter parameter : parameters) {
System.out.println("形参" + parameter);
}
}
Constructor constructor = s.getDeclaredConstructor(String.class, int.class, char.class, double.class, String.class);
Student o = (Student) constructor.newInstance("小B", 23, '女', 167.5, "睡觉");
System.out.println(o.getName());
class Student {
private int age;
private String name;
private char gender;
private double height;
private String hobby;
public String getName() {
return name;
}
public Student(String name, int age, char gender, double height, String hobby) {
this.age = age;
this.name = name;
this.gender = gender;
this.height = height;
this.hobby = hobby;
}
private Student(String name) {
System.out.println("这是私有构造方法");
}
}
成员变量:
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
方法 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
直接练习一下就OK了:
public class Main {
public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Student student = new Student("小A", 23, '女', 167.5, "睡觉");
Teacher teacher = new Teacher("波妞", BigDecimal.valueOf(100000));
Class s = student.getClass();
Class t = teacher.getClass();
Field[] stu = s.getDeclaredFields();
for (Field field : stu) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(student);
System.out.println(name + "=" + value);
}
System.out.println("------------------");
Field[] tea = t.getDeclaredFields();
for (Field field : tea) {
field.setAccessible(true);
String name = field.getName();
Object value = field.get(teacher);
System.out.println(name + "=" + value);
}
}
}
class Student {
private int age;
private String name;
private char gender;
private double height;
private String hobby;
public String getName() {
return name;
}
public Student(String name, int age, char gender, double height, String hobby) {
this.age = age;
this.name = name;
this.gender = gender;
this.height = height;
this.hobby = hobby;
}
private Student(String name) {
System.out.println("这是私有构造方法");
}
}
class Teacher{
private String name;
private BigDecimal salary;
public Teacher(String name, BigDecimal salary) {
this.name = name;
this.salary = salary;
}
}
黑马:
public class ReflectDemo5 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Student s = new Student("zhangsan",23,"广州");
Student ss = new Student("lisi",24,"北京");
//需求:
//利用反射获取成员变量并获取值和修改值
//1.获取class对象
Class clazz = Class.forName("com.itheima.reflectdemo.Student");
//2.获取name成员变量
//field就表示name这个属性的对象
Field field = clazz.getDeclaredField("name");
//临时修饰他的访问权限
field.setAccessible(true);
//3.设置(修改)name的值
//参数一:表示要修改哪个对象的name?
//参数二:表示要修改为多少?
field.set(s,"wangwu");
//3.获取name的值
//表示我要获取这个对象的name的值
String result = (String)field.get(s);
//4.打印结果
System.out.println(result);
System.out.println(s);
System.out.println(ss);
}
}
class Student {
private String name;
private int age;
public String gender;
public String address;
public Student() {
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
}
成员方法:
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
import java.lang.reflect.*;
public class Main {
public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Student student = new Student("小A", 23, '女', 167.5, "睡觉");
Teacher teacher = new Teacher("波妞", BigDecimal.valueOf(100000));
Class s = student.getClass();
Class t = teacher.getClass();
//获取一个指定的方法
//参数一:方法名
//参数二:参数列表,如果没有可以不写
Method method = s.getDeclaredMethod("getName");
//运行
//参数一:表示方法的调用对象
//参数二:方法在运行时需要的实际参数
System.out.println(method.invoke(student));
}
}
class Student {
private int age;
private String name;
private char gender;
private double height;
private String hobby;
public String getName() {
return name;
}
public Student(String name, int age, char gender, double height, String hobby) {
this.age = age;
this.name = name;
this.gender = gender;
this.height = height;
this.hobby = hobby;
}
private Student(String name) {
System.out.println("这是私有构造方法");
}
}
class Teacher{
private String name;
private BigDecimal salary;
public Teacher(String name, BigDecimal salary) {
this.name = name;
this.salary = salary;
}
}