反射是动态语言的关键,反射允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任曦对象的内部属性及方法。
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- java.lang.Class : 代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java .lang.reflect.Construct:代表类的构造方法
Class类的作用:
1.每一个运行时类只加载一次!
2.获取对应的运行时类的完整结构(属性,方法,构造器,内部类,父类,所在包,异常,注 解。。。。)
3.调用对应的运行时类的指定结构(属性,方法,构造器)
4.反射应用:动态代理
4.获取Class对象。
Class<Person> personClass01 = Person.class;
2.通过运行时类的一个对象
Person person = new Person(); Class<? extends Person> aClass = person.getClass();
3.通过Class.forName("com.jdy.bean.Dog")
Class<?> aClass1 = Class.forName("com.jdy.bean.Dog");
4.通过类的加载器
ClassLoader classLoader = this.getClass().getClassLoader();
public Constructor<?>[] getConstructors() throws SecurityException //获取类的全部构造 public Field[] getDeclaredFields() throws SecurityException//获取类中全部的属性 public Field[] getFields() throws SecurityException //获取继承的全部属性 public Method[] getMethods() throws SecurityException//获取一个类中的所有方法 public Class<?>[] getInterfaces() //获取类实现的所有接口 public native Class<? super T> getSuperclass();//获取类的父类
String packageName ="com.jdy.bean.Dog"; Class<?> aClass = Class.forName(packageName); Dog dog = (Dog)aClass.newInstance(); //使用newInstance()必须保证实例化类中存在一个无参构造器
public int getModifiers()//获取构造方法的修饰符 public String getName()//获取构造方法的名称 public Class<?>[] getParameterTypes()//获取构造方法的参数类型 public T newInstance(Object ... initargs)//像构造方法,传入参数实例化对象
<Dog> constructor = (Constructor<Dog>) aClass.getConstructor(String.class, String.class, String.class);
Dog dog1 = constructor.newInstance("二狗子", "黑背", "8");
- Constructor:表示类的构造器
- Field:表示类的属性
- Method:表示类的方法
取得所有实现的接口
Class<?>[] interfaces = aClass.getInterfaces();
取得父类
Class<?> superclass = aClass.getSuperclass();
取得全部构造器
Constructor<?>[] constructors = aClass.getConstructors();
将访问修饰符由数字转化成可看懂的
int modifiers = declaredField.getModifiers(); System.out.println("modifiers = " + Modifier.toString(modifiers));
取得所有的方法
Method[] methods = aClass.getMethods();
取得全部属性
//得到实现的接口或父类中的公共属性 Field[] fields = aClass.getFields(); //得到本类当中的全部属性 Field[] declaredFields = aClass.getDeclaredFields();
Field的常用方法
//得到一个对象中属性的具体内容 public Object get(Object obj)throws IllegalArgumentException, IllegalAccessException //设置指定对象中属性的具体内容 public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException //得到属性的修饰符 public int getModifiers() //返回属性的名称 public String getName() //判断属性是否可悲外部访问 public boolean isAccessible() //设置一个属性是否可被外部方法 public void setAccessible(boolean flag) throws SecurityException
(4)通过反射待用类中的方法
Method destory_method = aClass.getMethod("destory_method"); //invoke方法的参数是一个实例化的对象 Object invoke = destory_method.invoke(aClass.newInstance());
反射中通过Field类提供的set()/get()完成设置和取得属性内容的操作,但是类中的属性都设置成私有的访问权限,所以在使用set()/get()方法时首先要使用Field()中的setAccessible(true),方法将需要操作的属性设置成可被外部访问。
Field field0 = personClass.getDeclaredField("address"); //todo 什么校验 field0.setAccessible(true); field0.set(person,"xian"); System.out.println(person);
一般给类的属性赋值,不建议使用以上方法,因为扩大了属性的访问权限,建议使用类中属性的getter/setter方法
//3.引导类加载器不能直接获取 ClassLoader parent1 = parent.getParent(); System.out.println("引导类加载器 = " + parent1);//null
//2.获取扩展类加载器 ClassLoader parent = loader.getParent(); System.out.println("扩展类加载器 = " + parent);
//1.获取系统类加载器 ClassLoader loader = ClassLoader.getSystemClassLoader(); System.out.println("系统类加载器 = " + loader);
获取某个实例的类加载器
Person person = new Person(); Class<? extends Person> aClass = person.getClass(); ClassLoader classLoader = aClass.getClassLoader(); System.out.println("Perosn类的加载器 = " +classLoader);
Class<?> aClass1 = Class.forName("com.jdy.bean.Dog"); ClassLoader classLoader1 = aClass1.getClassLoader(); System.out.println("Dog类的加载器 = " + classLoader1);
类加载器配合IO
ClassLoader classLoader2 = this.getClass().getClassLoader(); InputStream resourceAsStream = classLoader2.getResourceAsStream("test.properties"); Properties properties = new Properties(); properties.load(resourceAsStream);