什么是反射
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
反射获取类对象(三种方式)
我们先来创建一个Student类
package com.xieminglu.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());
}
@Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
}
}
1.Class.forName(“类的全路径名”); 常用与jdbc、自定义mvc框架
Class<?> class1 = Class.forName("com.xieminglu.reflect.Student");
System.out.println(class1);
输出的结果为:
2.类名.class 做通用查询
Class<?> class1 = Student.class;
System.out.println(class1);
输出的结果为:
3.类(Class类类的类对象)实例.getClass() 做通用的增删改
Student stu=new Student();
Class<?> class1 = stu.getClass();
System.out.println(class1);
输出的结果为:
一切反射相关的代码都从获得类(java.lang.Class)对象开始
3.1 Class.forName(完整类名)
3.2 类名.class
3.3 对象.getClass()
反射实例化
1.能够实例化未知的类
2.能够通过私有构造器创建实例
Student stu=(Student)cla.newInstance();
输出的结果为:
// 拿到构造器类
Constructor<Student> con = cla.getConstructor(String.class);
// 通过构造器实例化对象
Student student = (Student)con.newInstance("s001");
输出的结果为:
Constructor<Student> con = cla.getConstructor(String.class,String.class);
Student student = (Student)con.newInstance("s001","zs");
输出的结果为:
Constructor<Student> con = cla.getConstructor(Integer.class);
Student student = (Student)con.newInstance(1);
输出的结果为:
这个报错的原因是因为getConstructor只能找到public修饰的构造器,getDeclaredConstructor可以找到任何修饰符的构造器
Constructor<Student> con = cla.getDeclaredConstructor(Integer.class);
Student student = (Student)con.newInstance(1);
输出的结果为:
这个报错的原因public是私有的不让访问,我们得设置让它访问
Constructor<Student> con = cla.getDeclaredConstructor(Integer.class);
con.setAccessible(true);
Student student = (Student)con.newInstance(1);
输出的结果为:
反射调用方法
Student stu=new Student();
stu.hello();
输出的结果为:
Student stu=new Student();
Class cla=stu.getClass();
Method m=cla.getDeclaredMethod("hello");
m.invoke(stu);
输出的结果为:
Student stu=new Student();
Class cla=stu.getClass();
Method m=cla.getDeclaredMethod("hello",String.class);
m.invoke(stu,"zs");
输出的结果为:
Student stu=new Student();
Class cla=stu.getClass();
Method m=cla.getDeclaredMethod("add",Integer.class,Integer.class);
m.setAccessible(true);
//invoke如果反射动态调用的方法是被void所修饰,那么返回的是null
//如果反射动态调用的方法不被void所修饰,那么返回的就是被调用的方法的返回值
Object invoke = m.invoke(stu,20,5);
System.out.println(invoke);
输出的结果为:
反射属性赋值取值
package com.xieminglu.reflect;
import java.lang.reflect.Field;
/*
* 反射属性赋值取值
* *
*/
public class Demo4 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
Student stu=new Student();
stu.setSid("s001");
stu.age=22;
System.out.println(stu);
// 反射赋值
Class cla=stu.getClass();
Field f = cla.getDeclaredField("sid");
Field f1 = cla.getDeclaredField("age");
f.setAccessible(true);
f.set(stu, "s002");
f1.set(stu, 28);
System.out.println(stu);
// 读
System.out.println(f.get(stu));
System.out.println(f1.get(stu));
// 使用反射读取
Field[] fields = cla.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName() + " : " + field.get(stu));
}
}
}
输出的结果为: