咱們建立一個類,經過編譯,生成對應的.calss文件,以後使用java.exe加載(jvm的類加載器)此.class文件,此.class文件加載到內存之後,就是一個運行時類,存在緩存區,那麼這個運行時類的自己就是一個class的實例java
在反射之前,如何建立一個類的對象,並調用其中的方法屬性數組
public void test1() { Person p = new Person(); p.setAge(10); p.setName("AA"); p.show(); System.out.println(p); }
有了反射,能夠經過反射建立一個類的對象,並調用其中的方法,下面詳細說緩存
public void test2() throws Exception { Class clazz = Person.class; //1.建立clazz對應的運行時類Person類的對象 Person p = (Person)clazz.newInstance(); System.out.println(p); //2.經過反射調用運行時類的指定屬性,public name的修改方式 Field f1 = clazz.getField("name"); f1.set(p, "LiuDaHua"); System.out.println(p); //private age的方式 Field f2 = clazz.getDeclaredField("age"); f2.setAccessible(true); f2.set(p, 20); System.out.println(p); //3.經過反射調用運行時類的指定方法 public修飾的 Method m1 = clazz.getMethod("show"); // 執行 m1.invoke(p); // 帶參數的方法 Method m2 = clazz.getMethod("display", String.class); m2.invoke(p, "cn"); }
Class clazz = Person.class; System.out.println(clazz.getName()); Class clazz1 = String.class; System.out.println(clazz1.getName());
Person p = new Person(); Class clazz2 = p.getClass(); System.out.println(clazz.getName());
String className = "com.atguigu.java.Person"; Class clazz4 = Class.forName(className); System.out.println(clazz4);
ClassLoader classLoader = this.getClass().getClassLoader(); Class clazz5 = classLoader.loadClass(className); System.out.println(clazz5.getName());
整個代碼jvm
public void test4() throws Exception { //1.調用運行時類自己的.class屬性 Class clazz = Person.class; System.out.println(clazz.getName()); Class clazz1 = String.class; System.out.println(clazz1.getName()); //2.經過運行時類的對象獲取 Person p = new Person(); Class clazz2 = p.getClass(); System.out.println(clazz.getName()); //3.經過Class的靜態方法獲取,經過此方式,體會反射的動態性 String className = "com.atguigu.java.Person"; Class clazz4 = Class.forName(className); System.out.println(clazz4); //4.經過類的加載器 ClassLoader classLoader = this.getClass().getClassLoader(); Class clazz5 = classLoader.loadClass(className); System.out.println(clazz5.getName()); }
一般直接使用類名.class , 例如Person.class測試
固然了,上面的幾種方法都是能夠的ui
String className = "com.atguigu.java.Person"; Class clazz = Class.forName(className);
建立對應的運行時類的對象,使用的是newInstance(),實際上就是運用了運行時類的空參數的構造器this
要想可以建立成功code
Object obj = clazz.newInstance();//調用的是空參構造器 Person p = (Person)obj; System.out.println(p);
所有代碼對象
public void test1() throws Exception { // 獲取Class實例 Class clazz = Person.class; //建立對應的運行時類的對象,使用的是newInstance(),實際上就是運用了運行時類的空參數的構造器 //要想可以建立成功,①要求對應的運行時類要有空參數的構造器,②構造器的權限修飾符的權限要足夠 Object obj = clazz.newInstance();//調用的是空參構造器 Person p = (Person)obj; System.out.println(p); }
1.getFields() 返回 :表示公共字段的 Field 對象的數組,只能獲取運行時類中以及父類中聲明的爲public的屬性接口
Field[] fiels = clazz.getFields(); for(int i=0;i<fiels.length;i++) { System.out.println(fiels[i]); }
2.getDeclaredFields() :獲取運行時類自己聲明的全部的屬性,包括私有的
Field[] fiels1 = clazz.getDeclaredFields(); for(int i=0;i<fiels1.length;i++) { System.out.println(fiels1[i].getName()); } //加強for循環 for(Field f:fiels1) { System.out.println(f.getName()); }
權限修飾符 變量類型 變量名
1.獲取每一個屬性的權限修飾符
Field[] field = clazz.getDeclaredFields(); for(Field i:field) { //1.獲取每一個屬性的權限修飾符 int a = i.getModifiers(); String str1 = Modifier.toString(a); System.out.print(str1+" "); }
2.獲取屬性的變量類型
Field[] field = clazz.getDeclaredFields(); for(Field i:field) { //2.獲取屬性的變量類型 Class type = i.getType(); System.out.print(type+" "); }
3.獲取屬性名
Class clazz = Person.class; Field[] field = clazz.getDeclaredFields(); for(Field i:field) { //3.獲取屬性名 System.out.print(i.getName()); System.out.println(); }
1.getMethods() 獲取運行時類及其父類中全部聲明爲public的方法
Class clazz = Person.class; Method[] m1 = clazz.getMethods(); for(Method m:m1) { System.out.println(m); }
2.getDeclaredMethods() 獲取運行時類自己聲明的全部的方法
Method[] methods = clazz.getDeclaredMethods(); for(int i=0;i<methods.length;i++) { System.out.println(methods[i]); }
註解 權限修飾符 返回值類型 方法名 形參列表 異常
1.註解
Class clazz = Person.class; Method[] m1 = clazz.getMethods(); for(Method m:m1) { Annotation[] an = m.getAnnotations(); for(Annotation a:an) { System.out.println(a); } }
2.權限修飾符
int a = m.getModifiers(); String str1 = Modifier.toString(a); System.out.print(str1+" ");
3.返回值類型
Class return1 = m.getReturnType(); System.out.print(return1+" ");
4.方法名
System.out.print(m.getName()+" ");
5.形參列表
System.out.print("("); Class[] params = m.getParameterTypes(); for(Class p : params) { System.out.print(p.getName()); } System.out.println(")"+" ");
6.拋的異常
Class[] ex = m.getExceptionTypes(); for(Class e:ex) { System.out.print(e.getName()); } // for(int i=0;i<ex.length;i++) { // System.out.print(ex[i].getName()); // }
@Test public void test5() throws Exception { Class clazz = Class.forName("com.atguigu.java.Person"); Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor c : cons) { System.out.println(c); } }
@Test public void test6() { Class clazz = Person.class; Class super1 = clazz.getSuperclass(); System.out.println(super1); }
@Test public void test7() { Class clazz = Person.class; Type type1 = clazz.getGenericSuperclass(); System.out.println(type1); }
@Test public void test8() { Class clazz = Person.class; Type type1 = clazz.getGenericSuperclass(); ParameterizedType param= (ParameterizedType)type1; Type[] ars = param.getActualTypeArguments(); System.out.println((Class)ars[0]); }
@Test public void test9() { Class clazz = Person.class; Class[] i = clazz.getInterfaces(); for(Class a:i) { System.out.println(a); } }
@Test public void test10() { Class clazz = Person.class; Package p = clazz.getPackage(); System.out.println(p); }
所有代碼以下:
package com.atguigu.java; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import org.junit.Test; /** * 經過反射獲取類的完整結構 * * @author MD * */ public class TestField { /** * 1.獲取運行時類的屬性 */ @Test public void test1() { Class clazz = Person.class; //1.getFields() 返回 :表示公共字段的 Field 對象的數組 // 只能獲取運行時類中以及父類中聲明的爲public的屬性 // Field[] fiels = clazz.getFields(); // for(int i=0;i<fiels.length;i++) { // System.out.println(fiels[i]); // } //2.getDeclaredFields() :獲取運行時類自己聲明的全部的屬性 Field[] fiels1 = clazz.getDeclaredFields(); for(int i=0;i<fiels1.length;i++) { System.out.println(fiels1[i].getName()); } //加強for循環 for(Field f:fiels1) { System.out.println(f.getName()); } } /** * 權限修飾符 變量類型 變量名 * 2.獲取屬性的各個部分的內容 * */ @Test public void tset2() { Class clazz = Person.class; Field[] field = clazz.getDeclaredFields(); for(Field i:field) { //1.獲取每一個屬性的權限修飾符 int a = i.getModifiers(); String str1 = Modifier.toString(a); System.out.print(str1+" "); //2.獲取屬性的變量類型 Class type = i.getType(); System.out.print(type+" "); //3.獲取屬性名 System.out.print(i.getName()); System.out.println(); } } /** * 3.獲取運行時類的方法 */ @Test public void test3() { Class clazz = Person.class; //1.getMethods() 獲取運行時類及其父類中全部聲明爲public的方法 // Method[] m1 = clazz.getMethods(); // for(Method m:m1) { // System.out.println(m); // } //2.getDeclaredMethods() 獲取運行時類自己聲明的全部的方法 Method[] methods = clazz.getDeclaredMethods(); for(int i=0;i<methods.length;i++) { System.out.println(methods[i]); } } /** * 4.獲取方法的各個部分的內容 * 註解 權限修飾符 返回值類型 方法名 形參列表 異常 * */ @Test public void test4() { Class clazz = Person.class; Method[] m1 = clazz.getMethods(); for(Method m:m1) { //1.註解 Annotation[] an = m.getAnnotations(); for(Annotation a:an) { System.out.println(a); } //2.權限修飾符 int a = m.getModifiers(); String str1 = Modifier.toString(a); System.out.print(str1+" "); //3.返回值類型 Class return1 = m.getReturnType(); System.out.print(return1+" "); //4.方法名 System.out.print(m.getName()+" "); //5.形參列表 System.out.print("("); Class[] params = m.getParameterTypes(); for(Class p : params) { System.out.print(p.getName()); } System.out.println(")"+" "); //6.拋的異常 Class[] ex = m.getExceptionTypes(); for(Class e:ex) { System.out.print(e.getName()); } // for(int i=0;i<ex.length;i++) { // System.out.print(ex[i].getName()); // } System.out.println(); } } /** * 5.獲取構造器 * @throws Exception */ @Test public void test5() throws Exception { Class clazz = Class.forName("com.atguigu.java.Person"); Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor c : cons) { System.out.println(c); } } /** * * 6.獲取運行時類的父類 */ @Test public void test6() { Class clazz = Person.class; Class super1 = clazz.getSuperclass(); System.out.println(super1); } /** * 7.獲取帶泛型的父類 */ @Test public void test7() { Class clazz = Person.class; Type type1 = clazz.getGenericSuperclass(); System.out.println(type1); } /** * 8.獲取父類的泛型 */ @Test public void test8() { Class clazz = Person.class; Type type1 = clazz.getGenericSuperclass(); ParameterizedType param= (ParameterizedType)type1; Type[] ars = param.getActualTypeArguments(); System.out.println((Class)ars[0]); } /** * 9.獲取實現的接口 */ @Test public void test9() { Class clazz = Person.class; Class[] i = clazz.getInterfaces(); for(Class a:i) { System.out.println(a); } } /** * 10.獲取所在的包 */ @Test public void test10() { Class clazz = Person.class; Package p = clazz.getPackage(); System.out.println(p); } }
1. 獲取指定的屬性
getField(String fieldName):獲取運行時類中聲明爲public的指定的屬性名爲fieldName的屬性
Field name = clazz.getField("name");
2.建立運行時類的對象
Person p = (Person) clazz.newInstance(); System.out.println(p);
3.將運行時類的指定屬性賦值
name.set(p, "Jerry"); System.out.println(p);
給age賦值,private須要注意
getDeclareField(String fieldName):獲取運行時類中指明爲filedName的屬性
Field age = clazz.getDeclaredField("age"); //因爲屬性權限修飾符的限制,爲了保證能夠給屬性賦值,須要在操做前使得此屬性可被操做 age.setAccessible(true);//私有的設置成能夠訪問的 age.set(p,1); System.out.println(p);
給id賦值,默認的修飾符
Field id = clazz.getDeclaredField("id"); id.set(p,10); System.out.println(p);
1.getMethod(String methodName,Class...params)獲取指定的public方法,方法名,參數列表
Class clazz = Person.class; Method m1 = clazz.getMethod("show");
2.建立運行時類的對象
Person p =(Person)clazz.newInstance();
3.和屬性類似,這裏是invoke關鍵字裏面是對象和參數列表,或許還有返回值,用Object接收
Object returnVal = m1.invoke(p); System.out.println(returnVal);//沒返回值的打印爲null
4.獲取toString()有返回值的
Method m2 = clazz.getMethod("toString"); Object returnVal1 = m2.invoke(p); System.out.println(returnVal1);
5.獲取display()帶參數的
Method m3 = clazz.getMethod("display",String.class); m3.invoke(p, "china");
6.獲取info()靜態的方法
Method m4 = clazz.getMethod("info"); m4.invoke(Person.class);
7.獲取Test() 私有的帶參數的有返回值的
Method m5 = clazz.getDeclaredMethod("Test",String.class,Integer.class); m5.setAccessible(true); Object o = m5.invoke(p,"測試",5); System.out.println(o);
public void test3() throws InstantiationException, Exception { Class clazz = Person.class; Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); cons.setAccessible(true); Person p = (Person)cons.newInstance("迪麗熱巴",20); System.out.println(p); }
所有代碼
package com.atguigu.java; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import org.junit.Test; /** * ******調用對應的運行時類的指定的結構(屬性、方法) * @author MD * */ public class TestField1 { /** * 調用運行時類指定的屬性 * @throws Exception * @throws NoSuchFieldException */ @Test public void test1() throws Exception { Class clazz = Person.class; //1.獲取指定的屬性 //getField(String fieldName):獲取運行時類中聲明爲public的指定的屬性名爲fieldName的屬性 Field name = clazz.getField("name"); //2.建立運行時類的對象 Person p = (Person) clazz.newInstance(); System.out.println(p); //3.將運行時類的指定屬性賦值 name.set(p, "Jerry"); System.out.println(p); //給age賦值,private須要注意 //getDeclareField(String fieldName):獲取運行時類中指明爲filedName的屬性 Field age = clazz.getDeclaredField("age"); //因爲屬性權限修飾符的限制,爲了保證能夠給屬性賦值,須要在操做前使得此屬性可被操做 age.setAccessible(true);//私有的設置成能夠訪問的 age.set(p,1); System.out.println(p); //給id賦值,默認的修飾符 Field id = clazz.getDeclaredField("id"); id.set(p,10); System.out.println(p); } /** * 調用運行時類中指定的方法 * @throws Exception * @throws NoSuchMethodException */ @Test public void test2() throws NoSuchMethodException, Exception { Class clazz = Person.class; //getMethod(String methodName,Class...params)獲取指定的public方法,方法名,參數列表 Method m1 = clazz.getMethod("show"); //建立運行時類的對象 Person p =(Person)clazz.newInstance(); //和屬性類似,這裏是invoke關鍵字裏面是對象和參數列表,或許還有返回值,用Object接收 Object returnVal = m1.invoke(p); System.out.println(returnVal); //獲取toString()有返回值的 Method m2 = clazz.getMethod("toString"); Object returnVal1 = m2.invoke(p); System.out.println(returnVal1); //獲取display()帶參數的 Method m3 = clazz.getMethod("display",String.class); m3.invoke(p, "china"); //獲取info()靜態的方法 Method m4 = clazz.getMethod("info"); m4.invoke(Person.class); //獲取Test() 私有的帶參數的有返回值的 Method m5 = clazz.getDeclaredMethod("Test",String.class,Integer.class); m5.setAccessible(true); Object o = m5.invoke(p,"測試",5); System.out.println(o); } /** * 調用指定的構造器,建立類對象 * @throws Exception * @throws InstantiationException */ @Test public void test3() throws InstantiationException, Exception { Class clazz = Person.class; Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); cons.setAccessible(true); Person p = (Person)cons.newInstance("迪麗熱巴",20); System.out.println(p); } }
類加載器是用來把類(class)裝載進內存
1.獲取一個系統類加載器
ClassLoader loader1 = ClassLoader.getSystemClassLoader(); System.out.println(loader1);
2.獲取系統類加載器的父類加載器,即擴展類加載器
ClassLoader loader2 = loader1.getParent(); System.out.println(loader2);
3.獲取擴展類加載器的父類加載器,即引導類加載器,加載的是核心庫,打印爲null
ClassLoader loader3 = loader2.getParent(); System.out.println(loader3);
4.測試當前類由哪一個類加載器進行加載
Class clazz1 = Person.class; ClassLoader loader4 = clazz1.getClassLoader(); System.out.println(loader4);//系統類加載器
JVM中類的裝載是由ClassLoader和它的子類來實現的,
Java ClassLoader 是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。