import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.spec.ECField;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Ans {
public static void main(String[] args) throws Exception {
test0();
test1();
test2();
test3();
test4();
}
static void test0() throws ClassNotFoundException {
//Class類是final的,而且它的構造函數是private的,所以只有JVM可以構建Class
//JVM是動態加載的,即使用到某個類時才加載,這也就是爲什麼把Log4j放入路徑後可以自動使用,否則會使用Commons Logging。因爲如果沒有Log4j存在於路徑中,就檢測不到這個類,也就不用加載
Class cl = String.class,cl2 = ("").getClass(); //這個是兩種常見的方式得到class
Class cl3 = Class.forName("java.lang.String"); //這是第三種
System.out.println(cl==cl2); //這裏是true,因爲每個類只有唯一的Class所以不管怎麼得到Class都是一個對象,所以相等
}
static void test1() {
//在用反射得到Field或者Method時,不帶Declared是包含其父類的所有public成員,帶Declared是不包含父類的所有成員(這裏不只限於public)
//雖然getField可以得到private的域,但是我們不能對其進行訪問,否則會出現IllegalAccessException,只有使用setAccessible
//使用setAccessible時可能因爲JVM運行時存在的SecurityManager而出錯,有時SecurityManager會阻止對java,javax中域的setAccessible操作
System.out.println(Ans.class.getModifiers()); //這個getModifiers是對類型的一種編碼,用一個int的不同位來表示其屬性(public,private,static,final...),詳情可見:https://blog.csdn.net/qq_39385118/article/details/83757536
}
static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//對於方法的使用與test1中對域的使用基本相同
//有一點,當使用父類的class調用子類的重寫函數時,依然遵守多態原則,調用的是子類的函數
class A {void a() {System.out.println("a");}}
class B extends A {void a() {System.out.println("b");}}
Method m = A.class.getDeclaredMethod("a");
m.invoke(new B());
}
static void test3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//java SE9之前Class.newInstance只能調用默認的public無參數構造方法,如果需要調用其他構造方法則需要Constructor.newInstance
//但是在java SE9中刪除了Class.newInstance,而可以使用getConstructor和getDeclaredConstructor去構建對象,而對Declared的用法相似於getDeclaredMethod,具體用法如下
class A {
A() {System.out.println("unpublic");}
A(int i) {System.out.println("int");}
}
class B {
public B() {System.out.println("public");}
public B(int i) {System.out.println("public int");}
}
A.class.getDeclaredConstructor().newInstance();
//!A.class.getConstructor().newInstance(); 這兩步中構造函數不是public,所以必須加Declared
A.class.getDeclaredConstructor(int.class).newInstance(1);
B.class.getConstructor().newInstance();
B.class.getConstructor(int.class).newInstance(1); //而這裏可以
}
static void test4() {
//可以使用getSuperClass獲得父類,除了Object父類爲null,其他都有父類(除了interface外(interface也是class))
//查詢實現的接口應該調用getInterfaces
//對任何沒有繼承接口的interface調用getSuperClass會返回null
//getInterfaces不會返回父類實現的接口
System.out.println(Object.class.getSuperclass());
System.out.println(Integer.class.getSuperclass());
System.out.println(Arrays.toString(ArrayList.class.getInterfaces()));
System.out.println(Arrays.toString(List.class.getInterfaces()));
//爲了判斷一個向上轉型是否成立可以使用isAssignableFrom
System.out.println(Object.class.isAssignableFrom(Integer.class));
System.out.println(Integer.class.isAssignableFrom(Object.class));
}
static void test5() {
//對於動態代理,blog中講的比較淺,可以參考java編程思想裏面有非常詳細的解釋
//Proxy.newProxyInstance中需要傳入一個classLoader,一個接口列表,一個InvocationHandler實例(代理的調用函數invoke就實現在這個InvocationHandler實例中)
}
}