Day26
注解
什么是注解
java.annotation包Annotation是從JDK1.5開始引入的新技術,注解即可以對程序員解釋又可以對程序解釋
注解與注釋的區別
注釋:對程序員解釋代碼信息注解:對程序和程序員解釋代碼信息
注解的所用
- 不是程序本身,可以對程序作出解釋(與注釋(comment)類似)2. 可以被其他程序(編譯器)讀取
注解的格式
注解是以“@注釋名”在代碼中存在的,還可以添加一些參數例如:@SuppressWarnings(value=“unchecked”)
注解的應用
可以附加在package、class、method、field等上面,相當于給他們添加了額外的輔助信息,我們可以通過反射機制實現對這些數據的訪問
知識點:內置注解
理解:Java給我們提供的注解
@Override - 重寫父類方法的注解
@SuppressWarnings - 鎮壓警告的注解
@Deprecated - 已棄用的注解@Deprecatedpublic void method02(){}@SuppressWarnings("all")public void method01(){ArrayList list = new ArrayList();list.add(100);list.add(123.123);}@Overridepublic String toString() {return super.toString();}
元注解
元注解的作用:負責注解其他注解,Java定義了4個標準的meta-annotation類型,他們被用來提供對其他annotation類型作說明
這些類型和它們所支持的類在java.lang.annotation包中可以找到
(@Target,@Retention,@Documented,@Inherited )
*@Target*:用于描述注解的使用范圍(即:被描述的注解可以用在什么地方)
*@**Retention*:表示需要要在什么級別保存該注擇信息,用于描述注解的生命周期
(SOURCE < CLASS < *RUNTIME*)
@Document:說明該注解將被包含在javadoc中
@lnherited:說明子類可以繼承父類中的該注解
知識點:自定義注解
@interface用來聲明一個注解,格式:public @interface注解名{定義內容}
其中的每一個方法實際上是聲明了一個配置參數.
方法的名稱就是參數的名稱.
返回值類型就是參數的類型(返回值只能是基本類型、Class、String、enum)
可以通過default來聲明參數的默認值
如果只有一個參數成員,一般參數名為value()
注解元素必須要有值,我們定義注解元素時,經常使用空字符串.0作為默認值
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotaction {}@MyAnnotactionpublic void method01() {}
@Target({TYPE,FIELD,CONSTRUCTOR,METHOD,PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaction {String value(); } @MyAnnotaction("aaa")public class Test01 {/*** 知識點:自定義注解*/@MyAnnotaction("aaa")String str;@MyAnnotaction("aaa")public Test01() {}@MyAnnotaction(value = "aaa")public void method01() {}@MyAnnotaction("aaa")public void method02(@MyAnnotaction("aaa") int i) {} }
@Target(METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaction {String value() default "abc"; }public class Test01 {/*** 知識點:自定義注解*/@MyAnnotaction(value = "aaa")public void method01() {}@MyAnnotaction("aaa")public void method02() {}@MyAnnotaction()public void method03() {}@MyAnnotactionpublic void method04() {} }
@Target(METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaction {String[] value(); }public class Test01 {/*** 知識點:自定義注解*/@MyAnnotaction(value = "aaa")public void method01() {}@MyAnnotaction({"aaa","bbb","ccc"})public void method02() {}@MyAnnotaction(value={"aaa","bbb","ccc"})public void method03() {} }
@Target(METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaction {String[] name(); }public class Test01 {/*** 知識點:自定義注解*/@MyAnnotaction(name = "aaa")public void method01() {}@MyAnnotaction(name = {"aaa","bbb","ccc"})public void method02() {}}
@Target(METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotaction {String name();String info() default "xxx"; }public class Test01 {/*** 知識點:自定義注解*/@MyAnnotaction(name = "aaa",info="xxx")public void method01() {}@MyAnnotaction(name = "aaa")public void method02() {} }
反射
反射機制
知識點:反射機制
前言:
使用到一個類,JVM會將該類的class文件加載到方法區(一次),
同時會在堆中創建一個該類的class對象,該類的class對象作為
該class文件的訪問入口。class文件里有什么?
該類中所有的信息,都在class文件里
比如:類信息、屬性信息、方法信息…理解:反射機制就是獲取到class對象,通過class對象操作class文件里的任意內容
學習路線:概念獲取class對象操作屬性操作構造方法操作方法操作參數、返回值操作泛型操作數組案例
知識點:獲取class對象
public static void main(String[] args) throws ClassNotFoundException {//方式一:直接通過類名調用Class<? extends Student> clazz1 = Student.class;//方式二:通過該類的對象的getClass()獲取該類的class對象Student stu = new Student();Class<? extends Student> clazz2 = stu.getClass();//方式三:Class<?> clazz3 = Class.forName("com.qf.reflex01.Student");System.out.println(clazz1 == clazz2);//trueSystem.out.println(clazz1 == clazz3);//true}
知識點:獲取class對象 + 配置文件
public class Test02 {/*** 知識點:獲取class對象 + 配置文件*/public static void main(String[] args) throws ClassNotFoundException, IOException {//創建properties對象Properties p = new Properties();//加載配置文件p.load(Test02.class.getClassLoader().getResourceAsStream("BeanConfig.properties"));//獲取屬性值String className = p.getProperty("className");Class<?> clazz = Class.forName(className);System.out.println(clazz);} }
知識點:封裝工具 + 配置文件 -> 獲取class對象
public class Test03 {/*** 知識點:封裝工具 + 配置文件 -> 獲取class對象*/public static void main(String[] args) {Class<?> clazz = ReflexUtil.getClazz();System.out.println(clazz);} }/*** 反射工具類* @author 何老師**/ public final class ReflexUtil {//配置文件里類的全限定名private static String className;//初始化配置文件static{Properties p = new Properties();try {p.load(ReflexUtil.class.getClassLoader().getResourceAsStream("BeanConfig.properties"));} catch (IOException e) {e.printStackTrace();}className = p.getProperty("className");}private ReflexUtil() {}/*** 獲取配置文件里配置的class對象* @return class對象*/public static Class<?> getClazz(){return getClazz(className);}/*** 獲取指定的class對象* @param className 類的全限定名* @return class對象*/public static Class<?> getClazz(String className){try {Class<?> clazz = Class.forName(className);return clazz;} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}
操作屬性
public class Test04 {/*** 知識點:操作屬性*/public static void main(String[] args) {//獲取class對象 // Class<?> clazz = ReflexUtil.getClazz();//獲取本類及其父類公有的屬性對象 // Field[] fields = clazz.getFields(); // for (Field field : fields){ // System.out.println(field); // }//獲取本類所有的屬性對象 // Field[] fields = clazz.getDeclaredFields(); // for (Field field : fields) { // System.out.println(field); // }//獲取本類及其父類所有的屬性對象 // for(Class<?> c = clazz;c != null;c = c.getSuperclass()){ // Field[] fields = c.getDeclaredFields(); // for (Field field : fields) { // System.out.println(field); // } // }//通過屬性名獲取本類及其父類公有的屬性對象 // try { // Field field = clazz.getField("classId"); // System.out.println(field); // } catch (NoSuchFieldException e) { // e.printStackTrace(); // } catch (SecurityException e) { // e.printStackTrace(); // }//通過屬性名獲取本類指定的屬性對象 // try { // Field field = clazz.getDeclaredField("classId"); // System.out.println(field); // } catch (NoSuchFieldException e) { // // TODO Auto-generated catch block // } catch (SecurityException e) { // e.printStackTrace(); // }//通過屬性名獲取本類及其父類指定的屬性對象 // for(Class<?> c = clazz;c != null;c = c.getSuperclass()){ // try { // Field field = c.getDeclaredField("name"); // System.out.println(field); // // //獲取屬性修飾信息 // int modifiers = field.getModifiers(); // System.out.println("判斷屬性是否使用public修飾:" + Modifier.isPublic(modifiers));//false // System.out.println("判斷屬性是否使用protected修飾:" + Modifier.isProtected(modifiers));//false // System.out.println("判斷屬性是否使用private修飾:" + Modifier.isPrivate(modifiers));//true // System.out.println("判斷屬性是否使用static修飾:" + Modifier.isStatic(modifiers));//false // System.out.println("判斷屬性是否使用final修飾:" + Modifier.isFinal(modifiers));//false // System.out.println("判斷屬性是否使用transient修飾:" + Modifier.isTransient(modifiers));//false // System.out.println("判斷屬性是否使用volatile修飾:" + Modifier.isVolatile(modifiers));//false // // } catch (NoSuchFieldException e) {//不輸出錯誤信息,子類找不到沒關系,直接去找父類 // } catch (SecurityException e) { // } // }//封裝工具類 -- 通過屬性名獲取本類及其父類指定的屬性對象 // Field field = ReflexUtil.getField(clazz, "name"); // System.out.println(field);//操作屬性 -- 獲取、設置 // Student stu = new Student(); // Field nameField = ReflexUtil.getField(clazz, "name"); // // nameField.setAccessible(true);//設置操作權限 // try { // //設置stu對象里面的name屬性為侯小康 // nameField.set(stu, "侯小康"); // } catch (IllegalArgumentException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // } // System.out.println(stu);//封裝工具類 -- 操作屬性 -- 獲取、設置Student stu = new Student();ReflexUtil.setField(stu, "name", "侯小康");ReflexUtil.setField(stu, "sex", '男');ReflexUtil.setField(stu, "age", 23);ReflexUtil.setField(stu, "classId", "2402");ReflexUtil.setField(stu, "id", "001");System.out.println(stu);} }
ReflexUitl.java里添加:
/*** 獲取屬性對象* @param clazz class對象* @param name 屬性名* @return 屬性對象*/public static Field getField(Class<?> clazz,String name){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Field field = c.getDeclaredField(name);return field;} catch (NoSuchFieldException e) {} catch (SecurityException e) {}}return null;}/*** 設置屬性* @param obj 目標對象* @param name 屬性名* @param val 屬性值*/public static void setField(Object obj,String name,Object val){Class<? extends Object> clazz = obj.getClass();Field field = getField(clazz, name);field.setAccessible(true);try {field.set(obj, val);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}
操作構造方法
創建對象
反射機制中傳入的基本數據類型會自動裝箱,而使用類方法獲取構造器時參數為class對象數組,且里面的元素是包裝類,所以要先設計一個參數類型處理的方法
/*** 參數類型處理器* @param parameterVals 參數數據的可變參數* @return 參數類型的數組*/private static Class<?>[] parameterValsHandle(Object... parameterVals){ArrayList<Class<?>> list = new ArrayList<>();for (Object object : parameterVals) {Class<? extends Object> parameterType = object.getClass();if(parameterType == Byte.class){parameterType = byte.class;} else if(parameterType == Short.class){parameterType = short.class;} else if(parameterType == Integer.class){parameterType = int.class;} else if(parameterType == Long.class){parameterType = long.class;} else if(parameterType == Float.class){parameterType = float.class;} else if(parameterType == Double.class){parameterType = double.class;} else if(parameterType == Character.class){parameterType = char.class;} else if(parameterType == Boolean.class){parameterType = boolean.class;} list.add(parameterType);}Class<?>[] parameterTypes = new Class[list.size()];list.toArray(parameterTypes);return parameterTypes;}
思路為通過獲取的class對象創建構造器,再用構造器去創建對象。
public static <T> T newInstance(Class<T> clazz,Object...parameterVals){Class<?>[] parameterTypes = parameterValsHandle(parameterVals);try {Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);constructor.setAccessible(true);T t = constructor.newInstance(parameterVals);return t;} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}
public class Test05 {/*** 知識點:操作構造方法*/@SuppressWarnings("all")public static void main(String[] args) {//獲取class對象Class<Student> clazz = (Class<Student>) ReflexUtil.getClazz();//獲取本類公有的構造方法 // Constructor<?>[] constructors = clazz.getConstructors(); // for (Constructor<?> constructor : constructors) { // System.out.println(constructor); // }//獲取本類所有的構造方法 // Constructor<?>[] constructors = clazz.getDeclaredConstructors(); // for (Constructor<?> constructor : constructors) { // System.out.println(constructor); // }//獲取本類及其父類所有的構造方法 // for(Class<?> c = clazz;c != null;c = c.getSuperclass()){ // Constructor<?>[] constructors = c.getDeclaredConstructors(); // for (Constructor<?> constructor : constructors) { // System.out.println(constructor); // } // }//獲取無參構造方法對象,利用無參構造方法對象創建該類的對象 // try { // //獲取無參構造方法對象 // Constructor<?> constructor = clazz.getDeclaredConstructor(); // //利用無參構造方法對象創建該類的對象 // Student stu = (Student) constructor.newInstance(); // System.out.println(stu); // } catch (NoSuchMethodException e) { // e.printStackTrace(); // } catch (SecurityException e) { // e.printStackTrace(); // } catch (InstantiationException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // } catch (IllegalArgumentException e) { // e.printStackTrace(); // } catch (InvocationTargetException e) { // e.printStackTrace(); // }//利用無參構造方法對象創建該類的對象 // try { // Student stu = (Student) clazz.newInstance(); // System.out.println(stu); // } catch (InstantiationException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // }//獲取有參構造方法對象,利用有參構造方法對象創建該類的對象 // try { // //獲取有參構造方法對象 // Constructor<?> constructor = clazz.getDeclaredConstructor(String.class,char.class,int.class,String.class,String.class); // //設置操作權限 // constructor.setAccessible(true); // //利用有參構造方法對象創建該類的對象 // Student stu = (Student) constructor.newInstance("侯小康",'男',23,"2402","001"); // System.out.println(stu); // } catch (NoSuchMethodException e) { // e.printStackTrace(); // } catch (SecurityException e) { // e.printStackTrace(); // } catch (InstantiationException e) { // e.printStackTrace(); // } catch (IllegalAccessException e) { // e.printStackTrace(); // } catch (IllegalArgumentException e) { // e.printStackTrace(); // } catch (InvocationTargetException e) { // e.printStackTrace(); // }//封裝工具類 -- 創建對象 // Student stu = ReflexUtil.newInstance(clazz); // System.out.println(stu);//封裝工具類 -- 創建對象Student stu = ReflexUtil.newInstance(clazz, "侯小康",'男',23,"2402","001");System.out.println(stu);} }
操作方法、參數、返回值及泛型
知識點:操作方法
public class Test06 {/*** 知識點:操作方法*/@SuppressWarnings("all")public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//獲取class對象Class<Student> clazz = (Class<Student>) ReflexUtil.getClazz();//獲取本類及其父類的公有方法對象 // Method[] methods = clazz.getMethods(); // for (Method method : methods) { // System.out.println(method); // }//獲取本類的所有方法對象 // Method[] methods = clazz.getDeclaredMethods(); // for (Method method : methods) { // System.out.println(method); // }//獲取本類及其父類所有方法對象 // for(Class<?> c = clazz;c != null;c = c.getSuperclass()){ // Method[] methods = c.getDeclaredMethods(); // for (Method method : methods) { // System.out.println(method); // } // }//通過方法名獲取方法對象 // try { // Method method = clazz.getDeclaredMethod("setClassId", String.class); // method.setAccessible(true); // System.out.println(method); // // //獲取方法修飾信息 // int modifiers = method.getModifiers(); // System.out.println("判斷方法是否使用public修飾:" + Modifier.isPublic(modifiers));//true // System.out.println("判斷方法是否使用protected修飾:" + Modifier.isProtected(modifiers));//false // System.out.println("判斷方法是否使用private修飾:" + Modifier.isPrivate(modifiers));//false // System.out.println("判斷方法是否使用static修飾:" + Modifier.isStatic(modifiers));//false // System.out.println("判斷方法是否使用final修飾:" + Modifier.isFinal(modifiers));//false // System.out.println("判斷方法是否使用abstract修飾:" + Modifier.isAbstract(modifiers));//false // System.out.println("判斷方法是否使用synchronized修飾:" + Modifier.isSynchronized(modifiers));//false // // } catch (NoSuchMethodException e) { // e.printStackTrace(); // } catch (SecurityException e) { // e.printStackTrace(); // }//調用成員方法 // Student stu = ReflexUtil.newInstance(clazz, "侯小康",'男',23,"2402","001"); // Method getClassIdMethod = clazz.getDeclaredMethod("getClassId"); // getClassIdMethod.setAccessible(true); // Object getClassIdMethodReturnVal = getClassIdMethod.invoke(stu); // System.out.println(getClassIdMethodReturnVal);//2402 // // Method setClassIdMethod = clazz.getDeclaredMethod("setClassId", String.class); // setClassIdMethod.setAccessible(true); // Object setClassIdMethodReturnVal = setClassIdMethod.invoke(stu, "2403"); // System.out.println(setClassIdMethodReturnVal);//null // // System.out.println(stu);//調用靜態 // Method method = clazz.getDeclaredMethod("method", String.class,int.class); // method.setAccessible(true); // Object methodReturnVal = method.invoke(null, "abc",888); // System.out.println(methodReturnVal);//封裝工具類 -- 調用成員方法 // Student stu = ReflexUtil.newInstance(clazz, "侯小康",'男',23,"2402","001"); // Object getClassIdMethodReturnVal = ReflexUtil.invoke(stu, "getClassId"); // System.out.println(getClassIdMethodReturnVal);//2402 // // Object setClassIdMethodReturnVal = ReflexUtil.invoke(stu, "setClassId", "2403"); // System.out.println(setClassIdMethodReturnVal);//null // System.out.println(stu);//封裝工具類 -- 調用靜態Object methodReturnVal = ReflexUtil.invoke(clazz, "method", "abc",888);System.out.println(methodReturnVal);} }
工具類相關方法創建:
/*** 獲取方法對象* @param clazz class對象* @param name 方法名* @param parameterTypes 方法參數類型數組* @return 方法對象*/public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Method method = c.getDeclaredMethod(name, parameterTypes);return method;} catch (NoSuchMethodException e) {} catch (SecurityException e) {}}return null;}/*** 調用靜態方法* @param clazz class對象* @param name 方法名* @param parameterVals 參數數組* @return 返回值*/public static Object invoke(Class<?> clazz,String name,Object... parameterVals){Class<?>[] parameterTypes = parameterValsHandle(parameterVals);Method method = getMethod(clazz, name, parameterTypes);try {Object returnVal = method.invoke(null, parameterVals);return returnVal;} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}/*** 調用成員方法* @param obj 對象* @param name 方法名* @param parameterVals 方法參數數組* @return 返回值*/public static Object invoke(Object obj,String name,Object... parameterVals){Class<? extends Object> clazz = obj.getClass();Class<?>[] parameterTypes = parameterValsHandle(parameterVals);Method method = getMethod(clazz, name, parameterTypes);try {Object returnVal = method.invoke(obj, parameterVals);return returnVal;} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}
知識點:操作方法的參數和返回值
public class Test07 {/*** 知識點:操作方法的參數和返回值*/@SuppressWarnings("all")public static void main(String[] args) {//獲取class對象Class<Student> clazz = (Class<Student>) ReflexUtil.getClazz();Method method = ReflexUtil.getMethod(clazz, "method", String.class,int.class);//獲取參數信息 -----------------------------------------------------------------------//獲取參數列表的類型 // Class<?>[] parameterTypes = method.getParameterTypes(); // for (Class<?> c : parameterTypes) { // System.out.println(c); // }//獲取參數對象數組 // Parameter[] parameters = method.getParameters(); // for (Parameter parameter : parameters) { // // Class<?> type = parameter.getType();//參數類型 // String name = parameter.getName();//參數名(注意:參數名不會隨著編譯而編譯到class文件里) // System.out.println(type + " -- " + name); // }//獲取參數個數 // int parameterCount = method.getParameterCount(); // System.out.println("獲取參數個數:" + parameterCount);//2//獲取返回值信息 -----------------------------------------------------------------------Class<?> returnType = method.getReturnType();System.out.println(returnType);//class java.lang.StringType genericReturnType = method.getGenericReturnType();System.out.println(genericReturnType);//class java.lang.String} }
知識點:操作泛型
public class Test08 {/*** 知識點:操作泛型*/public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException { // Class<Student> clazz = Student.class;Class<?> clazz = ReflexUtil.getClazz("Student");//獲取屬性上的泛型類型Field mapField = clazz.getDeclaredField("map");Type mapFieldGenericType = mapField.getGenericType();//獲取屬性類型ParameterizedType mapFieldPT = (ParameterizedType) mapFieldGenericType;//強轉為子接口的類型Type[] actualTypeArguments = mapFieldPT.getActualTypeArguments();//獲取泛型類型數組for (Type type : actualTypeArguments) {System.out.println(type);}//獲取參數上的泛型類型Method method = clazz.getDeclaredMethod("method", ArrayList.class,ConcurrentHashMap.class);Parameter[] parameters = method.getParameters();for (Parameter parameter : parameters) {Type type = parameter.getParameterizedType();ParameterizedType pt = (ParameterizedType) type;Type[] ata = pt.getActualTypeArguments();for (Type t : ata) {System.out.println(t);}}//獲取返回值上的泛型類型Type genericReturnType = method.getGenericReturnType();ParameterizedType pt = (ParameterizedType) genericReturnType;Type[] actualTypeArguments2 = pt.getActualTypeArguments();for (Type type : actualTypeArguments2) {System.out.println(type);}} }
操作數組
知識點:操作數組
理解:Array類是Java提供的反射數組類
public static void main(String[] args) {//創建數組int[] arr = (int[]) Array.newInstance(int.class, 10);//獲取長度System.out.println("獲取長度:" + Array.getLength(arr));//10//循環遍歷 - 設置數據for (int i = 0; i < Array.getLength(arr); i++) {Array.set(arr, i, i+1);//設置數據}//循環遍歷 - 獲取數據for (int i = 0; i < Array.getLength(arr); i++) {Object element = Array.get(arr, i);System.out.println(element);}}