类型转换

编辑

类型转换将原始类型的值转换为目标类型的等效值。隐式转换推断目标类型,并在某些操作期间自动发生。显式转换指定目标类型,并作为其自身操作强制发生。使用cast 运算符 '()'来指定显式转换。

请参阅转换表,以快速参考所有允许的转换。

错误

  • 如果在转换期间目标类型不存在等效值。
  • 如果给出了隐式转换,但需要显式转换。

语法

cast: '(' TYPE ')' expression

示例

  • 有效的转换。

    int i = (int)5L;         
    Map m = new HashMap();   
    HashMap hm = (HashMap)m; 

    声明 int i;显式转换 long 5int 5int 5;将 int 5 存储到 i

    声明 Map m;分配 HashMap 实例 → HashMap 引用;隐式转换 HashMap 引用Map 引用Map 引用;将 Map 引用 存储到 m

    声明 HashMap hm;从 m 加载 → Map 引用;显式转换 Map 引用HashMap 引用HashMap 引用;将 HashMap 引用 存储到 hm

数值类型转换

编辑

数值类型转换将原始数值类型的值转换为目标数值类型的等效值。当原始数值类型的值大于目标数值类型所能容纳的值时,两个数值类型值之间的转换会导致数据丢失。整数类型值和浮点类型值之间的转换可能会导致精度丢失。

下表以行的形式显示了每种数值类型的值允许的转换。

byte

short

char

int

long

float

double

byte

隐式

隐式

隐式

隐式

隐式

隐式

short

显式

显式

隐式

隐式

隐式

隐式

char

显式

显式

隐式

隐式

隐式

隐式

int

显式

显式

显式

隐式

隐式

隐式

long

显式

显式

显式

显式

隐式

隐式

float

显式

显式

显式

显式

显式

隐式

double

显式

显式

显式

显式

显式

显式

示例

  • 有效的数值类型转换。

    int a = 1;            
    long b = a;           
    short c = (short)b;   
    double e = (double)a; 

    声明 int a;将 int 1 存储到 a

    声明 long b;从 a 加载 → int 1;隐式转换 int 1long 1long 1;将 long 1 存储到 b

    声明 short c;从 b 加载 → long 1;显式转换 long 1short 1short 1;将 short 1 值存储到 c

    声明 double e;从 a 加载 → int 1;显式转换 int 1double 1.0;将 double 1.0 存储到 e;(注意,由于隐式转换有效,因此显式转换是多余的)

  • 导致错误的无效数值类型转换。

    int a = 1.0; // error 
    int b = 2;            
    byte c = b;  // error 

    声明 int i错误 → 无法将 double 1.0 隐式转换为 int 1;(注意显式转换有效)

    声明 int b;将 int 2 存储到 b

    声明 byte c;从 b 加载 → int 2错误 → 无法将 int 2 隐式转换为 byte 2;(注意显式转换有效)

引用类型转换

编辑

引用类型转换将原始引用类型的值转换为目标引用类型的等效值。当原始引用类型是目标类型的子类时,允许在两个引用类型值之间进行隐式转换。当原始类型是目标类型的子类或目标类型是原始类型的子类时,允许在两个引用类型值之间进行显式转换。

示例

  • 有效的引用类型转换。

    List x;                        
    ArrayList y = new ArrayList(); 
    x = y;                         
    y = (ArrayList)x;              
    x = (List)y;                   

    声明 List x;将默认值 null 存储到 x

    声明 ArrayList y;分配 ArrayList 实例 → ArrayList 引用;将 ArrayList 引用 存储到 y

    y 加载 → ArrayList 引用;隐式转换 ArrayList 引用List 引用List 引用;将 List 引用 存储到 x;(注意 ArrayListList 的子类)

    x 加载 → List 引用;显式转换 List 引用ArrayList 引用ArrayList 引用;将 ArrayList 引用 存储到 y

    y 加载 → ArrayList 引用;显式转换 ArrayList 引用List 引用List 引用;将 List 引用 存储到 x;(注意显式转换是多余的,并且隐式转换有效)

  • 导致错误的无效引用类型转换。

    List x = new ArrayList();          
    ArrayList y = x;          // error 
    Map m = (Map)x;           // error 

    声明 List x;分配 ArrayList 实例 → ArrayList 引用;隐式转换 ArrayList 引用List 引用List 引用;将 List 引用 存储到 x

    声明 ArrayList y;从 x 加载 → List 引用错误 → 无法将 List 引用 隐式转换为 ArrayList 引用;(注意显式转换有效,因为 ArrayListList 的子类)

    声明 ArrayList y;从 x 加载 → List 引用错误 → 无法将 List 引用 显式转换为 Map 引用;(注意没有转换有效,因为 ListMap 都不彼此是子类)

