手機直播原始碼,Android Studio使用者登入及驗證
阿新 • • 發佈:2022-05-16
指在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法,對於任意一個物件,都能呼叫它的任意一個方法.這種動態獲取資訊,以及動態呼叫物件方法的功能叫java語言的反射機制.
反射機制常用的類:
Java.lang.Class; //代表一個類
Java.lang.reflect.Constructor; //代表類的構造器
Java.lang.reflect.Field; //代表類的成員變數
Java.lang.reflect.Method; //代表類的方法
Java.lang.reflect.Modifier;
反射的基本使用:
不使用反射的處理:
1 public classPerson { 2 private String name; 3 public int age; 4 5 public String getName() { 6 return name; 7 } 8 9 public void setName(String name) { 10 this.name = name; 11 } 12 13 public int getAge() { 14 return age; 15 } 16 17 public voidsetAge(int age) { 18 this.age = age; 19 } 20 21 public Person(String name, int age) { 22 this.name = name; 23 this.age = age; 24 } 25 26 private Person(String name) { 27 this.name = name; 28 } 29 public Person(){ 30 31 } 32 33 @Override34 public String toString() { 35 return "Person{" + 36 "name='" + name + '\'' + 37 ", age=" + age + 38 '}'; 39 } 40 public void show(){ 41 System.out.println("hello"); 42 } 43 private String showNation(String nation){ 44 System.out.println("中國"); 45 return nation; 46 } 47 }
使用反射機制:
1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.Method; 4 5 public class ReflectTest { 6 /** 7 * 不使用反射的情況 8 */ 9 @Test 10 public void test01(){ 11 Person person = new Person("jack",20); 12 person.age=15; 13 System.out.println(person.toString()); 14 person.show(); 15 //在Person類的外部,不可以通過Person類的物件呼叫其內部私有的結構。 16 //比如:name、showNation以及私有的構造器。 17 } 18 19 /** 20 * 使用反射的情況 21 */ 22 @Test 23 public void test02() throws Exception { 24 //1.通過反射,建立Person類的物件 25 Class clazz = Person.class; 26 Constructor cons = clazz.getConstructor(String.class,int.class); 27 Object obj = cons.newInstance("john",21); 28 Person person = (Person) obj; 29 System.out.println(person.toString()); 30 //2.通過反射,呼叫物件指定的屬性和方法 31 //呼叫屬性 32 Field age = clazz.getDeclaredField("age"); 33 age.set(person,11); 34 System.out.println(person.toString()); 35 //呼叫方法 36 Method show = clazz.getDeclaredMethod("show"); 37 show.invoke(person); 38 System.out.println("============"); 39 //通過反射,是可以呼叫Person類的私有結構的。比如:私有的構造器、方法、屬性 40 //呼叫私有的構造器 41 Constructor constructor = clazz.getDeclaredConstructor(String.class); 42 constructor.setAccessible(true); 43 Person p = (Person) constructor.newInstance("kk"); 44 System.out.println(p); 45 //呼叫私有的屬性 46 Field name = clazz.getDeclaredField("name"); 47 name.setAccessible(true); 48 name.set(p,"zz"); 49 System.out.println(p); 50 51 //呼叫私有的方法 52 Method showNation = clazz.getDeclaredMethod("showNation",String.class); 53 showNation.setAccessible(true); 54 String nation = (String) showNation.invoke(p,"china"); 55 // 相當於String nation = p1.showNation("FaceBook") 56 System.out.println(nation); 57 58 } 59 60 }
理解Class類並獲取Class例項
關於java.lang.Class類的理解
類的載入過程:
1.程式經過Javac.exe命令後,會生成一個或多個位元組碼檔案(.class結尾)。接著我們使用java.exe命令對某個位元組碼檔案進行解釋執行。相當於將某個位元組碼檔案載入到記憶體中。此過程就稱為類的載入。載入到記憶體中的類,我們就稱為執行時類,此執行時類,就作為Class的一個例項。
2.換句話說,Class的例項就對應著一個執行時類。
3.載入到記憶體中的執行時類,會快取一定的個時間。在此時間內,我們可以通過不同的方式來獲取此執行時類。
獲取class例項的方式
1 import org.junit.Test; 2 3 import java.lang.annotation.ElementType; 4 import java.lang.reflect.Constructor; 5 import java.lang.reflect.Field; 6 import java.lang.reflect.Method; 7 8 public class ReflectionTest { 9 10 @Test 11 public void test3() throws ClassNotFoundException { 12 //方式一:呼叫執行時類的屬性 13 Class c1 = Person.class; 14 System.out.println(c1); 15 16 //方式二:通過執行時類的物件,呼叫getClass() 17 Person p1 = new Person(); 18 Class c2 = p1.getClass(); 19 System.out.println(c2); 20 21 //方式三:呼叫Class的靜態方法:forName(String classPath) 22 Class c3 = Class.forName("java.lang.String"); 23 System.out.println(c3); 24 25 System.out.println(c1 == c2); 26 System.out.println(c1 == c3); 27 28 //方式四:使用類的載入器:ClassLoader (瞭解) 29 ClassLoader classLoader = ReflectionTest.class.getClassLoader(); 30 Class c4 = classLoader.loadClass("java.lang.String"); 31 System.out.println(c4); 32 33 System.out.println(c1 == c4); 34 } 35 }
哪些型別可以有Class物件
class
:外部類, 成員(成員內部類, 靜態內部類), 區域性內部類, 匿名內部類interface
: 介面[]
:陣列enum
:列舉annotation
:註解@interface
primitive type
:基本資料型別void
使用ClassLoader載入配置檔案
1 import org.junit.Test; 2 3 import java.io.FileInputStream; 4 import java.io.InputStream; 5 import java.util.Properties; 6 7 public class PropertiesTest { 8 @Test 9 public void test01() throws Exception{ 10 Properties properties = new Properties(); 11 //讀取配置檔案的方式一,此時檔案路徑預設在當前的module下 12 //FileInputStream fileInputStream = new FileInputStream("jdbc.properties"); 13 //FileInputStream fileInputStream = new FileInputStream("src/jdbc1.properties"); 14 //properties.load(fileInputStream); 15 16 //讀取配置檔案的方式2,此時檔案路徑預設識別為當前module下的src 17 ClassLoader classLoader = ClassLoadingTest.class.getClassLoader(); 18 InputStream resourceAsStream = classLoader.getResourceAsStream("jdbc1.properties"); 19 properties.load(resourceAsStream); 20 21 String user = properties.getProperty("user"); 22 String password = properties.getProperty("password"); 23 System.out.println("user=:"+user+";passward:"+password); 24 } 25 }
通過Class物件,建立執行時類的物件,通過呼叫Class物件的newInstance()方法
1 import org.junit.Test; 2 import pers.chh3213.reflectionDemo.Person; 3 4 public class NewInstanceTest { 5 6 @Test 7 public void test() throws Exception{ 8 Class<Person> clazz = Person.class; 9 /** 10 * newInstance():呼叫此方法,建立對應的執行時類的物件。內部呼叫了執行時類的空參的構造器。 11 * 12 * 要想此方法正常的建立執行時類的物件,要求: 13 * 1.執行時類必須提供空參的構造器 14 * 2.空參的構造器的訪問許可權得夠。通常,設定為public。 15 * 16 * 在javabean中要求提供一個public的空參構造器。原因: 17 * 1.便於通過反射,建立執行時類的物件 18 * 2.便於子類繼承此執行時類時,預設呼叫super()時,保證父類有此構造器 19 */ 20 Person obj = clazz.newInstance(); 21 System.out.println(obj); 22 } 23 24 }
反射機制的動態性體現
1 import org.junit.Test; 2 3 import java.util.Random; 4 5 public class NewInstanceTest2 { 6 @Test 7 public void test2(){ 8 for (int i = 0; i < 100; i++) { 9 int num = new Random().nextInt(3); 10 String classpath = ""; 11 switch (num){ 12 case 0: 13 classpath = "java.util.Date"; 14 break; 15 case 1: 16 classpath = "java.lang.Object"; 17 break; 18 case 2: 19 classpath = "pers.chh3213.reflectionDemo.Person"; 20 break; 21 } 22 try { 23 Object obj = getInstance(classpath); 24 System.out.println(obj); 25 }catch (Exception e){ 26 e.printStackTrace(); 27 } 28 } 29 30 } 31 /** 32 * 建立一個指定類的物件。 33 * classPath:指定類的全類名 34 * 35 * @param classPath 36 * @return 37 * @throws Exception 38 */ 39 public Object getInstance(String classPath) throws Exception { 40 Class clazz = Class.forName(classPath); 41 return clazz.newInstance(); 42 } 43 }
具體建立哪個類的物件,直到執行時才能確定
參考部落格:https://blog.csdn.net/weixin_42301220/article/details/122639224