反射
package reflect; public class Car { public String brand; private String color; private int maxSpeed; //①默认构造函数 public Car(){} //②带参构造函数 public Car(String brand,String color,int maxSpeed){ this.brand = brand; this.color = color; this.maxSpeed = maxSpeed; } //③未带参的方法 public void introduce() { System.out.println("brand:"+brand+";color:"+color+";maxSpeed:" +maxSpeed); } public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } }
package reflect; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class ReflectTest { /** *验证所有的类都是Class类的实例对象 * @throws ClassNotFoundException */ public static void verifyIns() throws ClassNotFoundException{ System.out.println("-----验证所有的类都是Class类的实例对象 -----"); //定义两个类型都未知的Class , 设置初值为null, 看看如何给它们赋值成Person类 Class<?> class1 = null; Class<?> class2 = null; //写法1, 可能抛出 ClassNotFoundException [多用这个写法] class1 = Class.forName("reflect.Car"); System.out.println("(写法1) 包名: " + class1.getPackage().getName() + "," + "完整类名: " + class1.getName()); //写法2 // class2 = Car.class; // System.out.println("(写法2) 包名: " + class2.getPackage().getName() + "," // + "完整类名: " + class2.getName()); } /** * 通过获取类的默认构造器创建实例 * @throws Throwable */ public static void initByDefaultConst() throws Throwable { System.out.println("-----通过获取类的默认构造器创建实例-----"); //写法1 //通过类加载器获取car对象 ClassLoader loader = Thread.currentThread().getContextClassLoader();//获取当前线程的ClassLoader Class clazz = loader.loadClass("reflect.Car");//通过指定的全限定类“reflect.Car”装载Car类对应的反射实例 //获取类的默认构造器对象并通过它实例化car Constructor cons = clazz.getDeclaredConstructor((Class[]) null);//通过Car的反射类对象获取Car的构造函数对象cons Car car = (Car) cons.newInstance();//通过构造函数对象的newInstrance()方法实例化Car对象,其效果等同于new Car() System.out.println("包名:"+car.getClass().getPackage().getName()+",完整类名:"+car.getClass().getName()); //通过反射方法设置属性 Method setBrand = clazz.getMethod("setBrand", String.class);//通过Car的反射类对象的getMethod(String methodName,Class paramClass)获取属性的Setter方法对象,第一个参数是目标Class的方法名;第二个参数是方法入参的对象类型 setBrand.invoke(car, "红旗");//获取方法反射对象后,即可通过invoke(Object obj,Object param)方法调用目标类的方法,该方法的第一个参数是操作的目标类对象实例;第二个参数是目标方法的入参。 Method setColor = clazz.getMethod("setColor", String.class); setColor.invoke(car, "红色"); Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class); setMaxSpeed.invoke(car, 200); Method introduce = clazz.getMethod("introduce",null); introduce.invoke(car, null); //写法2 // Class clazz = Class.forName("reflect.Car"); // Car car = (Car)clazz.newInstance(); // System.out.println("包名:"+car.getClass().getPackage().getName()+",完整类名:"+car.getClass().getName()); } /** * 通过获取类的指定构造器创建实例 * @throws Throwable */ public static void initBySpecifiedConst() throws Throwable { System.out.println("-----通过获取类的指定构造器创建实例-----"); ClassLoader loader = Thread.currentThread().getContextClassLoader();//获取当前线程的ClassLoader Class clazz = loader.loadClass("reflect.Car");//通过指定的全限定类“reflect.Car”装载Car类对应的反射实例 Constructor c = clazz.getConstructor(String.class,String.class,int.class); Car car = (Car) c.newInstance("Benz","黑色",100); Method introduce = clazz.getMethod("introduce",null); introduce.invoke(car, null); } /** *获取构造器列表并用其中一个创建实例 * @throws Throwable * @throws Exception */ public static void getAllConstsAndNewInstance() throws Throwable { System.out.println("-----获取构造器列表并用其中一个创建实例-----"); ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class clazz = loader.loadClass("reflect.Car"); Constructor[] constructors = clazz.getConstructors(); Car car0 = (Car)constructors[0].newInstance(); System.out.println("包名:"+car0.getClass().getPackage().getName()+",完整类名:"+car0.getClass().getName()); Object obj = (Car)constructors[1].newInstance("Benz","黑色",100); System.out.println("包名:"+obj.getClass().getPackage().getName()+",完整类名:"+obj.getClass().getName()); } /** * 获取并操作成员变量 * @throws Throwable */ public static void getAndProcessField() throws Throwable{ System.out.println("-----获取并操作成员变量-----"); Class clazz = Class.forName("reflect.Car"); Object obj = clazz.newInstance(); // Field[] fields = clazz.getFields();//getFields():获得某个类的所有的公共(public)的字段,包括父类中的字段 Field[] fields = clazz.getDeclaredFields();//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。 for(Object o :fields){ System.out.println(o); } // AccessibleObject.setAccessible(fields, true); //对所有属性设置访问权限 当类中的成员变量为private时 必须设置此项 Field fieldBrand = clazz.getField("brand"); fieldBrand.setAccessible(true); fieldBrand.set(obj, "BWM");//对当前属性设置访问权限 当类中的成员变量为private时 必须设置此项 System.out.println("修改属性之后得到属性变量的值:" + fieldBrand.get(obj)); Field fieldColor = clazz.getDeclaredField("color"); fieldColor.setAccessible(true); fieldColor.set(obj, "white");//对当前属性设置访问权限 当类中的成员变量为private时 必须设置此项 System.out.println("修改属性之后得到属性变量的值:" + fieldColor.get(obj)); } /** * 获取并操作成员方法 * @throws Throwable */ public static void getAndProcessMethods() throws Throwable{ System.out.println("-----获取并操作成员方法-----"); ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class clazz = loader.loadClass("reflect.Car"); // Method[] methods = clazz.getMethods(); //getMethods()返回某个类的所有公用(public)方法包括其继承类的公用方法,当然也包括它所实现接口的方法。 Method[] methods = clazz.getDeclaredMethods();//getDeclaredMethods()对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。当然也包括它所实现接口的方法。 for(Method m :methods){ System.out.println("方法:"+m); System.out.println("方法名:"+m.getName()); System.out.println("方法返回类型:"+m.getReturnType()); System.out.println("函数访问修饰符:" + Modifier.toString(m.getModifiers())); } Method methodIntroduce = clazz.getMethod("introduce",null); methodIntroduce.invoke(clazz.newInstance(), null); //取得类实现的接口,因为接口类也属于Class Class interfaces[] = clazz.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { System.out.println("实现的接口类名: " + interfaces[i].getName() ); } } /**得到类加载器信息 * @throws Throwable */ public static void getClassLoader() throws Throwable{ System.out.println("-----得到类加载器信息-----"); Class clazz = Class.forName("reflect.Car"); String classLoaderName = clazz.getClassLoader().getClass().getName(); System.out.println("classLoaderName:"+classLoaderName); } public static void main(String args[]) throws Throwable{ verifyIns(); initByDefaultConst(); initBySpecifiedConst(); getAllConstsAndNewInstance(); getAndProcessField(); getAndProcessMethods(); getClassLoader(); } }
常用反射的一些地方
https://www.cnblogs.com/ldh-better/p/7148975.html#_label2_1
1.工厂模式:Factory类中用反射的话,添加了一个新的类之后,就不需要再修改工厂类Factory了
2.数据库JDBC中通过Class.forName(Driver).来获得数据库连接驱动
3.分析类文件:毕竟能得到类中的方法等等
4.访问一些不能访问的变量或属性:破解别人代码
如何优化反射?
一. 善用API
比如,尽量不要getMethods()后再遍历筛选,而直接用getMethod(methodName)来根据方法名获取方法
二、缓存
比如,需要多次动态创建一个类的实例的时候,有缓存的写法会比没有缓存要快很多:
// 1. 没有缓存
void createInstance(String className){
return Class.forName(className).newInstance();
}
// 2. 缓存forName的结果
void createInstance(String className){
cachedClass = cache.get(className);
if (cachedClass == null){
cachedClass = Class.forName(className);
cache.set(className, cachedClass);
}
return cachedClass.newInstance();
}
为什么?当然是因为forName太耗时了。