动态类型转换

编辑

动态(def)类型转换将原始 def 类型的值转换为任何目标类型的等效值,或将任何原始类型的值转换为目标 def 类型的等效值。

始终允许从任何原始类型值到 def 类型值的隐式转换。始终允许从任何原始类型值到 def 类型值的显式转换,但从不需要。

当且仅当根据 def 类型值表示的当前类型值通常允许转换时,才允许从原始 def 类型值到任何目标类型值的隐式或显式转换。

示例

  • 使用任何原始类型到目标 def 类型的有效动态类型转换。

    def d0 = 3;               
    d0 = new ArrayList();     
    Object o = new HashMap(); 
    def d1 = o;               
    int i = d1.size();        

    声明 def d0;隐式转换 int 3def;将 int 3 存储到 d0

    分配 ArrayList 实例 → ArrayList 引用;隐式转换 ArrayList 引用defdef;将 def 存储到 d0

    声明 Object o;分配 HashMap 实例 → HashMap 引用;隐式转换 HashMap 引用Object 引用Object 引用;将 Object 引用 存储到 o

    声明 def d1;从 o 加载 → Object 引用;隐式转换 Object 引用defdef;将 def 存储到 d1

    声明 int i;从 d1 加载 → def;隐式转换 defHashMap 引用 → HashMap 引用`;对 HashMap 引用 调用 sizeint 0;将 int 0 存储到 i;(注意 def 被隐式转换为 HashMap 引用,因为 HashMapdef 类型值表示的最内层子类类型值)

  • 使用原始 def 类型到任何目标类型的有效动态类型转换。

    def d = 1.0;         
    int i = (int)d;      
    d = 1;               
    float f = d;         
    d = new ArrayList(); 
    List l = d;          

    声明 def d;隐式转换 double 1.0defdef;将 def 存储到 d

    声明 int i;从 d 加载 → def;隐式转换 defdouble 1.0double 1.0;显式转换 double 1.0int 1int 1;将 int 1 存储到 i;(注意,由于 double 类型值不会隐式转换为 int 类型值,因此需要显式转换)

    int 1 存储到 d;(注意 d 表示的类型从 double 切换为 int

    声明 float i;从 d 加载 → def;隐式转换 defint 1int 1;隐式转换 int 1float 1.0float 1.0;将 float 1.0 存储到 f

    分配 ArrayList 实例 → ArrayList 引用;将 ArrayList 引用 存储到 d;(注意 d 表示的类型从 int 切换为 ArrayList

    声明 List l;从 d 加载 → def;隐式转换 defArrayList 引用ArrayList 引用;隐式转换 ArrayList 引用List 引用List 引用;将 List 引用 存储到 l

  • 无效的动态类型转换导致错误。

    def d = 1;                  
    short s = d;       // error 
    d = new HashMap();          
    List l = d;        // error 

    声明 def d;隐式转换 int 1defdef;将 def 存储到 d

    声明 short s;从 d 加载 → def;隐式转换 defint 1int 1错误 → 无法隐式转换 int 1short 1;(注意显式转换是有效的)

    分配 HashMap 实例 → HashMap 引用;隐式转换 HashMap 引用defdef;将 def 存储到 d

    声明 List l;从 d 加载 → def;隐式转换 defHashMap 引用错误 → 无法隐式转换 HashMap 引用List 引用;(注意由于 HashMapList 都不属于对方的子类,因此任何转换都不合法)

字符串到字符的转换

编辑

使用强制转换运算符将 String 类型 值转换为 char 类型 值。

错误

  • 如果 String 类型的值长度不为 1。
  • 如果 String 类型的值为 null

示例

  • 将字符串字面量转换为 char 类型的值。

    char c = (char)"C"; 
    c = (char)'c';      

    声明 char c;显式转换 String "C"char Cchar C;将 char C 存储到 c

    显式转换 String 'c'char cchar c;将 char c 存储到 c

  • String 引用转换为 char 类型的值。

    String s = "s";   
    char c = (char)s; 

    声明 String s;将 String "s" 存储到 s

    声明 char cs 加载 → String "s";显式转换 String "s"char schar s;将 char s 存储到 c

字符到字符串的转换

编辑

使用强制转换运算符将 char 类型 值转换为 String 类型 值。

示例

  • String 引用转换为 char 类型的值。

    char c = 65;          
    String s = (String)c; 

    声明 char c;将 char 65 存储到 c

    声明 String sc 加载 → char A;显式转换 char AString "A"String "A";将 String "A" 存储到 s

装箱和拆箱

编辑

装箱是一种特殊的转换类型,用于将基本类型转换为其对应的引用类型。拆箱是相反的操作,用于将引用类型转换为其对应的基本类型。

在以下操作中会发生隐式装箱/拆箱

  • def 类型和基本类型之间的转换会根据需要隐式地进行装箱/拆箱,尽管在整个文档中将其称为隐式转换。
  • 方法/函数调用参数会根据需要隐式地进行装箱/拆箱。
  • 当对基本类型值调用引用类型方法时,该基本类型值会隐式地进行装箱。

不允许显式装箱/拆箱。使用引用类型 API 显式地将基本类型值转换为其对应的引用类型值,反之亦然。

错误

  • 如果进行显式转换以装箱/拆箱基本类型。

示例

  • 隐式装箱/拆箱的使用。

    List l = new ArrayList();       
    l.add(1);                       
    Integer I = Integer.valueOf(0); 
    int i = l.get(i);               

    声明 List l;分配 ArrayList 实例 → ArrayList 引用;将 ArrayList 引用 存储到 l

    l 加载 → List 引用;隐式转换 int 1defdef;使用参数 (def) 调用 List 引用 上的 add 方法;(注意,在内部,int 1 会被装箱为 Integer 1 以存储为 def 类型的值)

    声明 Integer I;使用参数 (int 0) 调用 Integer 上的 valueOf 方法 → Integer 0;将 Integer 0 存储到 I

    声明 int i;从 I 加载 → Integer 0;拆箱 Integer 0int 0;从 l 加载 → List 引用;使用参数 (int 0) 调用 List 引用 上的 get 方法 → def;隐式转换 defint 1int 1;将 int 1 存储到 i;(注意,在内部,当从 def 类型的值加载时,int 1 会从 Integer 1 拆箱)

  • 导致错误的无效装箱/拆箱的使用。

    Integer x = 1;                   // error 
    Integer y = (Integer)1;          // error 
    int a = Integer.valueOf(1);      // error 
    int b = (int)Integer.valueOf(1); // error 

    声明 Integer x错误 → 在赋值期间无法隐式装箱 int 1Integer 1

    声明 Integer y错误 → 在赋值期间无法显式装箱 int 1Integer 1

    声明 int a;使用参数 (int 1) 调用 Integer 上的 valueOf 方法 → Integer 1错误 → 在赋值期间无法隐式拆箱 Integer 1int 1

    声明 int a;使用参数 (int 1) 调用 Integer 上的 valueOf 方法 → Integer 1错误 → 在赋值期间无法显式拆箱 Integer 1int 1

提升

编辑

提升是指将单个值隐式转换为特定类型,或者将多个值隐式转换为某些操作所需的相同类型。每个需要提升的操作都有一个提升表,该表根据值类型显示所有必需的隐式转换。在编译时提升为 def 类型的值会在运行时根据 def 值表示的类型再次提升。

错误

  • 如果特定操作无法为给定值类型找到允许的提升类型。

示例

  • 提升的使用。

    double d = 2 + 2.0; 
    def x = 1;          
    float f = x + 2.0F; 

    声明 double d;提升 int 2double 2.0 @0:结果为 double;隐式转换 int 2double 2.0 @1double 2.0 @1;将 double 2.0 @1double 2.0 @0 相加 → double 4.0;将 double 4.0 存储到 d

    声明 def x;隐式转换 int 1defdef;将 def 存储到 x

    声明 float f;从 x 加载 → def;隐式转换 defint 1int 1;提升 int 1float 2.0:结果为 float;隐式转换 int 1float 1.0float `1.0;将 float 1.0float 2.0 相加 → float 3.0;将 float 3.0 存储到 f;(注意,此示例说明了在运行时执行的提升,因为在编译时执行的提升将解析为 def 类型的值)

