1. 反射的第一步都是先得到加载后的类,然后才可以去那类的其他成分。
2. 获取Class类的对象的三种方式
在这里,获取Class对象的构造器作用依然是初始化一个对象返回,接下来是代码展示,并且相关代码进行了详细注解,包括获取Class对象的三种方式、获取Class对象的构造函数的相关方法以及使用Class对象的构造函数。
首先是用做测试的Cat类,这里使用Cat类的Class对象做测试。
package com.itheima_reflect;
public class Cat {
private String name;
private int age;
public Cat() {
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
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 +
'}';
}
}
这是主函数,包括了详细的代码
package com.itheima_reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestConstructor {
public static void main(String[] args) throws Exception {
/*
以下代码演示创建Class对象的三种方法
*/
// 获取的Class的方法一
Class catClass = Cat.class;
// 获取的Class的方法二
Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
// 获取的Class的方法三
Cat cat = new Cat();
Class extends Cat> getClass = cat.getClass();
/*
* 以下代码是使用反射技术获取构造器对象并使用
*/
// 返回所有构造器对象的数组(只能拿public的)
// 在这里需要注意,如果Class对象的其中一个构造函数是用private关键字修饰,那么这个构造函数是遍历不到的
Constructor>[] constructors = catClass.getConstructors();
for (Constructor> constructor : constructors) {
System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
}
// 返回所有构造器对象的数组
// 在这里需要注意,即使Class对象的其中一个构造函数是用private关键字修饰,也能遍历到
Constructor>[] declaredConstructors = catClass.getDeclaredConstructors();
for (Constructor> constructor : declaredConstructors) {
// 输出Class对象中构造函数的名称和参数数量
System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
}
// 返回单个构造器对象(只能拿public的)
Constructor constructor = catClass.getConstructor();//如果不填写参数,调用Class对象的无参构造函数
System.out.println(constructor.getName() + "---->" + constructor.getParameterCount());
/**
* 以下代码展示的是使用Class对象的构造函数创建对象
*/
// 通过newInstance()方法创建一个Cat对象
Cat newCat = catClass.newInstance();
// 暴力破解,如果当前catClass这个构造函数在Cat类中是私有的,那么不执行暴力破解会报错
// public void setAccessible(boolean flag)
// catClass.setAccessible(boolean flag)
}
}
Class类中用于获取成员变量的方法,在代码中详细解释。这是主函数,包括了详细的代码(还是继续使用了Cat类)
package com.itheima_reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class TestConstructor {
public static void main(String[] args) throws Exception {
/*
以下代码演示创建Class对象的三种方法
*/
// 获取的Class的方法一
Class catClass = Cat.class;
// 获取的Class的方法二
Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
// 获取的Class的方法三
Cat cat = new Cat();
Class extends Cat> getClass = cat.getClass();
/**
* 以下代码,展示的是如何获取Cat类的Class对象的变成员变量
*/
// 返回所有成员变量对象的数组(只能拿public的)。在这里,因为Cat类中的成员变量都是使用private修饰的,所以数组为空
Field[] fields = catClass.getFields();
// 返回所有成员变量对象的数组,存在就能拿到
Field[] declaredFields = catClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName());
}
// 返回单个成员变量对象(只能拿public的),在这里,因为Cat类中的成员变量都是使用private修饰的,所以变量为空
Field field = catClass.getField("name");
// 返回单个成员变量对象,存在就能拿到
Field declaredField = catClass.getDeclaredField("name");
}
}
Class类中用于获取成员方法的方法,在代码中详细解释。这是主函数,包括了详细的代码(还是继续使用了Cat类)
package com.itheima_reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestConstructor {
public static void main(String[] args) throws Exception {
/*
以下代码演示创建Class对象的三种方法
*/
// 获取的Class的方法一
Class catClass = Cat.class;
// 获取的Class的方法二
Class name = (Class) Class.forName("MyHomeTest\\src\\com\\itheima_reflect\\Cat.java");
// 获取的Class的方法三
Cat cat = new Cat();
Class extends Cat> getClass = cat.getClass();
/**
* 以下代码,展示的是如何获取Cat类的Class对象的方法
*/
// 返回所有成员方法对象的数组(只能拿public的)
Method[] methods = catClass.getMethods();
for (Method method : methods) {
System.out.println(method.getName() + "----." + method.getParameterCount() + "---->" + method.getParameterTypes());
}
// 返回所有成员方法对象的数组,存在就能拿到
Method[] declaredMethods = catClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method.getName() + "----." + method.getParameterCount() + "---->" + method.getParameterTypes());
}
// 返回单个成员方法对象(只能拿public的)
Method method = catClass.getMethod("getName"); // 参数为要获取的方法名和以及要获取的方法参数
// 返回单个成员方法对象,存在就能拿到
Method getName = catClass.getDeclaredMethod("getName"); // 参数为要获取的方法名和以及要获取的方法参数
/* // 返回所有成员变量对象的数组(只能拿public的)。在这里,因为Cat类中的成员变量都是使用private修饰的,所以数组为空
Field[] fields = catClass.getFields();
// 返回所有成员变量对象的数组,存在就能拿到
Field[] declaredFields = catClass.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field.getName());
}
// 返回单个成员变量对象(只能拿public的),在这里,因为Cat类中的成员变量都是使用private修饰的,所以变量为空
Field field = catClass.getField("name");
// 返回单个成员变量对象,存在就能拿到
Field declaredField = catClass.getDeclaredField("name");*/
}
}
在这里通过一个小案例来展示反射的功能和作用。本案例是实现一个获取运行中对象的字段数据,并且将字段名和字段值打印到指定的文件中去。
首先是创建两个类:Student、Teacher
package com.itheima_reflect;
public class Student {
private String name;
private int age;
private char sex;
private double height;
private String hobby;
public Student() {
}
public Student(String name, int age, char sex, double height, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.height = height;
this.hobby = hobby;
}
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;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
", height=" + height +
", hobby='" + hobby + '\'' +
'}';
}
}
package com.itheima_reflect;
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", salary=" + salary +
'}';
}
}
接下来创建一个反射框架类,通过反射获取运行中对象的Class对象,通过获取的Class对象来获取相应的字段信息。 具体代码如下
package com.itheima_reflect;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
public class ObjectFrame {
// 功能:保存任意对象的字段和相应数据到文件中去
public static void saveObject(Object object) throws Exception {
// 创建一个打印流,用以向文件中打印数据
PrintStream printStream = new PrintStream(new FileOutputStream("D:\\LenovoSoftstore\\Install\\IDEA\\IDEAProject\\MyHomeTest\\src\\user.txt", true));
// 获取object对象的Class对象
Class aClass = object.getClass();
String simpleName = aClass.getSimpleName();
printStream.println("----------" + simpleName + "-------------");
// 通过这个Class对象(aClass)获取全部字段
Field[] fields = aClass.getDeclaredFields();
// 遍历每一个成员变量
for (Field field : fields) {
// 禁止检查访问控制
field.setAccessible(true);
// 通过field获取字段名称
String name = field.getName();
// 通过field获取字段值
String value = field.get(object) + "";
printStream.println(name + " = " + value);
}
printStream.close();
}
}
最后是测试类,对上述功能代码进行测试。代码如下。
package com.itheima_reflect;
public class FrameTest {
public static void main(String[] args) {
Student student = new Student("王大宁", 18, '男', 188, "乒乓球");
Teacher teacher = new Teacher("柳岩", 170);
try {
ObjectFrame.saveObject(student);
ObjectFrame.saveObject(teacher);
} catch (Exception e) {
e.printStackTrace();
}
}
}
以上就是一个通过一个小案例来展示反射的功能和作用。代码经过小猿亲测可跑。