思维导图~~~
一、什么是反射
反射是java语言的一种机制,利用反射机制动态的实例化对象(构造函数)、读写属性、调用方法。
二、类类
1、如何得到类对象
一切反射相关的代码都从获得类对象开始;
2、三种获取方式
(1)、Class.forName(全限定名/全路径名)(最常用);
(2)、类名.class;
(3)、对象名.getClass();
在写有参构造的时候顺便加一个无参构造;因为在很多框架的底层是通过无参构造去对类进行实例化的;
没有无参构造会报以下错误:
Student类:(所有代码中所用的)
package com.mwy.fs;
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());
}
}
三种获取方式:
package com.mwy.fs;
/**
* 获取类类的类对象的三种方式
* 1、Class.forName
* 2、类.class
* 3、类类的类对象的类实例.getClass();
*/
public class Test_1 {
public static void main(String[] args) throws Exception {
//1、Class.forName
Class<Student> stuCla = (Class<Student>) Class.forName("com.mwy.fs.Student");
//2、Student.class 会用于:通用查询
Class stuCla1=Student.class;
//3、会用于:通用增删改
Class stuCla2=new Student().getClass();
}
}
注意:ClassNotFoundException(类名错|少jar包);同一类的、类对象只会创建一个 。
三、反射实例化
1、getConstructor:获取单个公有构造方法;
2、getDeclaredConstructor:获取单个构造方法(包括私有、受保护、默认、公有);
3、getConstrutors(); :获取所有的公有构造方法
4、getDeclaredConstrutors(); :获取所有的构造方法(包括私有、受保护、默认、公有)
5、newInstance:
//1、Class.forName
Class<Student> stuCla = (Class<Student>) Class.forName("com.mwy.fs.Student");、//实例化
Student stu = stuCla.newInstance();
1、getDeclaredConstructor与getConstructor的区别
(1)getConstructor() ;反射调用有参构造
//反射调用有参构造
//括号里面放要调的有参构造的参数类型
Constructor<Student> c = stuCla.getConstructor(String.class);
//实例化
Student s = c.newInstance("s001");
//括号里面放要调的有参构造的参数类型
Constructor<Student> c1 = stuCla.getConstructor(String.class,String.class);
//实例化
Student s1 = c1.newInstance("s001","zs");
(2)调用私有化(公开)的方法 ;getDeclaredConstructor();
//getDeclaredConstructor:可以获取到私有的构造器,以及公共的构造器
//调用私有化的方法
//括号里面放要调的有参构造的参数类型
Constructor<Student> c2 = stuCla.getDeclaredConstructor(Integer.class);
//打开访问权限
c2.setAccessible(true);
//实例化
Student s2 = c2.newInstance(18);
(3)setAccessible():打开访问权限
①、当私有化方法用getConstructor();时
②、调用getDeclaredConstructor();记得打开权限;不然会出现以下错误:
四、反射动态方法调用
1、getMethod(); :获取单个公有方法
2、getDeclaredMethod(); :获取单个方法(包括私有、受保护、默认、公有)
3、getMethods(); :获取所有公有方法
4、getDeclaredMethods(); :获取所有的方法(包括私有、受保护、默认、公有)
调用hello方法,方法无参;
//1、Class.forName
Class<Student> stuCla = (Class<Student>) Class.forName("com.mwy.fs.Student");
//实例化
Student s = stuCla.newInstance();
//调用hello方法,方法无参;
Method m = stuCla.getDeclaredMethod("hello");
//执行;invoke参数1:类实例,在这里指的是Student类实例;
//参数2:当前被调用的方法,传递的参数值;
//invoke的返回值,就是被反射调用的方法的返回值;如果被调用的方法是void,那么返回null;
System.out.println( m.invoke(s));
调用hello方法,方法有参;参数放有参构造的参数类型
//调用hello方法,方法有参;参数放有参构造的参数类型
Method m1 = stuCla.getDeclaredMethod("hello",String.class);
System.out.println( m1.invoke(s,"mwy"));
//调用私有化hello方法,方法有参;参数放有参构造的参数类型
Method m2 = stuCla.getDeclaredMethod("add",Integer.class,Integer.class);
//打开访问权限
m2.setAccessible(true);
System.out.println( m2.invoke(s,10,10));
结果为:
五、反射读写属性
Field f = stuCla.getDeclaredField("sname"); //sname:属性名
1、getDeclaredField(“属性名”); 获取单个属性(私有、公有、受保护、默认、静态)
2、getDeclaredFields(); 获取所有属性(私有、公有、受保护、默认、静态)
3、getName(); 获取属性名
4、getType(); 获取属性类型
5、getModifiers(); 获取属性访问修饰符
6、set(Object,Object); 设置属性值,参数1:要设置属性所在对象;参数2:要设置的值
7、get(Object); 获取属性值,参数:要获取属性值的对象
//1、Class.forName
Class<Student> stuCla = (Class<Student>) Class.forName("com.mwy.fs.Student");
//实例化
Student s = stuCla.newInstance();
//拿到Student的sname
Field f = stuCla.getDeclaredField("sname");
//打开访问权限
f.setAccessible(true);
//反射写属性
//第一个:给类实例放入;第二个:给sname的属性设置值
f.set(s, "mwy");
//oop的读属性
System.out.println(s.getSname());
//反射读属性
System.out.println(f.get(s));
例题:比较OOP与反射读取属性值得方式
Student stu=new Student("soo2","ls");
stu.age=18;
System.out.println(stu.getSid());
System.out.println(stu.getSname());
System.out.println(stu.age);
System.out.println("----------");
//反射获取该对象所有属性值
Field[] field = stuCla.getDeclaredFields();
for (Field ff : field) {
ff.setAccessible(true);//打开权限
System.out.println(ff.getName()+":"+ff.get(stu));
}
结果: 反射更便捷;
今天到此结束了哦~~~