目录
【思维导图】
一、什么是反射?
eg:
狗类 旺财
猫类 肥波
旺财是狗类的实例
肥波是猫类的实例
那么狗类是谁的实例?
狗类是类类的实例
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法。
二、类类
Student实体类代码块展示:
package com.chenchen.reflect;
/**
* 实体类:
* 学生类
* @author ChenChen
*@date 2022年6月16日 下午3:57:24
*/
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());
}
}
获取类类的三种方式:
1、类名.class
代码块展示:
package com.chenchen.reflect;
import com.mysql.jdbc.Driver;
/**
* 如何获得类类
* 获取到student类的类
* 1、类.class
* @author ChenChen
*@date 2022年6月16日 下午3:58:31
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 1.类.class
Class c = Student.class;
}
}
2、Class.forName(完整类名)
代码块展示:
package com.chenchen.reflect;
import com.mysql.jdbc.Driver;
/**
* 如何获得类类
* 获取到student类的类
* 2、类实例.getClass()
* @author ChenChen
*@date 2022年6月16日 下午3:58:31
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 注意:确定本工程有这个实体类
// 2.类实例.getClass
Student stu = new Student();
Class c1 = stu.getClass();
}
}
结果展示:
注意:前文的Student类的构造方法
3、对象.getClass()
代码展示:
package com.chenchen.reflect;
import com.mysql.jdbc.Driver;
/**
* 如何获得类类
* 获取到student类的类
* 3、Class.forName("类的全路径名")
* @author ChenChen
*@date 2022年6月16日 下午3:58:31
*/
public class Demo1 {
public static void main(String[] args) throws Exception {
// 本工程没有这个类也可以编译通过
// 3、Class.forName("类的全路径名");
Class c2 = Class.forName("com.chenchen.reflect.Student");
}
}
结果输出:
注意:本工程没有这个类时,编译也可以通过。
三、反射实例化
①getConstructor ——>constructor只能够获取共有的构造方法
②getDeclaredConstructor ——>获取私有的构造器
③newInstance ——>获取无参的构造方法
提问:
* 1、如何获取无参数 共有的构造方法?
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 1、无参数 共有的构造方法
* 2、有参数 共有的构造方法
* 3、有多个参数 共有的构造方法
* 4、私有的构造方法
* @author ChenChen
*@date 2022年6月16日 下午5:59:31
*/
public class Demo2 {
public static void main(String[] args) throws Exception, Exception {
//实例化一个学生对象
Student stu = new Student();
// -------------------------------------以下均为反射的方法实例化对象----------------
//获取类类
Class<? extends Student> clas = stu.getClass();
// 默认的是调用无参 公有的构造函数
// 1、如何获取无参数的共有的构造方法
Student su1 = clas.newInstance();
}
}
结果输出:
* 2、如何获取有参数 共有的构造方法?
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 2、有参数 共有的构造方法
* @author ChenChen
*@date 2022年6月16日 下午5:59:31
*/
public class Demo2 {
public static void main(String[] args) throws Exception, Exception {
//实例化一个学生对象
Student stu = new Student();
// -------------------------------------一下均为反射的方法实例化对象----------
//获取类类
Class<? extends Student> clas = stu.getClass();
// 2、有参数 共有的构造方法
//拿到构造器对象 三个.代表可以传1个2个..n个参数-->拿到一个参数为String的构造器对象
Constructor<? extends Student> cons = clas.getConstructor(String.class);
Student stu2 = cons.newInstance("s001");
}
}
结果输出:
* 3、如何获取有多个参数 共有的构造方法?
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 3、有多个参数 共有的构造方法
* @author ChenChen
*@date 2022年6月16日 下午5:59:31
*/
public class Demo2 {
public static void main(String[] args) throws Exception, Exception {
//实例化一个学生对象
Student stu = new Student();
// -------------------------------------一下均为反射的方法实例化对象----------
//获取类类
Class<? extends Student> clas = stu.getClass();
// 3、如何获取有多个参数的共有的构造方法
Constructor<? extends Student> cons1 = clas.getConstructor(String.class,String.class);
Student stu3 = cons1.newInstance("w001","吴彦祖");
}
}
结果输出:
* 4、如何获取私有的构造方法?
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 4、私有的构造方法
* @author ChenChen
*@date 2022年6月16日 下午5:59:31
*/
public class Demo2 {
public static void main(String[] args) throws Exception, Exception {
//实例化一个学生对象
Student stu = new Student();
// -------------------------------------一下均为反射的方法实例化对象----------
//获取类类
Class<? extends Student> clas = stu.getClass();
// 4、如何获取私有的构造方法
// 注意:constructor只能够获取共有的构造方法,要获取私有的构造器getDeclaredConstructor
Constructor<? extends Student> cons2 =clas.getDeclaredConstructor(Integer.class);
// 打开访问权限
cons2.setAccessible(true);
Student stu4 = cons2.newInstance(18);
}
}
结果输出:
注意:获取私有的构造方法时,不仅需要私有的构造器【getDeclaredConstructor】,还需要打开权限 【setAccessible(true)】。
四、反射动态方法调用
①getMethod ——>调用公有方法
②getDeclaredMethod ——>调用私有方法
* 1、如何调用无参的 公有方法
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Method;
/**
* 反射动态调用方法
* 1、调用无参的 共有方法
* @author ChenChen
*@date 2022年6月16日 下午6:28:56
*/
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
/**
* 1、先拿到类类
* 2、拿到方法对象
* 3.调用对应的方法
*/
// 1、先拿到类类
Class<Student> clz = Student.class;
// name:方法名 parameterTypes:方法对应的参数
// 调用1个有参的 共有方法
Method m1 = clz.getMethod("hello");
// 调用对应的方法
// 第一个参数:那个类实例 第二个参数:方法调用时的实参
// m1.invoke方法调用的返回值就是方法对象本身的返回值
Object invoke = m1.invoke(clz.newInstance());
}
}
结果输出:
* 2、如何调用1个有参的 公有方法
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Method;
/**
* 反射动态调用方法
* 2、调用1个有参的 共有方法
* @author ChenChen
*@date 2022年6月16日 下午6:28:56
*/
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
/**
* 1、先拿到类类
* 2、拿到方法对象
* 3.调用对应的方法
*/
// 调用1个有参的共有方法
Method m2 = clz.getMethod("hello", String.class);
Object invoke2 = m2.invoke(clz.newInstance(),"吴彦祖");
System.out.println(invoke2);
}
}
结果输出:
* 3、如何调用私有方法
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Method;
/**
* 反射动态调用方法
* 3、调用私有方法
* @author ChenChen
*@date 2022年6月16日 下午6:28:56
*/
public class Demo3 {
public static void main(String[] args) throws Exception, Exception {
/**
* 1、先拿到类类
* 2、拿到方法对象
* 3.调用对应的方法
*/
// 调用私有方法
Method m3 = clz.getDeclaredMethod("add", Integer.class,Integer.class);
m3.setAccessible(true);
Object invoke3 = m3.invoke(clz.newInstance(), 5,5);
System.out.println(invoke3);
}
}
结果输出:
五、反射读写属性
代码块展示:
package com.chenchen.reflect;
import java.lang.reflect.Field;
/**
* 反射读写属性
* @author ChenChen
*@date 2022年6月16日 下午7:47:14
*/
public class Demo4 {
public static void main(String[] args) throws Exception, Exception {
Student stu = new Student("s001","吴彦祖");
stu.age=18;
// 需求:要拿到这个学生所有的属性及属性值
// System.out.println("age"+stu.age);
// System.out.println("sname"+stu.getSname());
// System.out.println("sid"+stu.getSid());
/**
* 上述代码存在的问题
* 1.你事先得知道这个类有哪些属性
* 2.假设Student有30个属性呢?那么就要写30行
* 对于未知的东西无法获取
*/
// 一切反射从类类开始
Class<? extends Student> clz = stu.getClass();
//拿到的是当前类的所有属性对象
Field[] files = clz.getDeclaredFields();//可以拿到私有的构造器也可以拿到公有的构造器
System.out.println("数组的长度"+files.length);
for (Field f : files) {//f-->代表每次循环的属性对象
//打开访问器
f.setAccessible(true);
//通过属性对象拿到属性名称
System.out.println("属性名称:"+f.getName());
//拿到当前的属性对象的属性值
System.out.println("属性的值:"+f.get(stu));
}
}
}
结果输出:
ok,本章内容分享完毕,下期预告JSP标签的解析知识点,希望对您有帮助,若本文章内容出现错误,还望指正,感谢您的观看。