什么是反射:反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读取属性、调用方法
为什么学习反射机制:在开发自定义mvc框架的时候,通过java 的反射机制去动态的生成这些类的实例对象,并且动态的调用它的方法
首先有一个Student学生实体类,里面有三个属性
Student类里的构造方法如下:
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 Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
//@SuppressWarnings("unused")压制警告的,可有可无
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
类类:①Class.forName(完整类名)
②类名.class
③对象.getClass()
下面是三种得到Student类的方法:
反射实例化:
①getConstructor
②getDeclaradConstryctor
③newlnstance
下面是演示代码:
public class Test02 {
public static void main(String[] args) throws Exception {
//获取Student对象
//第1种 直接new对象
//Student stu = new Student();
//第2种 反射
Class<Student> stuClazz = (Class<Student>) Class.forName("com.zking.reflect.Student");
/*Constructor<Student> c1 = stuClazz.getConstructor();//获取到无参的构造函数
Student stu02 = c1.newInstance();*/
//无参构造函数的简便办法
Student stu02 = stuClazz.newInstance();
stu02.setSid("11");
stu02.setSname("zs");
System.out.println("stu02 =" + stu02.getSname());
Constructor<Student> stuCon = stuClazz.getConstructor(String.class);
Student stu03 = stuCon.newInstance("22");
System.out.println("stu03 =" + stu03.getSid());
Constructor<Student> stuCon04 = stuClazz.getConstructor(String.class,String.class);
Student stu04 = stuCon04.newInstance("王五","33");
System.out.println("stu04 =" + stu04.getSid()+" "+stu04.getSname());
//调用私有的构造函数
//假如方法是私有的就需要用到getDeclaredConstructor才能获取到
Constructor<Student> stuCon05 = stuClazz.getDeclaredConstructor(Integer.class);
stuCon05.setAccessible(true);//打开私有方法的访问权限
Student stu05 = stuCon05.newInstance(23);
System.out.println("stu05 ="+ stu05.age);
}
}
运行结果如下:
注意:假如构造函数(构造方法)是私有的就需要用到getDeclaredConstructor才能获取到,然后还需要stuCon05.setAccessible(true);打开私有方法的访问权限,才能获取或者设置值 !!
反射动态方法调用:
①getMethod
②getDeclaradMenthod
代码实例:
public class Test03 {
public static void main(String[] args) throws Exception {
//1、传统方式
Student stu = new Student();
stu.setSid("1");
stu.setSname("张三");
//2、反射
Class<Student> stuClazz = (Class<Student>) Class.forName("com.zking.reflect.Student");
Student stu02 = stuClazz.newInstance();
stu02.setSid("01");
stu02.setSname("zs");
//通过反射来获取Method对象
Method method = stuClazz.getMethod("hello");
Object obj = method.invoke(stu02);
System.out.println(obj);
//调用有参的hello函数
Method m02 = stuClazz.getMethod("hello", String.class);
m02.invoke(stu02, "煲仔");
//调用有返回值的函数
//Method 方法对象,私有的方法要用到getDeclaredMethod
Method m03 = stuClazz.getDeclaredMethod("add", Integer.class, Integer.class);
m03.setAccessible(true);//打开私有方法的访问权限
int sum = (int) m03.invoke(stu02, 3,3);
System.out.println(sum);
}
}
运行结果如下:
注意:私有的方法要用到getDeclaredMethod,然后还需要m03.setAccessible(true);打开私有方法的访问权限!!!
反射读写属性:
①getDeclaredField
②getDelaredFieldes——得到的是一个数组
public class Test04 {
public static void main(String[] args) throws Exception {
Class<Student> stuClazz = (Class<Student>) Class.forName("com.zking.reflect.Student");
Student stu02 = stuClazz.newInstance();
stu02.setSid("01");
stu02.setSname("zs");
stu02.setAge(20);
//动态的获取属性的值
Field f = stuClazz.getField("age");
int age =(int) f.get(stu02);
System.out.println(age);
//获取私有的属性
Field f1 = stuClazz.getDeclaredField("sname");
f1.setAccessible(true);//打开私有的访问权限
String name = (String) f1.get(stu02);
System.out.println(name);
//设置值
f1.set(stu02, "煲仔爱吃煲仔饭");
System.out.println("-------"+stu02.getSname());
Field[] fs = stuClazz.getDeclaredFields();
for(Field f2 : fs) {
f2.setAccessible(true);
System.out.println(f2.getName()+":"+f2.get(stu02));
}
}
}
运行结果如下:
注意:私有的方法要用到getDeclaredField,然后还需要f1.setAccessible(true);打开私有方法的访问权限!!!