背景说明

  • 今天,在对在子类中调用getClass().getName()以及调用super.getClass().getName()的结果有点迷惑(获取的都是子类的字符串名称)
  • 因此,结合示例代码来分析分析

    调用方式

  • getClass().getName():直接在子类中调用

  • super.getClass().getName():直接在子类中调用
  • super.getDogClassName():调用父类中的方法,父类中该方法使用了 getClass().getName()
  • getClass().getSuperclass().getName():调用Class类中的getSuperclass()来获取父类名称

示例代码

  1. /**
  2. * 定义超类Dog
  3. */
  4. class Dog {
  5. public String getDogClassName() {
  6. return getClass().getName();
  7. }
  8. }
  9. /**
  10. * 定义子类SmallDog
  11. */
  12. class SmallDog extends Dog {
  13. public String getClassName() {
  14. return getClass().getName();
  15. }
  16. public String getSuperClassName() {
  17. return super.getClass().getName();
  18. }
  19. public String getSuperDogClassName() {
  20. return super.getDogClassName();
  21. }
  22. public String getClassSuperName() {
  23. return getClass().getSuperclass().getName();
  24. }
  25. }
  26. public class Test {
  27. public static void main(String[] args) {
  28. SmallDog dog = new SmallDog();
  29. // 打印:SmallDog
  30. System.out.println(dog.getClassName());
  31. // 打印:SmallDog
  32. System.out.println(dog.getSuperClassName());
  33. // 打印:SmallDog
  34. System.out.println(dog.getSuperDogClassName());
  35. // 打印:Dog
  36. System.out.println(dog.getClassSuperName());
  37. }
  38. }

场景结果

  • 1)当子类中直接调用getClass().getName()时:
    • 获取的是子类名称字符串SmallDog
  • 2)当子类中直接调用super.getClass().getName()时:
    • 获取的仍然是子类名称字符串SmallDog
  • 3)当子类调用父类中的方法super.getDogClassName()时:
    • 获取的还是子类名称字符串SmallDog
  • 4)当子类中调用getClass().getSuperclass().getName()时:

    • 获取到的是它的父类名称字符串Dog

      分析

  • getClass()方法归根结底,是所有类的超类Object定义的

    • public final native Class<?> getClass();
  • 这个方法一开始就被定义为final方法,任何子类都不可以将其覆盖
  • 从继承关系上来看,子类getClass方法继承关系为:子类继承于父类,父类继承于父类的父类,以此类推,最终继承于Object类
  • 可知,子类中的getClass方法来自于Object类
  • 另外,因为此方法来源于 继承 ,而子类继承父类可以理解为:子类拷贝了一份父类的域或方法 (但不可见) 【注意,只是辅助理解,不代表底层具体实现方式】
  • 那么,在子类中使用 super 关键字来调用父类中的方法便可以理解为:调用从父类中拷贝的方法,其本质上还是调用子类内部方法
  • 因此,场景1、2、3的结果都是一样的,都等价于在子类中直接调用getClass().getName()方法,结果一致

又如何正确地获取父类名称字符串呢

  • 在getClass()获取到Class类后,直接调用getSuperclass().getName()方法即可:getClass().getSuperclass().getName()