允许的转换

编辑

以下表格显示所有允许的转换。逐行阅读表格,其中第一列显示原始类型,后续每列指示是否可以隐式 (I)、显式 (E)、仅对方法进行装箱/拆箱 (A)、引用类型转换 (@) 或不允许 (-) 转换为指定的目标类型。有关允许的引用类型转换,请参阅 引用类型转换

基本类型/引用类型

O

N

T

b

y

s

c

i

j

f

d

B

Y

S

C

I

J

F

D

R

def

对象 ( O )

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@

I

数字 ( N )

I

-

-

-

-

-

-

-

-

-

-

@

@

-

@

@

@

@

@

I

字符串 ( T )

I

-

-

-

-

-

-

-

-

-

-

-

-

E

-

-

-

-

-

I

布尔值 ( b )

A

-

-

-

-

-

-

-

-

-

A

-

-

-

-

-

-

-

-

I

字节 ( y )

A

A

-

-

I

E

I

I

I

I

-

A

A

-

A

A

A

A

-

I

短整型 ( s )

A

A

-

-

E

E

I

I

I

I

-

-

A

-

A

A

A

A

-

I

字符 ( c )

A

-

E

-

E

E

I

I

I

I

-

-

-

A

A

A

A

A

-

I

整型 ( i )

A

