文章目錄
- 反射
- 獲取class對象的三種方式
- 獲取構造方法
- 獲取成員變量
- 獲取成員方法
- 反射的作用
- 動態代理
反射
允許對成員變量\成員方法\構造方法的信息進行編程訪問
把類內的信息扒的干干凈凈,獲取+解剖
獲取從class字節碼文件中獲取
獲取class對象的三種方式
public static void main(String[] args) throws ClassNotFoundException {//第一種//最為常用Class<?> aClass = Class.forName("com.itheima.stream.Student");System.out.println(aClass);//第二種//更多是作為參數進行傳遞Class<Student> studentClass = Student.class;System.out.println(studentClass);//第三種//有了這個類的對象,才可以使用Student student = new Student();Class<? extends Student> aClass1 = student.getClass();System.out.println(aClass1);
}
獲取構造方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getConstructors();//返回所有的公共構造方法
// aClass.getDeclaredConstructors();//返回所有的構造方法
// aClass.getConstructor();//返回單個公共的構造方法
// aClass.getDeclaredConstructor();//返回單個的構造方法Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);//獲取構造中的參數Parameter[] parameters = declaredConstructor.getParameters();for (Parameter parameter : parameters) {System.out.println(parameter);}//用反射創建對象//如果是私有的構造方法,需要設置 accessible 為 true,暴力反射訪問declaredConstructor.setAccessible(true);Student student = (Student) declaredConstructor.newInstance("張三", 23);System.out.println(student);
}
獲取成員變量
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getFields();
// aClass.getDeclaredFields();
// aClass.getField();
// aClass.getDeclaredField();Field[] declaredFields = aClass.getDeclaredFields();for (Field declaredField : declaredFields) {System.out.println(declaredField);}Field name = aClass.getField("name");//獲取權限修飾符System.out.println(name.getModifiers());//獲取成員變量類型System.out.println(name.getType());
}
獲取成員方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {Class<?> aClass = Class.forName("com.itheima.stream.Student");
// aClass.getMethods();//獲取所有的方法(包含父類)
// aClass.getDeclaredMethods();//獲取本類所有的方法(不包含父類)Method method = aClass.getMethod("toString");
// aClass.getDeclaredMethod();//獲取拋出的異常Class<?>[] exceptionTypes = method.getExceptionTypes();for (Class<?> exceptionType : exceptionTypes) {System.out.println(exceptionType.getName());}Method eat = aClass.getMethod("eat", String.class);Student student = new Student();Object out = eat.invoke(student, "漢堡");System.out.println(out);
}
這里的invoke是重點,蒼穹外賣的代理有用到
反射的作用
- 獲取一個類里面所有的信息,獲取到之后,再執行其他的業務邏輯
- 結合配置文件,動態的創建對象并調用方法
確實,我也想不出來怎么從配置文件中獲取或修改方法類
public static void saveObject(Object object) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class clazz = object.getClass();//獲取所有的成員變量Field[] declaredFields = clazz.getDeclaredFields();for (Field declaredField : declaredFields) {declaredField.setAccessible(true);String name = declaredField.getName();Object o = declaredField.get(object);System.out.println(name + ":" + o);}
}
動態代理
無侵入式的給對象增強其他的功能
代理工具類
public class ProxyUtil {public static Star createProxy(BigStar bigStar){Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),//指定用哪個類加載器,去加載生成的代理new Class[]{Star.class},//指定代理類需要實現的接口new InvocationHandler() {//指定生成的代理要干什么@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//參數1,代理對象//參數2,要調用的方法//參數3,調用方法時,傳遞的參數if ("sing".equals(method.getName())){System.out.println("準備話筒,收錢");} else if ("dance".equals(method.getName())) {System.out.println("準備場地,收錢");}return method.invoke(bigStar,args);}});return star;}
代理對象
public class BigStar implements Star{private String name;public BigStar() {}public BigStar(String name) {this.name = name;}@Overridepublic String sing(String name){System.out.println(this.name+"正在唱歌"+name);return "謝謝";}@Overridepublic void dance(){System.out.println(this.name+"正在跳舞");}/*** 獲取* @return name*/public String getName() {return name;}/*** 設置* @param name*/public void setName(String name) {this.name = name;}public String toString() {return "BigStar{name = " + name + "}";}
}
代理對象對應準備的接口,用接口代理對象實現附加功能
public interface Star {void dance();String sing(String name);
}
測試
public static void main(String[] args) {Star proxy = ProxyUtil.createProxy(new BigStar("王寶強"));String result = proxy.sing("某某");System.out.println(result);
}