反射
反射步骤
获取Class对象的三种方法
public class Test1Class {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种
Class c1 = Student.class;
System.out.println(c1.getName()); // 全类名 advanced.reflex.Student
System.out.println(c1.getSimpleName()); // 类名 Student
// 第二种
Class<?> c2 = Class.forName("advanced.reflex.Student");
// 第三种
Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c3 == c2);
}
}
/**
* 目标:获取类的构造器,并对其进行操作
*/
public class Test2Constructor {
@Test
public void testGetConstructors() {
// 1.必须先得到类的class对象
Class<Cat> catClass = Cat.class;
// 2.获取类的全部构造器
// Constructor[] constructors = catClass.getConstructors();
Constructor[] constructors = catClass.getDeclaredConstructors();
// 3.遍历数组的中构造器对象
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
}
}
@Test
public void testGetConstructor() throws NoSuchMethodException {
// 1.必须先得到类的class对象
Class<Cat> catClass = Cat.class;
// 2.获取类的某个构造器
// Constructor constructor = catClass.getConstructor();
Constructor<Cat> constructor = catClass.getDeclaredConstructor();
System.out.println(constructor.getName() + "--->" + constructor.getParameterCount());
// 3.获取有参的构造器
Constructor<Cat> constructor2 = catClass.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName() + "--->" + constructor2.getParameterCount());
}
}
获取类构造器的作用
获取类构造器的作用:依然是初始化对象返回
@Test
public voidtestGetConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1.必须先得到类的class对象
Class<Cat> catClass = Cat.class;
// 2.获取类的某个构造器
Constructor constructor = catClass.getDeclaredConstructor();
constructor.setAccessible(true);
Cat cat = (Cat) constructor.newInstance();
System.out.println(cat);
// 3.获取有参的构造器
Constructor constructor2 = catClass.getDeclaredConstructor(String.class, int.class);
constructor2.setAccessible(true);
Cat cat2 = (Cat) constructor2.newInstance("叮当猫", 12);
System.out.println(cat2);
}
public class Cat {
private static int a;
public static final String COUNTRY = "中国";
private String name;
private int age;
}
@Test
public void getGetFields() throws NoSuchFieldException {
// 1.获取Class对象
Class catClass = Cat.class;
// 2.获取类的全部成员变量
Field[] fields = catClass.getDeclaredFields();
// 3.遍历成员变量数组
for (Field field : fields) {
System.out.println(field.getName() + "---" + field.getType());
}
// 4.定位某个成员变量
Field fName = catClass.getDeclaredField("name");
System.out.println(fName.getName() + "-->" + fName.getType());
Field fAge = catClass.getDeclaredField("age");
System.out.println(fAge.getName() + "-->" + fAge.getType());
}
@Test
public void getGetFields() throws Exception {
// 1.获取Class对象
Class catClass = Cat.class;
// 2.定位某个成员变量
Field fName = catClass.getDeclaredField("name");
System.out.println(fName.getName() + "-->" + fName.getType());
// 赋值
Cat cat = new Cat();
fName.setAccessible(true);
fName.set(cat, "加菲猫");
System.out.println(cat);
// 取值
String name = (String) fName.get(cat);
System.out.println("name = " + name);
}
private void run() {
System.out.println("猫跑的很快");
}
private void eat() {
System.out.println("猫爱吃猫粮");
}
private String eat(String name) {
return "猫爱吃" + name;
}
@Test
public void testGetMethods() throws Exception {
// 1.获得Class对象
Class catClass = Cat.class;
// 2.获取类的全部成员方法
Method[] methods = catClass.getDeclaredMethods();
// 3.遍历
for (Method method : methods) {
System.out.println(method.getName() + "---" +
method.getParameterCount() + "---" +
method.getReturnType());
}
// 4.获取某个方法对象
Method run = catClass.getDeclaredMethod("run");
System.out.println(run.getName() + "---" +
run.getParameterCount() + "---" +
run.getReturnType());
Method eat = catClass.getDeclaredMethod("eat", String.class);
System.out.println(eat.getName() + "---" +
eat.getParameterCount() + "---" +
eat.getReturnType());
}
@Test
public void testGetMethods() throws Exception {
// 1.获得Class对象
Class catClass = Cat.class;
// 2.获取某个方法对象
Method run = catClass.getDeclaredMethod("run");
Method eat = catClass.getDeclaredMethod("eat", String.class);
// 执行方法
Cat cat = new Cat();
run.setAccessible(true);
Object rs = run.invoke(cat);// 调用无参数的run方法,用cat对象触发调用
System.out.println("rs = " + rs);
eat.setAccessible(true);
rs = eat.invoke(cat, "火腿肠");
System.out.println("rs = " + rs);
}
反射的作用
案例:使用反射做一个简易版的框架
需求:
实现步骤
public class Student {
private String name;
private char sex;
private int age;
private double height;
private String hobby;
}
public class Teacher {
private String name;
private double salary;
}
/**
* 使用反射技术,设计一个保存对象的简易版框架
*/
public class Test5Frame {
@Test
public void save() throws Exception{
Student s1 = new Student("吴彦祖", '男', 45, 185.3, "乒乓球");
Teacher t1 = new Teacher("黄子韬", 999.9);
// 需求:任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}
/**
* 保存任意对象的字段和数据到文件中去
*/
public class ObjectFrame {
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("F:\\Code\\JetBrains-Work\\Java\\2022study\\src\\advanced\\reflex\\data.txt", true));
// obj是任意对象,到底有多少个字段要保存
Class c = obj.getClass();
String cName = c.getSimpleName();
ps.println("-------------------" + cName + "-------------------");
// 2.从该类中提取全部成员变量
Field[] fields = c.getDeclaredFields();
// 3.变量每个成员变量
for (Field field : fields) {
// 4.拿到成员变量的名字
String name = field.getName();
// 5.拿到这个成员变量在该对象的值
field.setAccessible(true);
String value = field.get(obj).toString();
ps.println(name + "=" + value);
}
ps.close();
}
}