目录
一、什么是反射
二、java.lang.Class类类
三、反射如何实例化
四、反射动态方法的调用
五、反射如何读写属性
六、反射如何访问属性修饰符
一、什么是反射
反射就是Java语言中的一种机制,
通过这种机制可以动态的实例化对象、读写属性、调用方法。
二、java.lang.Class类类
我们需要使用Java反射机制的话就必须要先获得你想操作的类的java.lang.Class对象;
然后接下来我们就来一起了解一下类类的几种获取方式吧:
我们先放上学习案例需要的一个实体类:Student
package com.leaf.reflect;
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());
}
}
获取Class对象的三种方式:
2.1 类.class
//1、类.class
Class cl1 = Student.class;
2.2 类实例.getClass()
//2、类实例.getClass()
Student stu = new Student();
Class cl2 = stu.getClass();
2.3 Class.forName("类的全路径名");
//3、Class.forName("类的全路径名");
Class cl3 = Class.forName("com.leaf.reflect.Student");
三、反射如何实例化
使用Java反射机制的第一步获取Class的三种方式我们都了解过了,
接下来我们就来了解一下如何用反射来实例化一个对象吧:
我们以前一般实例化一个对象是这样做的:
Student stu = new Student();
而接下来我们就看看用反射又如何来实例化:
3.1 第一步还是获取Class类:3.2 无参的 共有的构造函数://获取类类
Class extends Student> cl1 = stu1.getClass();
3.3 有参数 共有的构造方法:1、无参数 共有的构造方法
Student stu = cl1.newInstance();
3.4 拿到有多个参数 共有的构造方法:2、有参数 共有的构造方法
//拿到构造器对象 三个点代表可以传n个参数--->拿到一个参数为String的构造器对象
Constructor extends Student> c1 = cl1.getConstructor(String.class);
Student stu5 = c1.newInstance("s001");
3.5 私有的构造方法:3、拿到有多个参数 共有的构造方法
Constructor extends Student> c2 = cl1.getConstructor(String.class,String.class);
Student stu6 = c2.newInstance("s002","颠婆");
4、私有的构造方法
//getConstructor只能获取共有的构造方法,要获取私有的构造器getDeclaredConstructor
Constructor extends Student> c3 = cl1.getDeclaredConstructor(Integer.class);
//打开访问权限
c3.setAccessible(true);
Student stu = c3.newInstance(19);
我们可以看到调用的实体类的方法运行结果:
最后总结一下反射机制实例化对象的步骤以及注意点:
1)拿到Class类;
2)Class类点newInstance();--->没有参数的实例化
3)有参数的实例化还要拿到构造器对象: Class类点getConstructor("参数的类型.class");
再用构造器对象点newInstance();
4)如果是私有的构造方法还就需要拿到私有的构造器对象:
Class类点getDeclaredConstructor("参数的类型.class");
然后再打开访问权限:构造器对象点setAccessible(true);
最后再用构造器对象点newInstance();
四、反射动态方法的调用
如何使用反射机制动态调用方法呢?一起来看看吧:
4.1 第一步还是先拿到类类:类点Class4.2 拿到方法对象:getMethod("方法名");1、拿到类类
Classcl1 = Student.class;
4.3 调用对应的方法:invoke(类实例, "参数");2、拿到方法对象
//name:方法名 parameterTypes:方法对应的参数类型
Method m1 = cl1.getMethod("hello");
3、调用对应的方法
//第一个参数:类实例 第二个参数:方法调用时的实际参数
//m1.invoke方法调用的返回值就是方法对象本身hello方法的返回值
Object invoke = m1.invoke(cl1.newInstance());
我们打印测试一下:
由于方法是void无返回,所以值为null,
但是根据文章开头提供的案例类Student可以发现方法已经成功调用~
还有有参以及私有方法的调用,步骤基本一致,这里就直接放上代码了:
Method m2 = cl1.getMethod("hello", String.class);
Object invoke2 = m2.invoke(cl1.newInstance(), "邓正威");
System.out.println(invoke2);
运行结果:
//拿到私有方法对象
Method m3 = cl1.getDeclaredMethod("add", Integer.class,Integer.class);
//打开权限
m3.setAccessible(true);
//调用方法参数1+参数2
Object invoke3 = m3.invoke(cl1.newInstance(), 10,7);
//打印结果
System.out.println(invoke3);
运行结果:
我们还是总结一下Java机制动态调用方法的步骤:
五、反射如何读写属性
学会了如何使用Java机制调用方法后我们再来看看如何读写属性吧:
实例化一个Student类:
Student stu = new Student("s009","Leaf");
然后我们再来看看这个案例需求:拿到这个学生所有的属性及属性值;
这时我们平常可能就是这样做的:
需求:拿到这个学生所有的属性及属性值
System.out.println("Sid:"+stu.getSid());
System.out.println("Sname:"+stu.getSname());
System.out.println("Age:"+stu.age);
是的,这样我们也能得到结果,简单快捷,但是,这样的代码也有着诸多问题:
5.1 这个时候我们就可以用到我们的Java反射啦:先拿到Class类类
5.2 拿到当前类所有的属性对象:getDeclaredFields();//一切反射从类类开始
Class extends Student> cl1 = stu.getClass();
5.3 循环遍历:Field[] fields = cl1.getDeclaredFields();
System.out.println("属性数量:"+fields.length);
注意--->当属性是私有化修饰的时候记得打开访问权限~
//循环遍历属性对象 f:每一个属性对象
for (Field f : fields) {
//打开访问权限
f.setAccessible(true);
//通过属性对象拿到属性名称
System.out.print(f.getName()+": ");
//通过此类实例拿到当前属性对象的属性值
System.out.println(f.get("类实例stu"));
}
运行结果:
六、反射如何访问属性修饰符
当我们能够成功读写到属性值后,
这想要访问这些属性的修饰符时,
就可以使用java.lang.reflect中Modifier接口的一个方法--->getModifiers()
我们这个时候回到上一标题获取属性值的循环遍历步骤:
//一切反射从类类开始
Class extends Student> cl1 = stu.getClass();
//当前类所有的属性对象
Field[] fields = cl1.getDeclaredFields();
//循环遍历属性对象 f:每一个属性对象
for (Field f : fields) {
//打开访问权限
f.setAccessible(true);
}
这个时候我们就用属性对象点getModifiers()
//循环遍历属性对象 f:每一个属性对象
for (Field f : fields) {
//打开访问权限
f.setAccessible(true);
//获取属性的修饰符
int i = f.getModifiers();
}
它返回的是一个修饰符整型数字,很难分辨这是什么修饰符,
于是我们可以用Modifier接口的toString(修饰符数字)方法转换为修饰符:
Modifier.toString(修饰符数字)
//循环遍历属性对象 f:每一个属性对象
for (Field f : fields) {
//打开访问权限
f.setAccessible(true);
//获取属性的修饰符
int i = f.getModifiers();
System.out.println(f.getName()+"的修饰符是:"+Modifier.toString(i));
}
我们运行看看:
OK,今天Leaf的学习笔记分享就到这里啦,后面也还会有更多的Java学习分享,喜欢的可以关注一起学习噢~有问题都可以私信俺!我们下次再见啦!!!



