介绍
Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查。被private封装的资源只能类内部访问,外部是不行的,但反射能直接操作类私有属性。
反射可以在运行时获取一个类的所有信息,(包括成员变量,成员方法,构造器等),并且可以操纵类的字段、方法、构造器等部分。通俗点总结就是不通过创建对象的方式来访问类的属性,并且能够访问private修饰的属
性。
Class类
Java反射的基础是Class类,它是Java反射的入口。Class类提供了获取类的构造函数、方法、字段、注解等信息的方法。
创建对象
Class.forName(“类的全路径”)( 例如:com.hqyj.core.io.serializestream.Student)
类名.class
类的对象.getClass();( 不建议)
测试代码
public static void test01() throws Exception{
//反射,拿到了类的所有信息,可以走后门
//方式一
//创建类的Class对象
System.out.println("===================================");
System.out.println("方式一");
Class c1=Class.forName("com.HQSecond.day9.Student");
//创建Student对象
Student stu1=(Student) c1.newInstance();
System.out.println(stu1);
System.out.println("===================================");
System.out.println("方式二");
Class c2=Student.class;
Student stu2=(Student) c2.newInstance();
System.out.println(stu2);
System.out.println("===================================");
System.out.println("方式三");
Class c3=new Student().getClass();
Student stu3=(Student) c3.newInstance();
System.out.println(stu3);
}
运行结果
属性
Fields[] fields; (存储的是类的成员变量)
getField() 根据名字获取public修饰的变量
getFields() 返回类中public修饰的成员变量
getDeclaredField() 根据名字获取所有变量
getDeclaredFields() 返回类中所有的成员变量
测试代码
public static void test02() throws Exception{
//创建类的Class对象
Class c1=Class.forName("com.HQSecond.day9.Student");
//创建Student对象
Student stu1=(Student) c1.newInstance();
//根据指定名字获取成员变量Field对象中包含了变量的属性(权限修饰符、类型、名字)
System.out.println("=========================================");
System.out.println("根据指定名字获取成员变量:");
Field f= c1.getField("name");
System.out.println("变量的名称:"+f.getName());
System.out.println("变量的类型:"+f.getType().getName());
System.out.println("=========================================");
System.out.println("获取类中所有public成员变量:");
Field[] fields = c1.getFields();
for (Field f1:fields) {
System.out.print(f1.getName()+" ");
System.out.println(f1.getType());
}
System.out.println("=========================================");
System.out.println("获取类中所有成员变量:");
Field[] fields1 = c1.getDeclaredFields();
for (Field f1 : fields1) {
System.out.print(f1.getName()+" ");
System.out.println(f1.getType());
}
System.out.println("=========================================");
System.out.println("给指定的变量赋值:");
System.out.println("public变量:");
Field f2 = c1.getDeclaredField("name");
f2.set(stu1,"Bob");//赋值
System.out.println(stu1.getName());//获取
System.out.println("private变量:");
Field f4 = c1.getDeclaredField("sex");
给private修饰的变量赋值,需要设置暴力反射
f4.setAccessible(true);
f4.set(stu1,"male");//赋值
System.out.println(stu1.getSex());//获取
}
运行结果
构造方法
Constructors[] constructors;(存储的是类的构造方法)
getConstructors();获取类中的所有构造方法
getConstructor();获取无参的构造方法
getConstructor(String.class, int.class, char.class);
获取有参的构造方法,表明第一个参数为String类型,第二个为int类,第三个为char
测试代码
public static void test03() throws Exception{
//方式二 创建class对象
Class c1=Student.class;
System.out.println("=========================================");
System.out.println("获取类中的构造方法:");
Constructor[] cons = c1.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("=========================================");
System.out.println("获取无参的构造方法,创对象:");
//获取无参的构造方法 创对象---->调用构造方法 调用构造方法----->创对象
Constructor con1 = c1.getConstructor();
//通过无参构造方法创建Student对象
Student Stu1=(Student)con1.newInstance();
System.out.println(Stu1);
System.out.println("=========================================");
System.out.println("获取有参的构造方法,创对象:");
//获取有参的构造方法
Constructor con2 = c1.getConstructor(String.class, Integer.class);
// 通过有参构造创建对象
Student stu2=(Student)con2.newInstance("大黄",5);
System.out.println(stu2);
System.out.println("=========================================");
System.out.println("获取有参的构造方法,创对象:");
Constructor con3 = c1.getConstructor(String.class, Integer.class,String.class,String.class);
Student stu3=(Student)con3.newInstance("Alice",18,"female","ball");
System.out.println(stu3.toString());
}
运行结果
成员方法
Methods[] methods;(存储的是类的成员方法)
getMethod("eat", String.class);(参数1:方法的名称, 参数2:方法形参类型)
测试代码
public static void test04()throws Exception{
Class c= Class.forName("com.HQSecond.day9.Student");
Student Stu1=(Student)c.newInstance();
Stu1.name="Jack";
//通过反射调用类中的成员方法 参数1:方法的名称, 参数2:方法形参类型
Method m = c.getMethod("getName");
//执行方法,传递参数
System.out.println(m.invoke(Stu1));
//测试2 用set方法设置,get方法获取
Method m1 = c.getMethod("setHobby", String.class);
m1.invoke(Stu1,"ball");
Method m2 = c.getMethod("getHobby");
System.out.println(m2.invoke(Stu1));
}
运行结果
用到的全部代码
student类
import java.io.Serializable;
public class Student implements Serializable {
//成员变量
//声明一个固定的序列号,此时无论去改变类,序列号都不会变。
public static final long serialVersionUID=12345;
public String name;
public Integer age;
private String sex;
protected String hobby;
//构造方法
public Student(){}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public Student(String name, Integer age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public Student(String name, Integer age, String sex, String hobby) {
this.name = name;
this.age = age;
this.sex = sex;
this.hobby = hobby;
}
//成员方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
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 + '\'' +
", hobby='" + hobby + '\'' +
'}';
}
}
运行的全部代码
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception {
test01();
test02();
test03();
test04();
}
public static void test01() throws Exception{
//反射,拿到了类的所有信息,可以走后门
//方式一
//创建类的Class对象
System.out.println("===================================");
System.out.println("方式一");
Class c1=Class.forName("com.HQSecond.day9.Student");
//创建Student对象
Student stu1=(Student) c1.newInstance();
System.out.println(stu1);
System.out.println("===================================");
System.out.println("方式二");
Class c2=Student.class;
Student stu2=(Student) c2.newInstance();
System.out.println(stu2);
System.out.println("===================================");
System.out.println("方式三");
Class c3=new Student().getClass();
Student stu3=(Student) c3.newInstance();
System.out.println(stu3);
}
public static void test02() throws Exception{
//创建类的Class对象
Class c1=Class.forName("com.HQSecond.day9.Student");
//创建Student对象
Student stu1=(Student) c1.newInstance();
//根据指定名字获取成员变量Field对象中包含了变量的属性(权限修饰符、类型、名字)
System.out.println("=========================================");
System.out.println("根据指定名字获取成员变量:");
Field f= c1.getField("name");
System.out.println("变量的名称:"+f.getName());
System.out.println("变量的类型:"+f.getType().getName());
System.out.println("=========================================");
System.out.println("获取类中所有public成员变量:");
Field[] fields = c1.getFields();
for (Field f1:fields) {
System.out.print(f1.getName()+" ");
System.out.println(f1.getType());
}
System.out.println("=========================================");
System.out.println("获取类中所有成员变量:");
Field[] fields1 = c1.getDeclaredFields();
for (Field f1 : fields1) {
System.out.print(f1.getName()+" ");
System.out.println(f1.getType());
}
System.out.println("=========================================");
System.out.println("给指定的变量赋值:");
System.out.println("public变量:");
Field f2 = c1.getDeclaredField("name");
f2.set(stu1,"Bob");//赋值
System.out.println(stu1.getName());//获取
System.out.println("private变量:");
Field f4 = c1.getDeclaredField("sex");
给private修饰的变量赋值,需要设置暴力反射
f4.setAccessible(true);
f4.set(stu1,"male");//赋值
System.out.println(stu1.getSex());//获取
}
public static void test03() throws Exception{
//方式二 创建class对象
Class c1=Student.class;
System.out.println("=========================================");
System.out.println("获取类中的构造方法:");
Constructor[] cons = c1.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("=========================================");
System.out.println("获取无参的构造方法,创对象:");
//获取无参的构造方法 创对象---->调用构造方法 调用构造方法----->创对象
Constructor con1 = c1.getConstructor();
//通过无参构造方法创建Student对象
Student Stu1=(Student)con1.newInstance();
System.out.println(Stu1);
System.out.println("=========================================");
System.out.println("获取有参的构造方法,创对象:");
//获取有参的构造方法
Constructor con2 = c1.getConstructor(String.class, Integer.class);
// 通过有参构造创建对象
Student stu2=(Student)con2.newInstance("大黄",5);
System.out.println(stu2);
System.out.println("=========================================");
System.out.println("获取有参的构造方法,创对象:");
Constructor con3 = c1.getConstructor(String.class, Integer.class,String.class,String.class);
Student stu3=(Student)con3.newInstance("Alice",18,"female","ball");
System.out.println(stu3.toString());
}
public static void test04()throws Exception{
System.out.println("===============================");
System.out.println("通过反射调用类中的成员方法:");
Class c= Class.forName("com.HQSecond.day9.Student");
Student Stu1=(Student)c.newInstance();
Stu1.name="Jack";
//通过反射调用类中的成员方法 参数1:方法的名称, 参数2:方法形参类型
Method m = c.getMethod("getName");
//执行方法,传递参数
System.out.println(m.invoke(Stu1));
//测试2 用set方法设置,get方法获取
Method m1 = c.getMethod("setHobby", String.class);
m1.invoke(Stu1,"ball");
Method m2 = c.getMethod("getHobby");
System.out.println(m2.invoke(Stu1));
}
}