(一)Class的getSuperclass与getGenericSuperclass区别

getSuperclass 返回直接继承的父类 (没有显示泛型参数)
Class<? super T>**getSuperclass**()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。如果Class 表示 Object 类、一个接口、一个基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示该 Object 类的 Class 对象。

getGenericSuperclass 返回直接继承的父类(包含泛型参数)
Type **[getGenericSuperclass]()**()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type。如果此 Class 表示 Object 类、接口、基本类型或 void,则返回 null。如果此对象表示一个数组类,则返回表示 Object 类的 Class 对象。

  1. /**
  2. * @author heian
  3. * @create 2020-07-07-7:48 下午
  4. * @description
  5. */
  6. public class Test {
  7. public static void main(String[] args) {
  8. //com.tz.campus.controller.Person
  9. System.out.println("Student.class.getSuperclass()\t" + Student.class.getSuperclass());
  10. //com.tz.campus.controller.Person<com.tz.campus.controller.Test>
  11. System.out.println("Student.class.getGenericSuperclass()\t" + Student.class.getGenericSuperclass());
  12. //java.lang.Object
  13. System.out.println("Test.class.getSuperclass()\t" + Test.class.getSuperclass());
  14. //java.lang.Object
  15. System.out.println("Test.class.getGenericSuperclass()\t" + Test.class.getGenericSuperclass());
  16. //null
  17. System.out.println("Object.class.getGenericSuperclass()\t" + Object.class.getGenericSuperclass());
  18. //null
  19. System.out.println("Object.class.getSuperclass()\t" + Object.class.getSuperclass());
  20. //null
  21. System.out.println("void.class.getSuperclass()\t" + void.class.getSuperclass());
  22. //null
  23. System.out.println("void.class.getGenericSuperclass()\t" + void.class.getGenericSuperclass());
  24. //java.lang.Object
  25. System.out.println("int[].class.getSuperclass()\t" + int[].class.getSuperclass());
  26. //java.lang.Object
  27. System.out.println("int[].class.getGenericSuperclass()\t" + int[].class.getGenericSuperclass());
  28. }
  29. }
  30. class Person<T> {
  31. }
  32. class Student extends Person<Test> {
  33. }

jdk动态代理实际应用举例

假设我们有一个接口有两个常用的业务方法,现在有100子类都实现此接口并且复写了这两个常用的方法,但是因为产品改需求,需要在调用这两个方法前加上前置和一个后置,如果你要改代码一般蠢得做法是修改这两个实现方法的其中,代码侵入性很强。所以一般做法是通过spring的aop实现,现在我们通过jdk的动态代理原生实现下。
image.png

  1. //要在狗吃东西之前加上 发出命令 和 获得奖励
  2. public class Dog implements Animals {
  3. public void eat() {
  4. System.out.println("狗吃东西");
  5. }
  6. public void run() {
  7. System.out.println("狗吃跑");
  8. }
  9. }
  1. //要在狗吃东西之前加上 发出命令 和 获得奖励
  2. public class Dog implements Animals {
  3. public void eat() {
  4. System.out.println("狗吃东西");
  5. }
  6. public void run() {
  7. System.out.println("狗吃跑");
  8. }
  9. }
  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.InvocationTargetException;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Proxy;
  5. /**
  6. * 代理类具体的执行逻辑
  7. */
  8. public class AnimalsProxyInvocationHandler implements InvocationHandler {
  9. private Object target;
  10. public AnimalsProxyInvocationHandler(Object target) {
  11. this.target = target;
  12. }
  13. public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
  14. System.out.println("主任发出命令");//前置
  15. Object invoke = method.invoke(target,args);//返回执行方法的结果
  16. System.out.println("获得奖励");//后置
  17. return invoke;
  18. }
  19. public static void main(String[] args) {
  20. //目标类必须实现接口否则会抛出类转化异常
  21. Animals dogTarget = new Dog();
  22. //类加载器、代理类的接口数组(Dog类实现接口的数组)、代理业务类
  23. Animals proxy = (Animals)Proxy.newProxyInstance(dogTarget.getClass().getClassLoader(), dogTarget.getClass().getInterfaces(),
  24. new AnimalsProxyInvocationHandler(dogTarget));
  25. //重新生成一个子类进行接口方法的调用
  26. proxy.eat();
  27. }
  28. }