导语:
Java反射机制就是一种提高代码灵活性,避免把程序写死到代码里的一种手段,我们都知道,Java代码跑是在jvm虚拟机当中运行的,而jvm中又有堆,栈,还有我们的方法区和程序计数器,而我们的Java之所以可以跨平台运行就是因为有jvm虚拟机,可以把jvm理解成一个进程,程序。
什么是反射?
反射就是Java语言中的一种机制,它可以动态的去调用我们的实例化对象,读写属性和调用方法。
反射机制的作用
通过Java的反射机制我们可以获取我们Class文件加载后的Class对象的所以信息,就比如public修饰的方法属性还有对象,还有我们的private修饰的方法属性和对象,也就是说我们的类变成了透明的,所有的细节都可以获取到。
通过反射调用我们的类
下面我们通过一个Student 来更好的讲解我们的反射机制
Class.forName(完整类名)
// 1.通过Class.forName()填写完整类名来获取Class对象
Class<Student> clazz01 = (Class<Student>) Class.forName("com.zking.reflect.Student");
类.calss
// 2.通过类.class的方式
Class clazz02 = Student.class;
对象.getcClass();
// 3.通过对象.class来获取class
Student stu01 = new Student();
Class clazz03 = stu01.getClass();
我们来看一下运行输出clazz01,clazz02,clazz03的结果
通过反射实例化我们的对象
getConsturcotr
// 通过反射来实例化对象
// 调用无参构造方法创建了一个学生对象
Constructor<Student> con1 = clazz01.getConstructor();
Student stu1 = con1.newInstance();
stu1.setSname("李凝");
System.out.println(stu1);
// 结果:调用无参构造方法创建了一个学生对象 Student [sid=null, sname=李凝, age=null]
// 调用带一个参数的构造方法创建了一个学生对象
Constructor<Student> con2 = clazz01.getConstructor(String.class);
Student stu2 = con2.newInstance("02");
stu2.setSname("李凝2");
System.out.println(stu2);
// 结果:调用带一个参数的构造方法创建了一个学生对象 Student [sid=02, sname=李凝2, age=null]
// 调用带二个参数的构造方法创建了一个学生对象
Constructor<Student> con3 = clazz01.getConstructor(String.class, String.class);
Student stu3 = con3.newInstance("03", "李凝3");
System.out.println(stu3);
// 结果: Student [sid=03, sname=李凝3, age=null]
getDeclaedConstrurcotr
// 获取private修饰的class
Constructor<Student> con4 = clazz01.getDeclaredConstructor(Integer.class);
con4.setAccessible(true);// 暴力反射,true可以访问,false不可访问
Student stu4 = con4.newInstance(17);
stu4.setSname("李凝4");
System.out.println(stu4);
// 结果: 调用Student类私有的构造方法创建一个学生对象 Student [sid=null, sname=李凝4, age=17]
反射动态方法调用
getMethod
// 通过反射获取方法//无参方法
Method f1 = clazz01.getMethod("hello");
stu1.setSname("李凝");
f1.invoke(stu1);
//结果: 你好!我是李凝
// 有参方法
Method f2 = clazz01.getMethod("hello", String.class);
stu1.setSname("鸣孀");
f2.invoke(stu1, "李凝");
// 结果: 李凝你好!我是鸣孀
getDeclaedMethod
//调用private修饰的方法
Method f3 = clazz01.getDeclaredMethod("add", Integer.class, Integer.class);
f3.setAccessible(true);
stu2.setSname("大李凝");
int d2 = (int) f3.invoke(stu2, 12, 78);
System.out.println(d2);
// 结果: 90
反射调用对象属性
getField
// 获取对象的属性
Field s1 = clazz03.getField("age");
s1.set(stu3, 19);
System.out.println(stu3);
System.out.println(s1.get(stu3));
// 结果: Student [sid=03, sname=李凝3, age=19] 19
getDecaledField or getDecaledFields
获取一个或者多个private修饰的属性
// 获取对象private修饰的属性
Field s2 = clazz03.getDeclaredField("sname");
s2.setAccessible(true);
s2.set(stu4, "华安");
System.out.println(stu4);
System.out.println(s2.get(stu4));
//Student [sid=null, sname=华安, age=17]
//华安
Student实例:
package com.zking.reflect;
public class Student {
private String sid;
private String sname;
public Integer age;
static {
System.out.println("加载进jvm中!");
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
}
}
总结:
Java的反射机制在于灵活性, 不但是程序的灵活性,更体现在代码的灵活性,如果我们需要通过反射来获取我们想要的属性对象或者是实例化对象,用public修饰的我们可以直接获取掉用,而如果是通过private修饰的话,我们就要先把可访问的开关给打开,xxx.setsetAccessible(true);true是可以访问,禁止访问就改成false就好啦!希望我的总计对你有用!