Java Type 类型

Type 只在反射中才有真正的意义,表示 Java 中所有类型的公共父接口。它包含:原始类型、参数化类型、数组类型、类型变量和基础数据类型。

Java 语言规范中指出变量只有下面三种类型 JLS

  • 基本类型 primitive typesboolean, byte, short, int, long, char, float, double
  • 引用类型 reference typesclass, interface, array, type variables
  • 空类型 null type

关于泛型和语言规范中三种类型的关系如下:

  • 如果类或接口声明了类型变量,那么它就是泛型
  • 类和接口如果是泛型,那么它就定义了一个参数化类型,简单理解为泛型就是参数化类型。但是参数化类型是属于类类型或者接口类型的
  • 参数化类型的参数 Type Arguments of Parameterized Types:可以是引用类型和通配符

在学习 Type 及子接口或实现类时,很容易将它们和语言规范中的类型混淆。语言规范简单来讲类型分为:基本数据类型,类类型(包含接口),数组(另外算上一个类型变量)。总是在想:为什么会多出 Type 这几种类型?它们和基本语言规范中类型的区别是什么呢?实际上从语言规范中的类型来讲,它们是标准的类类型(包含接口),只有在反射解析变量时,它们才有实际的意义,用来区分泛型的几种情景。

类图结构

0079-Type-uml-classdiag.png

Type 基本概念

Type 的引入主要是为了反射和泛型服务的,它能代表一切类型。在编码使用中(抛开反射概念),这几种类型是标准的类类型和接口类型;它们只能在反射中才能体现真正的意义,能代表泛型的几种细分场景:

  • Type
    表示 Java 中所有类型的公共接口。也就是反射Type 代表 Java 语言规范中的所有类型。
  • TypeVariable
    表示类型变量,即泛型中的 T, K, V 等等。
  • ParameterizedType
    表示参数化类型,即泛型,如:Collection<String>
  • GenericArrayType
    表示数组中的:参数化类型数组,类型变量数组,如:Collection<String>[], T[] 。并不包含基本类型和类类型数组。
  • WildcardType
    表示通配符类型表达式,如 ?? extends Number? super Integer 。它只是参数化类型中参数的一种类型,无法直接修饰变量。
  • Class
    它是 Type 的实现类,表示除了上面泛型中的几个特定类型之外的所有类型,包含基本数据类型,引用类型等。每个类在加载后都会对应一个 Class 类对象,它包含了 .class 文件转换为内存运行时数据结构,也就是包含类中的一切信息。参考:类加载机制

Class 对象是否反射的基石,在 Java 中使用 类名.clas 表示类对象。如:String.class, Object.class 等等。

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* Type is the common superinterface for all types in the Java
* programming language. These include raw types, parameterized types,
* array types, type variables and primitive types.
*
* @since 1.5
*/
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}

/**
* ParameterizedType represents a parameterized type
* such as Collection<String>.
*/
public interface ParameterizedType extends Type {
// 返回参数化类的,参数数组
Type[] getActualTypeArguments();

// 返回泛型类或者接口的原始类型
Type getRawType();

// getRawType 返回泛型如果为顶级类,则返回空;如果是内部类,则返回外部类
Type getOwnerType();
}

// TypeVariable is the common superinterface for type variables of kinds.
public interface TypeVariable<D extends GenericDeclaration>
extends Type, AnnotatedElement {
// 类型变量的上界
Type[] getBounds();

// 声明这个类型变量的泛型类
D getGenericDeclaration();

// 类型变量使用的名字
String getName();

// 1.8 添加的方法,返回 AnnotatedType 数组
AnnotatedType[] getAnnotatedBounds();
}

/**
* GenericArrayType represents an array type whose component type
* is either a parameterized type or a type variable.
*/
public interface GenericArrayType extends Type {
// 泛型数组元素类型
Type getGenericComponentType();
}

/**
* WildcardType represents a wildcard type expression,
* such as ?, ? extends Number, or ? super Integer.
*/
public interface WildcardType extends Type {
// 获取通配符上界
Type[] getUpperBounds();

// 获取通配符下界
Type[] getLowerBounds();
}

/**
* Instances of the class Class represent classes and interfaces
* in a running Java application.
*/
public final class Class<T> implements Serializable,
GenericDeclaration, Type, AnnotatedElement {...}

