Saul's blog Saul's blog
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)

Saul.J.Wu

立身之本,不在高低。
首页
后端
分布式
前端
更多
分类
标签
归档
友情链接
关于
GitHub (opens new window)
  • Java入门基础

  • Java核心基础

    • 多线程

    • Java常用类

    • 枚举类与注解

    • Java集合

    • 数据结构与算法

    • 泛型

    • IO流

    • 网络编程

    • 反射

      • 反射概述
      • Class类
      • 类加载器
      • 访问字段
      • 调用方法
      • 调用构造方法
      • 获取继承关系
        • 获取父类的Class
        • 获取interface
        • 继承关系
        • 小结
      • 动态代理
    • 函数式编程

  • 设计模式

  • Web开发

  • SpringBoot

  • 微服务

  • Elasticsearch

  • 运维

  • 后端
  • Java核心基础
  • 反射
SaulJWu
2021-01-12

获取继承关系

当我们获取到某个Class对象时,实际上就获取到了一个类的类型:

Class cls = String.class; // 获取到String的Class
1

还可以用实例的getClass()方法获取:

String s = "";
Class cls = s.getClass(); // s是String,因此获取到String的Class
1
2

最后一种获取Class的方法是通过Class.forName(""),传入Class的完整类名获取:

Class s = Class.forName("java.lang.String");
1

这三种方式获取的Class实例都是同一个实例,因为JVM对每个加载的Class只创建一个Class实例来表示它的类型。

# 获取父类的Class

有了Class实例,我们还可以获取它的父类的Class:

public class Main {
    public static void main(String[] args) throws Exception {
        Class i = Integer.class;
        Class n = i.getSuperclass();
        System.out.println(n);
        Class o = n.getSuperclass();
        System.out.println(o);
        System.out.println(o.getSuperclass());
    }
}
1
2
3
4
5
6
7
8
9
10

运行上述代码,可以看到,Integer的父类类型是Number,Number的父类是Object,Object的父类是null。除Object外,其他任何非interface的Class都必定存在一个父类类型。

# 获取interface

由于一个类可能实现一个或多个接口,通过Class我们就可以查询到实现的接口类型。例如,查询Integer实现的接口:

public class Main {
    public static void main(String[] args) throws Exception {
        Class s = Integer.class;
        Class[] is = s.getInterfaces();
        for (Class i : is) {
            System.out.println(i);
        }
    }
}
1
2
3
4
5
6
7
8
9

运行结果:

interface java.lang.Comparable
interface java.lang.constant.Constable
interface java.lang.constant.ConstantDesc
1
2
3

运行上述代码可知,Integer实现的接口有:

  • java.lang.Comparable
  • java.lang.constant.Constable
  • java.lang.constant.ConstantDesc

要特别注意:getInterfaces()只返回当前类直接实现的接口类型,并不包括其父类实现的接口类型:

public class Main {
    public static void main(String[] args) throws Exception {
        Class s = Integer.class.getSuperclass();
        Class[] is = s.getInterfaces();
        for (Class i : is) {
            System.out.println(i);
        }
    }
}
1
2
3
4
5
6
7
8
9

运行结果:

interface java.io.Serializable
1

Integer的父类是Number,Number实现的接口是java.io.Serializable。

此外,对所有interface的Class调用getSuperclass()返回的是null,获取接口的父接口要用getInterfaces():

System.out.println(java.io.DataInputStream.class.getSuperclass()); // java.io.FilterInputStream,因为DataInputStream继承自FilterInputStream
System.out.println(java.io.Closeable.class.getSuperclass()); // null,对接口调用getSuperclass()总是返回null,获取接口的父接口要用getInterfaces()
1
2

如果一个类没有实现任何interface,那么getInterfaces()返回空数组。

# 继承关系

当我们判断一个实例是否是某个类型时,正常情况下,使用instanceof操作符:

Object n = Integer.valueOf(123);
boolean isDouble = n instanceof Double; // false
boolean isInteger = n instanceof Integer; // true
boolean isNumber = n instanceof Number; // true
boolean isSerializable = n instanceof java.io.Serializable; // true
1
2
3
4
5

如果是两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom():

// Integer i = ?
Integer.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Integer
// Number n = ?
Number.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Number
// Object o = ?
Object.class.isAssignableFrom(Integer.class); // true,因为Integer可以赋值给Object
// Integer i = ?
Integer.class.isAssignableFrom(Number.class); // false,因为Number不能赋值给Integer
1
2
3
4
5
6
7
8

# 小结

通过Class对象可以获取继承关系:

  • Class getSuperclass():获取父类类型;
  • Class[] getInterfaces():获取当前类实现的所有接口。

通过Class对象的isAssignableFrom()方法可以判断一个向上转型是否可以实现。

帮我改善此页面 (opens new window)
上次更新: 2021/01/20, 05:46:57
调用构造方法
动态代理

← 调用构造方法 动态代理→

最近更新
01
zabbix学习笔记二
02-28
02
zabbix学习笔记一
02-10
03
Linux访问不了github
12-08
更多文章>
Theme by Vdoing | Copyright © 2020-2022 Saul.J.Wu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式