A

-

-

E

E

E

I

I

I

-

-

-

-

A

A

A

A

-

I

长整型 ( j )

A

A

-

-

E

E

E

E

I

I

-

-

-

-

-

A

A

A

-

I

浮点型 ( f )

A

A

-

-

E

E

E

E

E

I

-

-

-

-

-

-

A

A

-

I

双精度浮点型 ( d )

A

A

-

-

E

E

E

E

E

E

-

-

-

-

-

-

-

A

-

I

布尔对象 ( B )

A

-

-

A

-

-

-

-

-

-

-

-

-

-

-

-

-

-

@

I

字节对象 ( Y )

A

I

-

-

A

A

-

A

A

A

A

-

A

-

A

A

A

A

@

I

短整型对象 ( S )

A

I

-

-

-

A

-

A

A

A

A

-

-

-

A

A

A

A

@

I

字符对象 ( C )

A

-

-

-

-

-

A

A

A

A

A

-

-

-

A

A

A

A

@

I

整型对象 ( I )

A

-

-

-

-

-

-

A

A

A

A

-

-

-

-

A

A

A

@

I

长整型对象 ( J )

A

-

-

-

-

-

-

-

A

A

A

-

-

-

-

-

A

A

@

I

浮点对象 ( F )

A

-

-

-

-

-

-

-

-

A

A

-

-

-

-

-

-

A

@

I

双精度浮点对象 ( D )

A

-

-

-

-

-

-

-

-

-

A

-

-

-

-

-

-

-

@

I

引用 ( R )

I

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@

I

def 类型

O

N

T

b

y

s

c

i

j

f

d

B

Y

S

C

I

J

F

D

R

def 作为字符串

I

-

I

-

-

-

E

-

-

-

-

-

-

-

E

-

-

-

-

@

def 作为布尔值/Boolean

I

-

-

I

-

-

-

-

-

-

-

I

-

-

-

-

-

-

-

@

def 作为字节/Byte

I

-

-

-

I

I

E

I

I

I

I

-

I

I

E

I

I

I

I

@

def 作为短整型/Short

I

-

-

-

E

I

E

I

I

I

I

-

E

I

E

I

I

I

I

@

def 作为字符/Character

I

-

-

-

E

E

I

I

I

I

I

-

E

E

I

I

I

I

I

@

def 作为整型/Integer

I

-

-

-

E

E

E

I

I

I

I

-

E

E

E

I

I

I

I

@

def 作为长整型/Long

I

-

-

-

E

E

E

E

I

I

I

-

E

E

E

E

I

I

I

@

def 作为浮点数/Float

I

-

-

-

E

E

E

E

E

I

I

-

E

E

E

E

E

I

I

@

def 作为双精度浮点数/Double

I

-

-

-

E

E

E

E

E

E

I

-

E

E

E

E

E

E

I

@

def 作为引用

@

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@