示例

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
public class TestType {

private void testParameterizedType(){
class ParameterizedTypeTestClass{
List<String> list;
Map.Entry<Integer, String> entry;
Class<?> clazz;
}
showTypeDetails(ParameterizedTypeTestClass.class);
}

private void testTypeVariable(){
class TypeVariableTestClass<K extends Runnable, V> {
K k;
V v;
List<K> list;
}
showTypeDetails(TypeVariableTestClass.class);
}

private void testGenericArrayType(){
class GenericArrayTypeTestClass<T>{
List<String>[] lists;
T[] ts;
}
showTypeDetails(GenericArrayTypeTestClass.class);
}

private void testWildcardType(){
class WildcardTypeTestClass{
List<? extends Number> numbers;
List<? super Integer> list;
}
showTypeDetails(WildcardTypeTestClass.class);
}

private void testAllTypes(){
class AllTypes{
int i;
boolean b;
float f;
byte[] bytes;
String s;
Object o;
Runnable runnable;
Object[] os;
}
showTypeDetails(AllTypes.class);
}

private void showTypeDetails(Class<?> clazz){
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields){
System.out.println("*************************");
System.out.println("showTypeDetails: " + clazz);
System.out.println("Field: " + field);
Type type = field.getGenericType();
System.out.println("TypeName: " + type.getTypeName());
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType =(ParameterizedType)type;
System.out.println("ParameterizedType--RawType: "
+ parameterizedType.getRawType());
System.out.println("ParameterizedType--OwnerType: "
+ parameterizedType.getOwnerType());
Type[] types = parameterizedType.getActualTypeArguments();
System.out.println("ParameterizedType--Args.length = "
+ types.length);
for (Type t : types){
System.out.println("ParameterizedType--ActualTypeArguments: "
+ t);
if (t instanceof WildcardType){
WildcardType wildcardType = (WildcardType) t;
Type[] uppers = wildcardType.getUpperBounds();
System.out.println("WildcardType--uppers.length = "
+ uppers.length);
for (Type t1 : uppers) {
System.out.println("WildcardType--uppers, type ="
+ t1);
}
Type[] lowers = wildcardType.getLowerBounds();
System.out.println("WildcardType--lowers.length = "
+ lowers.length);
for (Type t2 : lowers){
System.out.println("WildcardType--lowers. type ="
+ t2);
}
}
}
} else if (type instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) type;
Type[] types = typeVariable.getBounds();
System.out.println("TypeVariable--Bounds.length = "
+ types.length);
for (Type t : types){
System.out.println("TypeVariable--Bounds = " + t);
}
System.out.println("TypeVariable--GenericDeclaration = "
+ typeVariable.getGenericDeclaration());
System.out.println("TypeVariable--Name = "
+ typeVariable.getName());
} else if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType) type;
System.out.println("GenericArrayType--ComponentType: "
+ genericArrayType.getGenericComponentType());
} else if (type instanceof Class) {
System.out.println("Class--SimpleName = "
+ ((Class) type).getSimpleName());
}
}
}

public static void main(String[] args) {
TestType testType = new TestType();
testType.testParameterizedType();
testType.testTypeVariable();
testType.testGenericArrayType();
testType.testWildcardType();
}
}

源码解析:

  • 反射后的字段类型
    只有四种:ParameterizedType, TypeVariable, GenericArrayType, Class,它们的公共父接口为 Type
  • 反射后参数化类型的参数
    类型为:通配符 WildcardType 和上面四种类型。
    1
    2
    3
    4
    5
    6
    Class<?> clazz;                     // WildcardType
    List<? extends Number> numbers; // WildcardType
    List<List<String>> listList; // ParameterizedType
    List<K> listK; // TypeVariable
    List<V[]> listVArray; // GenericArrayType
    List<String> list; // Class

