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实例中)
}
}