本节知识总结
目录
反射Java语言的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
用反射调用私(公)有的构造器用:getDeclaredConstructor
* ✍getConstructor与getDeclaredConstructor的区别:
前言
在jdk的配置环境中 从俩个地方体现出:一个是XML解析 另一个是实体类 而实体类则需要运用反射
jdk里面jre转译:是将.java文件转化为.class的文件
而今天我们说的是反射 它是将.class文件转为.java文件
一、反射是什么?
反射Java语言的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
接下来要学习的是框架,现在所学的都是把框架拆开学
首先框架:设计模式(23种)+反射
二、类类(类对象的三种获取方式)
1.Class.forName(完整类名)
2.类名.class
3.对象.getClass()
首先我们会用到一个Student实体类,里面有无参有参有返回无返回私有公开的构造方法,进行下面所有反射的使用
package com.xiehuiyi.class1;
public class Student {
private String sid;private String sname;
public Integer age;
static{
System.out.println("加载进jvm中!");
}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());
}
}
建立一个Demo1类:
package com.xiehuiyi.class1;
/**
* 获取类类的类对象的三种方式(识记)
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 1.class.forName(完整类名)
Class<Student> stuClz1 = (Class<Student>) Class.forName("com.xiehuiyi.class1.Student");
//2.类.class
Class stuClz2=Student.class;
//3.类类的类对象的类实例.getClass();
Class stuClz3=new Student().getClass();
}
}
三、反射实例化
用反射调用无参构造器用:newlnstance
代码如下:
package com.xiehuiyi.class1;
public class Demo2 {
public static void main(String[] args) throws Exception {
//拿到Studen文件
Class<Student> stuClz1 = (Class<Student>) Class.forName("com.xiehuiyi.class1.Student");
//调用无参方法
//实例化
Student stu1=(Student) stuClz1.newInstance();
stu1.hello();//调用student类中的方法
}
}
输出结果如下就实例化成功:
如果没有无参构造方法(会报以下错误):
原因:因为在很多框架底层都是通过无参构造器对这个类进行实例化的
用反射调用有参构造器用:getConstructor
代码如下:
package com.xiehuiyi.class1;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) throws Exception {
//拿到Studen文件
Class<Student> stuClz1 = (Class<Student>)
//调用有参构造器
Constructor<Student> c = stuClz1.getConstructor(String.class);//括号里填的是有参的参数的类型,如果有多个可以一样往后面加
Student s1 = c.newInstance("s001");
}
}
输出结果如下就实例化成功:
如果调用私有的:
所以用下面的方法👍
用反射调用私(公)有的构造器用:getDeclaredConstructor
代码如下:
package com.xiehuiyi.class1;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) throws Exception {
//拿到Studen文件
Class<Student> stuClz1 = (Class<Student>)
//调用私有有参构造器
Constructor<Student> c2 = stuClz1.getDeclaredConstructor(Integer.class);//括号里填的是有参的参数的类型,如果有多个可以一样往后面加
c2.setAccessible(true);//给私有化授权
Student s2=c2.newInstance(26);
}
}
输出结果如下就实例化成功:
如果没有授权setAccessible(true)(报错):
* ✍getConstructor与getDeclaredConstructor的区别:
getDeclaredConstructor可以获取到私有的有参无参构造器以及共有的
而getConstructor只能获取公有有参构造器
四、反射动态方法调用
1.getMethod(方法名 参数数据类型(无参数传null))获取公共方法
2.getDeclaredMethod(方法名 参数数据类型(无参数传null))获取私有公有方法
代码如下:
package com.xiehuiyi.class1;
import java.lang.reflect.Method;
/**
* 反射动态方法调用
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
//拿到Studen文件
System.out.println("====调用无参======");
Class<Student> stuClz1 = (Class<Student>) Class.forName("com.xiehuiyi.class1.Student");
Student s=(Student) stuClz1.newInstance();
Method m1 = stuClz1.getDeclaredMethod("hello");
Method m = stuClz1.getMethod("hello");
//m1.invoke(obj, args);
//参数1:类实例,在这里指的是Student类实例
//参数2:当前被调用的方法,传递的参数值
//invoke的返回值,就是被放射调用的方法的返回值,如果被调用的方法是void,那么返回null
System.out.println(m1.invoke(s));
System.out.println(m.invoke(s));
System.out.println("=======调用有参=======");
Method m2 = stuClz1.getDeclaredMethod("hello",String.class);
System.out.println(m2.invoke(s,"xhy"));
System.out.println("======有参私有=======");
Method m3 = stuClz1.getDeclaredMethod("add",Integer.class,Integer.class);
m3.setAccessible(true);
System.out.println(m3.invoke(s,50, 2));
}
}
输出结果:
如果用 .getMethod调用私有,报错:
*ps 得出getMethod只能调用公开的
五、反射读写属性
getDeclaredField
getDeclaredFields
package com.xiehuiyi.class1;
import java.io.File;
import java.lang.reflect.Field;/**
* 反射读写属性
* @author zjjt
*
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
//获得类对象
Class<Student> stuClz1 = (Class<Student>) Class.forName("com.xiehuiyi.class1.Student");
//实例化一个学生
Student s=(Student) stuClz1.newInstance();
Field f = stuClz1.getDeclaredField("sname");
f.setAccessible(true);
//反射写属性
f.set(s, "xhy");
System.out.println(s.getSname());
//反射读属性
System.out.println(f.get(s));
//比较oop读取属性值的方式
Student st=new Student("s002","ls");
st.age=18;
System.out.println(st.getSid());
System.out.println(st.getSname());
System.out.println(st.age);
//与反射读取属性
Field[] fields = stuClz1.getDeclaredFields();
for (Field ff : fields) {
ff.setAccessible(true);
System.out.println(ff.get(st));
}
}
}
ps:反射对比oop读取属性值的方式更方便
输出结果:
总结
在本节中类对象的三种获取方式需要我们识记,其他我们需要更深入的了解认识它用它,课后可以再去了解一下获取访问修饰符:getModifiers()
今天的内容就到这了!我们下期再见!希望以上内容能对你有帮助,当然有什么错误之处还望大佬指正!谢谢😘