类型
编辑类型
编辑类型是对数据进行分类的方式,用于定义值的属性。这些属性指定了值表示的数据以及值在操作期间的求值规则。每种类型都属于以下类别之一:原始、引用或动态。
原始类型
编辑原始类型表示 JVM 中原生构建的基本数据,并分配到非堆内存。声明一个原始类型变量或访问原始类型成员字段(来自引用类型实例),并为其分配一个原始类型值,以便在后续操作中进行求值。新声明的原始类型变量的默认值在下面的定义中列出。原始类型值在赋值期间或作为方法/函数调用的参数时会被复制。
原始类型具有相应的引用类型(也称为装箱类型)。使用字段访问操作符或方法调用操作符对原始类型值强制求值为其对应的引用类型值。
以下是可用的原始类型。相应的引用类型在括号中列出。例如,Byte
是 byte
原始类型的引用类型。
可用的原始类型
-
byte
(Byte
) - 8 位,有符号,二进制补码整数。范围:[
-128
,127
]。默认值:0
。 -
short
(Short
) - 16 位,有符号,二进制补码整数。范围:[
-32768
,32767
]。默认值:0
。 -
char
(Character
) - 16 位,无符号,Unicode 字符。范围:[
0
,65535
]。默认值:0
或\u0000
。 -
int
(Integer
) - 32 位,有符号,二进制补码整数。范围:[
-2^31
,2^31-1
]。默认值:0
。 -
long
(Long
) - 64 位,有符号,二进制补码整数。范围:[
-2^63
,2^63-1
]。默认值:0
。 -
float (`Float
)` - 32 位,有符号,单精度,IEEE 754 浮点数。默认值:
0.0
。 -
double
(Double
) - 64 位,有符号,双精度,IEEE 754 浮点数。默认值:
0.0
。 -
boolean
(Boolean
) - 逻辑量,具有两个可能的值:
true
和false
。默认值:false
。
示例
-
在声明、声明和赋值中使用的原始类型。
-
使用相应的引用类型对原始类型进行方法调用。
引用类型
编辑引用类型是命名的构造(对象),可能表示多个数据片段(成员字段)和用于操作该数据的逻辑(成员方法),定义为脚本的应用程序编程接口 (API) 的一部分。
引用类型实例是分配给堆的单个引用类型对象的一组数据。使用新实例操作符来分配引用类型实例。使用引用类型实例来加载、存储和操作复杂数据。
引用类型值引用引用类型实例,并且多个引用类型值可能引用同一个引用类型实例。对引用类型实例的更改将影响引用该特定实例的所有引用类型值。
声明一个引用类型变量或访问引用类型成员字段(来自引用类型实例),并为其分配一个引用类型值,以便在后续操作中进行求值。新声明的引用类型变量的默认值为 null
。引用类型值在赋值期间或作为方法/函数调用的参数时会被浅拷贝。将 null
赋值给引用类型变量表示引用类型值不引用任何引用类型实例。当没有任何引用类型值引用某个引用类型实例时,JVM 将对其进行垃圾回收。将 null
作为参数传递给方法/函数调用表示该参数不引用任何引用类型实例。
引用类型对象定义了零个到多个以下各项:
- 静态成员字段
- 静态成员字段是命名的且类型化的数据片段。每个引用类型对象都包含一组代表其静态成员字段的数据。使用字段访问操作符以及引用类型对象名称来访问静态成员字段,以便加载和存储到特定的引用类型对象。使用静态成员字段不需要分配引用类型实例。
- 非静态成员字段
- 非静态成员字段是命名的且类型化的数据片段。每个引用类型实例都包含一组代表其引用类型对象的非静态成员字段的数据。使用字段访问操作符来加载和存储到特定引用类型实例的非静态成员字段。使用非静态成员字段需要分配引用类型实例。
- 静态成员方法
- 静态成员方法是在引用类型对象上调用的函数。使用方法调用操作符以及引用类型对象名称来调用静态成员方法。使用静态成员方法不需要分配引用类型实例。
- 非静态成员方法
- 非静态成员方法是在引用类型实例上调用的函数。在引用类型实例上调用的非静态成员方法可以从该特定引用类型实例的非静态成员字段加载数据并存储到其中。使用方法调用操作符以及特定的引用类型实例来调用非静态成员方法。使用非静态成员方法需要分配引用类型实例。
- 构造函数
- 构造函数是一种特殊类型的函数,用于分配由特定引用类型对象定义的引用类型实例。使用新实例操作符来分配引用类型实例。
引用类型对象遵循基本继承模型。考虑类型 A 和 B。如果 B 继承(能够访问 A 的所有非静态成员作为自己的成员),则认为类型 A 是 B 的父类型,而 B 是 A 的子类型。如果从 B 到 A 存在递归的父子关系,且两者之间有零到多个类型,则认为类型 B 是 A 的后代。在这种情况下,B 继承了 A 的所有非静态成员以及两者之间所有类型的非静态成员。在这两种关系中,类型 B 也被认为是类型 A。
示例
-
在几种不同的操作中求值的引用类型。
声明
List l
; 分配ArrayList
实例 →ArrayList 引用
; 将ArrayList 引用
隐式转换为List 引用
→List 引用
; 将List 引用
存储到l
从
l
加载 →List 引用
; 将int 1
隐式转换为def
→def
; 使用参数 (def
) 在List 引用
上调用add
声明
int i
; 从l
加载 →List 引用
; 使用参数 (int 0
) 在List 引用
上调用get
→def
; 将def
隐式转换为int 1
→int 1
; 将int 1
和int 2
相加 →int 3
; 将int 3
存储到i
-
共享引用类型实例。
声明
List l0
; 分配ArrayList
实例 →ArrayList 引用
; 将ArrayList 引用
隐式转换为List 引用
→List 引用
; 将List 引用
存储到l0
声明
List l1
; 从l0
加载 →List 引用
; 将List 引用
存储到l1
(注意l0
和l1
引用同一个实例,称为浅拷贝)从
l0
加载 →List 引用
; 将int 1
隐式转换为def
→def
; 使用参数 (def
) 在List 引用
上调用add
从
l1
加载 →List 引用
; 将int 2
隐式转换为def
→def
; 使用参数 (def
) 在List 引用
上调用add
声明
int i
; 从l0
加载 →List 引用
; 使用参数 (int 0
) 在List 引用
上调用get
→def @0
; 将def @0
隐式转换为int 1
→int 1
; 从l1
加载 →List 引用
; 使用参数 (int 1
) 在List 引用
上调用get
→def @1
; 将def @1
隐式转换为int 2
→int 2
; 将int 1
和int 2
相加 →int 3
; 将int 3
存储到i
-
使用引用类型的静态成员。
动态类型
编辑动态类型值可以使用单一类型名称 def
来表示任何原始类型或引用类型的值。def
类型值在运行时会模拟它所表示的任何值的行为,并且在操作期间求值时,始终表示任何类型值的最底层子类型值。
声明一个 def
类型变量或访问 def
类型成员字段(来自引用类型实例),并为其赋值任何类型的值,以便在后续操作期间进行求值。新声明的 def
类型变量的默认值为 null
。def
类型变量或方法/函数参数可以在脚本的编译和求值期间更改其表示的类型。
使用 def
类型可能会对性能产生轻微影响。当性能至关重要时,请直接使用原始类型和引用类型。
错误
- 如果
def
类型值在运行时表示不适合操作求值的类型。
示例
-
def
类型的常用用法。 -
表示值的最底层子类型的
def
类型值。声明
Object l
; 分配ArrayList
实例 →ArrayList 引用
; 隐式转换ArrayList 引用
为Object 引用
→Object 引用
; 将Object 引用
存储到l
声明
def d
; 从l
加载 →Object 引用
; 隐式转换Object 引用
为def
→def
; 将def
存储到d
;从
d
加载 →def
; 隐式转换def
为ArrayList 引用
→ArrayList 引用
; 使用参数 (int 10
) 在ArrayList 引用
上调用ensureCapacity
; (注意def
被隐式转换为ArrayList 引用
,因为 ArrayList` 是def
类型值所表示的最底层子类型值)
字符串类型
编辑String
类型是一种特殊的引用类型,不需要显式分配。使用字符串字面量直接求值 String
类型值。虽然不是必需的,但新实例运算符可以分配 String
类型实例。
示例
-
String
类型的常用用法。
void 类型
编辑void
类型表示缺少类型的概念。使用 void
类型来指示函数不返回值。
示例
-
在函数中使用
void
类型。void addToList(List l, def d) { l.add(d); }
数组类型
编辑数组类型是一种特殊的引用类型,其中数组类型实例包含一系列分配给堆的值。数组类型实例中的每个值都定义为一个元素。数组类型实例中的所有元素都属于声明中指定的相同类型(元素类型)。每个元素都被分配一个范围在 [0, length)
内的索引,其中 length 是为数组类型实例分配的元素总数。
使用新数组运算符或数组初始化运算符来分配数组类型实例。声明一个数组类型变量或访问数组类型成员字段(来自引用类型实例),并为其赋值一个数组类型值,以便在后续操作期间进行求值。新声明的数组类型变量的默认值为 null
。在赋值或作为方法/函数调用的参数期间,数组类型值会被浅复制。将 null
赋值给数组类型变量,表示该数组类型值不引用任何数组类型实例。当没有任何数组类型值引用数组类型实例时,JVM 将对其进行垃圾回收。将 null
作为参数传递给方法/函数调用,表示该参数不引用任何数组类型实例。
使用数组长度运算符检索数组类型值的长度作为 int
类型值。使用数组访问运算符从数组类型实例中的单个元素加载和存储数据。
当使用范围 [2, d]
(其中 d >= 2
)分配具有多个维度的数组类型实例时,范围 [1, d-1]
中的每个维度中的每个元素也都是数组类型。每个维度 n 的元素类型都是一个数组类型,其维度数等于 d-n
。例如,考虑具有 3 个维度的 int[][][]
。第 3 维度 d-3
中的每个元素都是原始类型 int
。第 2 维度 d-2
中的每个元素都是数组类型 int[]
。第 1 维度 d-1
中的每个元素都是数组类型 int[][]
。
示例
-
一维数组的常用用法。
声明
int[] x
; 将默认null
存储到x
声明
float[] y
; 分配长度为[10]
的1-d float array
实例 →1-d float array 引用
; 将1-d float array 引用
存储到y
声明
def z
; 分配长度为[5]
的1-d float array
实例 →1-d float array 引用
; 隐式转换1-d float array 引用
为def
→def
; 将def
存储到z
从
y
加载 →1-d float array 引用
; 将float 1.0
存储到1-d float array 引用
的index [9]
从
y
加载 →1-d float array 引用 @0
; 从1-d float array 引用 @0
的index [9]
加载 →float 1.0
; 从z
加载 →def
; 隐式转换def
为1-d float array 引用 @1
→1-d float array 引用 @1
; 将float 1.0
存储到1-d float array 引用 @1
的index [0]
-
多维数组的常用用法。