一、反射简介
之前讲的类加载:将类的类信息加载的JVM中,我们在运行时采用才可以使用这些类
前提的条件:JVM一定要知道它现在需要加载的是什么类
有一种情况:JVM在加载类的时候,它不知道该加载什么类,但是它在运行时, 却知道它现在需要什么类,此时就需要使用到反射机制,才可以解决它不知道的类
反射:在类加载时,不知道它要加载什么东西,但是在运行时,却知道了它需要用什么类,此时就反过头去重新加载的情况
举例说明
info.properties文件
girl=com.woniuxy.java33.study.bean.GentleGirl
package com.woniuxy.java33.study.bean;public class Girl {}
package com.woniuxy.java33.study.bean;/*** 温柔型女孩* @author Administrator**/public class GentleGirl extends Girl{}
package com.woniuxy.java33.study.bean;/*** 粗鲁型女孩* @author Administrator**/public class BlodGirl extends Girl{}
package com.woniuxy.java33.study.util;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.Properties;/*** properties文件 的加载类* @author Administrator**/public class PropertiesUtil {public static String getValue(String key) {Properties props = new Properties();FileInputStream fis = null;try {String path = System.getProperty("user.dir") + File.separatorChar + "src" + File.separatorChar +"info.properties" ;File file = new File(path);fis = new FileInputStream(file);props.load(fis);}catch (Exception e) {// TODO: handle exceptione.printStackTrace();}finally {try {fis.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}return props.getProperty(key);}public static void main(String[] args) {System.out.println(getValue("girl"));}}
package com.woniuxy.java33.study.reflect;import com.woniuxy.java33.study.util.PropertiesUtil;public class MainEnter {public static void main(String[] args) {// TODO Auto-generated method stub//妈妈安排相亲String girl = PropertiesUtil.getValue("girl");System.out.println(girl);// Girl girl =//用反射try {//forName() 调用 类加载器 去重新加载Class cls = Class.forName(girl);System.out.println(cls);System.out.println(cls.newInstance());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
反射中,最核心的方法:Class.forName()
该方法:Class.forName() 可以做到:在运行期去加载 需要的类
二、Class类
class类是反射中最重要的类
如果你在程序代码,需要使用到Class类,有3种方式获取:
1、Class.forName() 应用于反射
2、如果已知类的情况,使用类名.class 也可以获取到
3、如果已知类的对象,使用 对象.getClass() 同样可以获取到
三、如何使用Class 类来完成创建对象,调用方法,调用属性
3.1 创建对象
调用无参构造器,产生实例
//forName() 调用 类加载器 去重新加载Class cls = Class.forName(girl);//根据cls创建实例 newInstance() 调用无参构造器Object obj = cls.newInstance();
调用有参构造器,产生实例
//forName() 调用 类加载器 去重新加载
Class cls = Class.forName(girl);
//返回有参构造器
Constructor cons = cls.getConstructor(String.class,Integer.class);
Object obj = cons.newInstance("三上",18);
System.out.println(obj);
3.2 调用属性
//返回有参构造器
Constructor cons = cls.getConstructor(String.class,Integer.class);
Object obj = cons.newInstance("三上",18);
System.out.println(obj);
// //不能返回私有属性
// Field field = cls.getField("girlName");
// System.out.println(field.get(obj));
//可以返回 私有属性
Field field = cls.getDeclaredField("girlName");
//给其他类,授权访问 私有属性
field.setAccessible(true);
System.out.println(field.get(obj));
//set 主要给属性赋新的值
field.set(obj, "市川**");
//get 主要用于获得属性的内容
System.out.println(field.get(obj));
3.3 调用方法
//获取私有方法
Method meth = cls.getDeclaredMethod("cry", null);
meth.setAccessible(true);//同样给私有方法,授权
System.out.println(meth);
//调用方法(第一个参数表示对象,第二个参数表示 具体的值)
Object result = meth.invoke(obj, null);
//输出方法的返回结果
System.out.println(result);
//获得非私有方法(第一个参数表示方法名,第二个参数表示 参数类型)
// Method meth = cls.getMethod("cry", null);
// System.out.println(meth);
// //调用方法(第一个参数表示对象,第二个参数表示 具体的值)
// Object result = meth.invoke(obj, null);
// //输出方法的返回结果
// System.out.println(result);
3.4 获得注解
//返回有参构造器
Constructor cons = cls.getConstructor(String.class,Integer.class);
Object obj = cons.newInstance("三上",18);
System.out.println(obj);
//根据方法对象,获得方法上的 注解
Method meth = cls.getMethod("cry", null);
MyLog mylog = meth.getAnnotation(MyLog.class);
System.out.println(mylog.menuName());
System.out.println(mylog.optType());
