反射机制
– 指的是可以于运行时加载、探知、使用编译期间完全未知的类。 – 程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个 已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对 象,都能够调用它的任意一个方法和属性;
Class c = Class.forName("com.bjsxt.test.User");
– 加载完类之后,在堆内存中,就产生了一个 Class 类型的对象(一个 类只有一个 Class 对象),这个对象就包含了完整的类的结构信息。 我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过 这个镜子看到类的结构,所以,我们形象的称之为:反射。
Class介绍
java.lang.Class类十分特殊,用来表示java中类型 (class/interface/enum/annotation/primitive type/void)本 身。
– Class类的对象包含了某个被加载类的结构。一个被加载的类对应一个 Class对象。
– 当一个class被加载,或当加载器(class loader)的defineClass()被 JVM调用,JVM 便自动产生一个Class 对象。
• Class类是Reflection的根源。 – 针对任何您想动态加载、运行的类,唯有先获得相应的Class 对象
测试
student类
package bean;
public class User {
private String name;
private int age;
private int id;
public User(String name, int age, int id) {
super();
this.name = name;
this.age = age;
this.id = id;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
package test;
@SuppressWarnings("all")
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
String path = "bean.User";//类的路径
//对象是表示或封装一些数据,一个类被加载后,JVM会创建一个对应类的Class对象,类的整个结构信息会放到对应的Class对象中
//这个对象就像一面镜子,通过这个镜子可以看到对应类的所有信息,就像图纸一样
Class<?> clz1 = Class.forName(path);
System.out.println(clz1.hashCode());
Class<?> clz2 = Class.forName(path);
System.out.println(clz2.hashCode());//同一个类hashcode一致,既同一个类就会被加载一次
//获得String类Class对象
Class strClaz = String.class;
Class strClaz2 = path.getClass();
System.out.println(strClaz == strClaz2);//都是class java.lang.String类对象
//数组
int[] arr01 = new int[10];
int[] arr02 = new int[20];
int[][] arr03 = new int[10][30];
System.out.println(arr01.getClass().hashCode());
System.out.println(arr02.getClass().hashCode());//同一维度数组的Class对象一致,与数组长度无关
System.out.println(arr03.getClass().hashCode());//不同维度数组的Class对象不一致
}
}
应用反射的api 获取类的信息(类的名字,属性,方法,构造器等)
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
* 应用反射的api 获取类的信息(类的名字,属性,方法,构造器等)
*
*
*/
@SuppressWarnings("all")
public class Demo02 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
String path = "bean.User";//类的路径
try {
Class<?> clz = Class.forName(path);
//获取类的名字
System.out.println(clz.getName());//获取包名+类名:bean.User
System.out.println(clz.getSimpleName());//获取类名:User
//获取属性信息
Field[] fields = clz.getFields();//只能获得public的field
System.out.println(fields.length);//0
Field[] fields2 = clz.getDeclaredFields();//获得所有的属性
System.out.println(fields2.length);//3
for (Field field : fields2) {
System.out.println(field);
}
/*private java.lang.String bean.User.name
private int bean.User.age
private int bean.User.id
*/
Field f = clz.getDeclaredField("name");
System.out.println(f);//获取指定属性的信息:private java.lang.String bean.User.name
//获取方法信息
Method[] methods = clz.getDeclaredMethods();//获取所有的方法
Method[] methods2 = clz.getMethods();//获取所有的public方法
Method m01 = clz.getDeclaredMethod("getName", null);//第二个参数表示方法的参数,没有写null
Method m02 = clz.getDeclaredMethod("setName", String.class);//如果有则必须指定参数的类型,方便方法的重载
for (Method method : methods2) {
System.out.println("方法----->" + method);
}
//获取构造器信息
Constructor[] constructors = clz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println("构造器---->" + constructor);
}
System.out.println("获取指定的构造器---->" + clz.getConstructor(String.class,int.class,int.class));//获取无参构造器设置为null
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
动态操作构造器 方法 属性
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import bean.User;
@SuppressWarnings("all")
public class Demo03 {
public static void main(String[] args) throws Exception{
String path = "bean.User";//类的路径
try {
Class clz = Class.forName(path);
//利用反射api调用构造方法,构造对象
User user = (User)clz.newInstance();//调用的是User类的无参构造器,没有会报错, 写javabean必须要无参构造器
//指定构造器
Constructor<User> c = clz.getConstructor(String.class,int.class,int.class);
User u = c.newInstance("dan",11,222);//建立对象
System.out.println(u.getId());//获得:222
//通过反射api调用普通方法
User u3 = (User)clz.newInstance();
Method method = clz.getDeclaredMethod("setId", int.class);
method.invoke(u3, 22);//相当于u3.setId(22)
System.out.println(u3.getId());
//通过反射api操作属性
User u4 = (User)clz.newInstance();
Field f = clz.getDeclaredField("name");
f.setAccessible(true);//设置私有属性可以访问
f.set(u4, "john");
System.out.println(u4.getName());//这时候回报错 不能访问私有属性
System.out.println(f.get(u4));//获取u4的f属性
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}