一切皆爲對象,是Java的核心概念;java
從這個概念出發,咱們不由要問類是否是對象?若是類也是對象,類又是誰的實例對象呢?函數
答案是確定的,類也是對象,類是java.lang.Class(如下簡稱Class)的實例對象,Class也被成爲類的類類型。spa
假設有類Student,以下code
class Student{ private int id; private String name; //get,set方法 }
獲取類的類類型有三種方法,分別以下:對象
1. Class c1 = Student.class;blog
2. Student stu = new Student();繼承
Class cl = stu.getClass();get
3. Class cl = Class.forName("類全名");io
咱們能夠經過類的類類型建立這個類的實例對象,前提是這個類有一個無參的構造函數,以下編譯
Student stu = (Student) c1.newInstance();
動態加載的概念
編譯時加載類是靜態加載類,new 對象
運行時加載類時動態加載類
反射使用
//獲取類的名稱 String className = cl.getName(); //獲取類名稱的簡寫 String classSimpleName = cl.getSimpleName(); /** * Method類,方法的對象 * 一個成員方法就是一個Method對象 * getMethods() 獲取的是所有public的方法,包括從父類繼承來的 *getDeclaredMethods()獲取本身聲明的所有方法(public private protect),不獲 * 取父類 */ Method[] methods = cl.getMethods(); for (Method method : methods){ //獲得方法的返回類型 //獲得方法返回值的類類型 Class returnType = method.getReturnType(); //獲得方法名 String methodName = method.getName(); //獲取參數類型 //獲得參數列表的類型的類類型 Class[] paras = method.getParameterTypes(); for (Class c : paras){ System.out.print(c.getName()); } }
經過反射獲取變量
/** * 成員變量也是對象 * java.lang.reflect.Field * Field 封裝了成員變量的操做 * getFields() 獲取全部的public成員變量信息 * getDeclaredFields() 獲取該類本身聲明的全部成員變量信息 */ Field[] fields = cl.getDeclaredFields(); for (Field field : fields){ //變量的修飾符 //獲得成員變量的類型的類類型 Class fieldType = field.getType(); String typeName = fieldType.getName(); //獲得成員變量的名稱 String fieldName = field.getName(); //打印變量類型和變量名 System.out.println(typeName + " " + fieldName); }
打印構造函數信息
/** * 構造函數也是對象 * java.lang.reflect.Constructor 中封裝了構造函數的信息 * getConstructors() 獲取全部的public的構造函數 * getDeclaredConstructors() 獲取全部的構造函數 */ /*Constructor[] cs = cl.getConstructors();*/ Constructor[] cs = cl.getDeclaredConstructors(); for (Constructor c : cs){ //獲取構造函數名稱 c.getName(); //獲取構造函數的類型的類類型 c.getParameterTypes(); }
方法反射
/** * 方法的反射 * 方法的名稱和方法的參數列表能夠惟一肯定一個方法 * 方法的反射操做 * Method.invoke(對象, 參數列表) */ public static void main(String[] args) throws Exception{ A a = new A(); //獲取print(int, int)方法 //1. 首先獲取類的類類型 Class cl = a.getClass(); /** * 2. 獲取方法,名稱和參數列表肯定惟一方法 * getMethod() 獲取的是public方法 * getDeclaredMethod() 獲取所有本身聲明的方法 */ Method method = cl.getMethod("print", new Class[]{int.class, int.class}); //3. 方法的反射操做,是指用Method對象來進行調用 //方法沒有返回值返回null,有返回值就返回返回值 Object object = method.invoke(a, new Object[]{1,2}); //method.invoke(a, 1, 2); }
使用反射回去對象變量值
public static <T> void printTInfo(T t) throws IllegalAccessException{ Class cl = t.getClass(); Field[] fields = cl.getDeclaredFields(); for (Field field : fields){ //setAccessible(true)不老是必須的,可是變量爲私有是必須設置 field.setAccessible(true); System.out.println(field.get(t)); } }
使用反射解析註解
//1.使用類加載器加載類 Class cl = Class.forName("Student"); //2.找到類上面的註解 boolean exist = cl.isAnnotationPresent(Customize.class); if (exist){ //3.拿到註解實例 Customize customize = (Customize) cl.getAnnotation(Customize.class); System.out.println(customize.value()); } //4.找到方法上的註解 Method[] methods = cl.getMethods(); for (Method method : methods){ if (method.isAnnotationPresent(Customize.class)){ System.out.println(((Customize)method.getAnnotation(Customize.class)).value()); } } //4.1另外一種解析方法 for (Method method : methods){ Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations){ if (annotation instanceof Customize){ System.out.println(((Customize) annotation).value()); } } }
註解定義
public @interface Customize { String value() default "I am annotation"; }