结果分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
*************************
// 传入的类名为 TestType 的内部类 1ParameterizedTypeTestClass
showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass
// 获取的字段为 list,类型为:参数化类型 List<String>,
// 其原始类型为 List,参数为 String
Field: java.util.List com.***.TestType$1ParameterizedTypeTestClass.list
TypeName: java.util.List<java.lang.String>
ParameterizedType--RawType = interface java.util.List
ParameterizedType--OwnerType = null
ParameterizedType--Args.length = 1
ParameterizedType--ActualTypeArguments = class java.lang.String
*************************
showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass
Field: java.util.Map$Entry com.***.TestType$1ParameterizedTypeTestClass.entry
TypeName: java.util.Map.java.util.Map$Entry<java.lang.Integer, java.lang.String>
ParameterizedType--RawType = interface java.util.Map$Entry
ParameterizedType--OwnerType = interface java.util.Map
ParameterizedType--Args.length = 2
ParameterizedType--ActualTypeArguments = class java.lang.Integer
ParameterizedType--ActualTypeArguments = class java.lang.String
*************************
showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass
// 获取的字段为 clazz,类型为:参数化类型 Class<?>
Field: java.lang.Class com.***.TestType$1ParameterizedTypeTestClass.clazz
TypeName: java.lang.Class<?>
ParameterizedType--RawType = class java.lang.Class
ParameterizedType--OwnerType = null
ParameterizedType--Args.length = 1
ParameterizedType--ActualTypeArguments = ?
// 其参数为通配符类型
WildcardType--uppers.length = 1
WildcardType--uppers, type = class java.lang.Object
WildcardType--lowers.length = 0
*************************
// 内部类持有外部类的引用
showTypeDetails: class com.***.TestType$1ParameterizedTypeTestClass
Field: final com.***.TestType com.***.TestType$1ParameterizedTypeTestClass.this$0
TypeName: com.***.TestType
Class--SimpleName = TestType
*************************
showTypeDetails: class com.***.TestType$1TypeVariableTestClass
// 获取的字段为 k,类型为:类型变量 K
Field: java.lang.Runnable com.***.TestType$1TypeVariableTestClass.k
TypeName: K
TypeVariable--Bounds.length = 1
TypeVariable--Bounds = interface java.lang.Runnable
TypeVariable--GenericDeclaration = class com.***.TestType$1TypeVariableTestClass
TypeVariable--Name = K
*************************
showTypeDetails: class com.***.TestType$1TypeVariableTestClass
Field: java.lang.Object com.***.TestType$1TypeVariableTestClass.v
TypeName: V
TypeVariable--Bounds.length = 1
TypeVariable--Bounds = class java.lang.Object
TypeVariable--GenericDeclaration = class com.***.TestType$1TypeVariableTestClass
TypeVariable--Name = V
*************************
showTypeDetails: class com.***.TestType$1TypeVariableTestClass
Field: java.util.List com.***.TestType$1TypeVariableTestClass.list
TypeName: java.util.List<K>
ParameterizedType--RawType = interface java.util.List
ParameterizedType--OwnerType = null
ParameterizedType--Args.length = 1
ParameterizedType--ActualTypeArguments = K
*************************
showTypeDetails: class com.***.
TestType$1TypeVariableTestClass
Field: final com.***.TestType com.***.TestType$1TypeVariableTestClass.this$0
TypeName: com.***.TestType
Class--SimpleName = TestType
*************************
showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass
// 获取字段为 lists,类型为:泛型数组 List<String>[]
Field: java.util.List[] com.***.TestType$1GenericArrayTypeTestClass.lists
TypeName: java.util.List<java.lang.String>[]
GenericArrayType--ComponentType = java.util.List<java.lang.String>
*************************
showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass
Field: java.lang.Object[] com.***.TestType$1GenericArrayTypeTestClass.ts
TypeName: T[]
GenericArrayType--ComponentType = T
*************************
showTypeDetails: class com.***.TestType$1GenericArrayTypeTestClass
Field: final com.***.TestType com.***.TestType$1GenericArrayTypeTestClass.this$0
TypeName: com.***.TestType
Class--SimpleName = TestType
*************************
showTypeDetails: class com.***.TestType$1WildcardTypeTestClass
// 获取字段为 numbers,类型为:参数化类型
// 参数化类型的参数为:通配符
Field: java.util.List com.***.TestType$1WildcardTypeTestClass.numbers
TypeName: java.util.List<? extends java.lang.Number>
ParameterizedType--RawType = interface java.util.List
ParameterizedType--OwnerType = null
ParameterizedType--Args.length = 1
ParameterizedType--ActualTypeArguments = ? extends java.lang.Number
WildcardType--uppers.length = 1
WildcardType--uppers, type = class java.lang.Number
WildcardType--lowers.length = 0
*************************
showTypeDetails: class com.***.TestType$1WildcardTypeTestClass
Field: java.util.List com.***.TestType$1WildcardTypeTestClass.list
TypeName: java.util.List<? super java.lang.Integer>
ParameterizedType--RawType = interface java.util.List
ParameterizedType--OwnerType = null
ParameterizedType--Args.length = 1
ParameterizedType--ActualTypeArguments = ? super java.lang.Integer
WildcardType--uppers.length = 1
WildcardType--uppers, type = class java.lang.Object
WildcardType--lowers.length = 1
WildcardType--lowers. type = class java.lang.Integer
*************************
showTypeDetails: class com.***.TestType$1WildcardTypeTestClass
Field: final com.***.TestType com.***.TestType$1WildcardTypeTestClass.this$0
TypeName: com.***.TestType
Class--SimpleName = TestType
*************************
// 获取基本数据类型、非泛型数组字段
showTypeDetails: class com.***.TestType$1AllTypes
Field: int com.***.TestType$1AllTypes.i
TypeName: int
Class--SimpleName = int
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: boolean com.***.TestType$1AllTypes.b
TypeName: boolean
Class--SimpleName = boolean
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: float com.***.TestType$1AllTypes.f
TypeName: float
Class--SimpleName = float
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: byte[] com.***.TestType$1AllTypes.bytes
TypeName: byte[]
Class--SimpleName = byte[]
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: java.lang.String com.***.TestType$1AllTypes.s
TypeName: java.lang.String
Class--SimpleName = String
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: java.lang.Object com.***.TestType$1AllTypes.o
TypeName: java.lang.Object
Class--SimpleName = Object
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: java.lang.Runnable com.***.TestType$1AllTypes.runnable
TypeName: java.lang.Runnable
Class--SimpleName = Runnable
*************************
showTypeDetails: class com.***.TestType$1AllTypes
Field: final com.***.TestType com.***.TestType$1AllTypes.this$0
TypeName: com.***.TestType
Class--SimpleName = TestType

参考文档

0%