1.什么是反射
反射是java语言中的一种机制,通过这种机制可以动态的实例化对象,读写属性,调用方法;
反射是框架设计的灵魂
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))
2反射的使用(这里用Student类做演示)
先写一个Student类(代码如下)
package com.zking.reflect;
public class Student {
private String sid;
private String sname;
public Integer age;
//静态代码块
static{
System.out.println("加载进jvm中!");
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
//无参构造函数
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());
}
}
2.1获取Class对象的3种方式
package com.zking.reflect;
public class Text {
private static void mian(String[] args) throws ClassNotFoundException {
//第一种Class.forName 得到Student的模板--可以制造出很多对象--对对象赋值就可以得到不同的学生。
// TODO Auto-generated method
//返回的是objcet类型
Class<Student> stuclazz = (Class<Student>) Class.forName("com.zking.Student.java");
//2.Student.class
Class<Student> stuClazz01= Student.class;
//3.对象.getClass()
Student stu =new Student();
Class<Student> stuClazz02 = (Class<Student>) stu.getClass();
//
}
}
注意:在运行期间,一个类,只有一个Class对象产生。
2.2反射获取构造方法并使用
反射实例化
getConstructor: |
getDeclaredConStructor: |
newlnstance:我们在调用newInstance()方法时就调用的无参的构造函数来获取得值 |
package com.zking.reflect;
import java.lang.reflect.Constructor;
public class Text2 {
public static void main(String[] args) throws Exception {
/*//1.直接new对象
Student stu =new Student();*/
//2.通过反射
//首先获取大写的class对象
Class<Student> stuClazz =(Class<Student>) Class.forName("com.zking.reflect.Student");
/*Constructor<Student> c1 = stuClazz.getConstructor();//wuc
Student stu02= c1.newInstance();*/
//获取到stu的实例
Student stu02=stuClazz.newInstance();//对于调用无参的构造函数的一种简单的方式
stu02.setSid("01");
stu02.setSname("zs");
System.out.println("stu =" + stu02.getSname());
//获取构造函数parameterTypes
Constructor<Student> stuCon = stuClazz.getConstructor(String.class);
//用构造函数new对象
//注意构造函数是有参数的所以要带参数
Student stu03 =stuCon.newInstance("li");
System.out.println("stu03 ="+stu03.getSid());
Constructor<Student> stuCon04 = stuClazz.getConstructor(String.class,String.class);
Student stu04= stuCon04.newInstance("04","ww");
System.out.println("stu04 ="+ stu02.getSid());
//调用私有的构造函数
Constructor<Student> stuCon05 = stuClazz.getDeclaredConstructor(Integer.class);
//如果方法是私有的
stuCon05.setAccessible(true);//打开私有方法的访问权限
Student stu05=stuCon05.newInstance(23);
System.out.println("stu05 =" +stu05.age);
}
}
运行结果
反射动态方法调用
getMethod |
GetDeclaredMethod: 私有的方法使用 |
package com.zking.reflect;
import java.lang.reflect.Method;
public class Text03 {
public static void main(String[] args) throws Exception {
//传统方式
Student stu =new Student();
stu.setSname("zs");
Class<Student> stuClazz =(Class<Student>) Class.forName("com.zking.reflect.Student");
Student stu02=stuClazz.newInstance();//对于调用无参的构造函数的一种简单的方式
stu02.setSid("01");
stu02.setSname("zs");
//动态获取方法
Method method = stuClazz.getMethod("hello");
Object obj = method.invoke(stu02);
System.out.println(obj);//无参
//所有的java反射都是基于stuClazz对象的
Method m02 = stuClazz.getMethod("hello",String.class);
m02.invoke(stu02, "hhhh");
//有返回值的情况 以及私有方法
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("add",Integer.class, Integer.class);
里面要写上方法名和参数。
如果方法是私有的就要用setAccessible(true);打开对该方法的访问权限
运行结果
反射读写属性
getDeclaredField |
getDeclaredFieds |
package com.zking.reflect;
import java.lang.reflect.Field;
public class Text04 {
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(2);
Field f = stuclazz.getField("age");
int age=(int) f.get(stu02);
//System.out.println(age);
//获取私有属性
Field f02 =stuclazz.getDeclaredField("sname");
f02.setAccessible(true);
String name=(String)f02.get(stu02);
//System.out.println(name);
f02.set(stu02, "hhhh");
System.out.println("-----"+stu02.getSname());
Field[] fs=stuclazz.getDeclaredFields();
for(Field f04:fs) {
f04.setAccessible(true);
System.out.println(f04.getName()+": "+f04.get(stu02));
}
}
}
运行结果