Casting

edit

A cast converts the value of an original type to the equivalent value of a target type. An implicit cast infers the target type and automatically occurs during certain operations. An explicit cast specifies the target type and forcefully occurs as its own operation. Use the cast operator '()' to specify an explicit cast.

Refer to the cast table for a quick reference on all allowed casts.

Errors

  • If during a cast there exists no equivalent value for the target type.
  • If an implicit cast is given, but an explicit cast is required.

Grammar

cast: '(' TYPE ')' expression

Examples

  • Valid casts.

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

    declare int i; explicit cast long 5 to int 5int 5; store int 5 to i

    declare Map m; allocate HashMap instance → HashMap reference; implicit cast HashMap reference to Map referenceMap reference; store Map reference to m

    declare HashMap hm; load from mMap reference; explicit cast Map reference to HashMap referenceHashMap reference; store HashMap reference to hm

Numeric Type Casting

edit

A numeric type cast converts the value of an original numeric type to the equivalent value of a target numeric type. A cast between two numeric type values results in data loss when the value of the original numeric type is larger than the target numeric type can accommodate. A cast between an integer type value and a floating point type value can result in precision loss.

The allowed casts for values of each numeric type are shown as a row in the following table:

byte

short

char

int

long

float

double

byte

implicit

implicit

implicit

implicit

implicit

implicit

short

explicit

explicit

implicit

implicit

implicit

implicit

char

explicit

explicit

implicit

implicit

implicit

implicit

int

explicit

explicit

explicit

implicit

implicit

implicit

long

explicit

explicit

explicit

explicit

implicit

implicit

float

explicit

explicit

explicit

explicit

explicit

implicit

double

explicit

explicit

explicit

explicit

explicit

explicit

Examples

  • Valid numeric type casts.

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

    declare int a; store int 1 to a

    declare long b; load from aint 1; implicit cast int 1 to long 1long 1; store long 1 to b

    declare short c; load from blong 1; explicit cast long 1 to short 1short 1; store short 1 value to c

    declare double e; load from aint 1; explicit cast int 1 to double 1.0; store double 1.0 to e; (note the explicit cast is extraneous since an implicit cast is valid)

  • Invalid numeric type casts resulting in errors.

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

    declare int i; error → cannot implicit cast double 1.0 to int 1; (note an explicit cast is valid)

    declare int b; store int 2 to b

    declare byte c; load from bint 2; error → cannot implicit cast int 2 to byte 2; (note an explicit cast is valid)

Reference Type Casting

edit

A reference type cast converts the value of an original reference type to the equivalent value of a target reference type. An implicit cast between two reference type values is allowed when the original reference type is a descendant of the target type. An explicit cast between two reference type values is allowed when the original type is a descendant of the target type or the target type is a descendant of the original type.

Examples

  • Valid reference type casts.

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

    declare List x; store default value null to x

    declare ArrayList y; allocate ArrayList instance → ArrayList reference; store ArrayList reference to y;

    load from yArrayList reference; implicit cast ArrayList reference to List referenceList reference; store List reference to x; (note ArrayList is a descendant of List)

    load from xList reference; explicit cast List reference to ArrayList referenceArrayList reference; store ArrayList reference to y;

    load from yArrayList reference; explicit cast ArrayList reference to List referenceList reference; store List reference to x; (note the explicit cast is extraneous, and an implicit cast is valid)

  • Invalid reference type casts resulting in errors.

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

    declare List x; allocate ArrayList instance → ArrayList reference; implicit cast ArrayList reference to List referenceList reference; store List reference to x

    declare ArrayList y; load from xList reference; error → cannot implicit cast List reference to ArrayList reference; (note an explicit cast is valid since ArrayList is a descendant of List)

    declare ArrayList y; load from xList reference; error → cannot explicit cast List reference to Map reference; (note no cast is valid since neither List nor Map is a descendant of the other)

Dynamic Type Casting

edit

A dynamic (def) type cast converts the value of an original def type to the equivalent value of any target type or converts the value of any original type to the equivalent value of a target def type.

An implicit cast from any original type value to a def type value is always allowed. An explicit cast from any original type value to a def type value is always allowed but never necessary.

An implicit or explicit cast from an original def type value to any target type value is allowed if and only if the cast is normally allowed based on the current type value the def type value represents.

Examples

  • Valid dynamic type casts with any original type to a target def type.

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

    declare def d0; implicit cast int 3 to def; store int 3 to d0

    allocate ArrayList instance → ArrayList reference; implicit cast ArrayList reference to defdef; store def to d0

    declare Object o; allocate HashMap instance → HashMap reference; implicit cast HashMap reference to Object referenceObject reference; store Object reference to o

    declare def d1; load from oObject reference; implicit cast Object reference to defdef; store def to d1

    declare int i; load from d1def; implicit cast def to HashMap reference → HashMap reference`; call size on HashMap referenceint 0; store int 0 to i; (note def was implicit cast to HashMap reference since HashMap is the child-most descendant type value that the def type value represents)

  • Valid dynamic type casts with an original def type to any target type.

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

    declare def d; implicit cast double 1.0 to defdef; store def to d

    declare int i; load from ddef; implicit cast def to double 1.0double 1.0; explicit cast double 1.0 to int 1int 1; store int 1 to i; (note the explicit cast is necessary since a double type value is not converted to an int type value implicitly)

    store int 1 to d; (note the switch in the type d represents from double to int)

    declare float i; load from ddef; implicit cast def to int 1int 1; implicit cast int 1 to float 1.0float 1.0; store float 1.0 to f

    allocate ArrayList instance → ArrayList reference; store ArrayList reference to d; (note the switch in the type d represents from int to ArrayList)

    declare List l; load from ddef; implicit cast def to ArrayList referenceArrayList reference; implicit cast ArrayList reference to List referenceList reference; store List reference to l

  • Invalid dynamic type casts resulting in errors.

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

    declare def d; implicit cast int 1 to defdef; store def to d

    declare short s; load from ddef; implicit cast def to int 1int 1; error → cannot implicit cast int 1 to short 1; (note an explicit cast is valid)

    allocate HashMap instance → HashMap reference; implicit cast HashMap reference to defdef; store def to d

    declare List l; load from ddef; implicit cast def to HashMap reference; error → cannot implicit cast HashMap reference to List reference; (note no cast is valid since neither HashMap nor List is a descendant of the other)

String to Character Casting

edit

Use the cast operator to convert a String type value into a char type value.

Errors

  • If the String type value isn’t one character in length.
  • If the String type value is null.

Examples

  • Casting string literals into char type values.

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

    declare char c; explicit cast String "C" to char Cchar C; store char C to c

    explicit cast String 'c' to char cchar c; store char c to c

  • Casting a String reference into a char type value.

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

    declare String s; store String "s" to s;

    declare char c load from sString "s"; explicit cast String "s" to char schar s; store char s to c

Character to String Casting

edit

Use the cast operator to convert a char type value into a String type value.

Examples

  • Casting a String reference into a char type value.

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

    declare char c; store char 65 to c;

    declare String s load from cchar A; explicit cast char A to String "A"String "A"; store String "A" to s

Boxing and Unboxing

edit

Boxing is a special type of cast used to convert a primitive type to its corresponding reference type. Unboxing is the reverse used to convert a reference type to its corresponding primitive type.

Implicit boxing/unboxing occurs during the following operations:

  • Conversions between a def type and a primitive type are implicitly boxed/unboxed as necessary, though this is referred to as an implicit cast throughout the documentation.
  • Method/function call arguments are implicitly boxed/unboxed as necessary.
  • A primitive type value is implicitly boxed when a reference type method is called on it.

Explicit boxing/unboxing is not allowed. Use the reference type API to explicitly convert a primitive type value to its respective reference type value and vice versa.

Errors

  • If an explicit cast is made to box/unbox a primitive type.

Examples

  • Uses of implicit boxing/unboxing.

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

    declare List l; allocate ArrayList instance → ArrayList reference; store ArrayList reference to l;

    load from lList reference; implicit cast int 1 to defdef; call add on List reference with arguments (def); (note internally int 1 is boxed to Integer 1 to store as a def type value)

    declare Integer I; call valueOf on Integer with arguments of (int 0) → Integer 0; store Integer 0 to I;

    declare int i; load from IInteger 0; unbox Integer 0int 0; load from lList reference; call get on List reference with arguments (int 0) → def; implicit cast def to int 1int 1; store int 1 to i; (note internally int 1 is unboxed from Integer 1 when loaded from a def type value)

  • Uses of invalid boxing/unboxing resulting in errors.

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

    declare Integer x; error → cannot implicit box int 1 to Integer 1 during assignment

    declare Integer y; error → cannot explicit box int 1 to Integer 1 during assignment

    declare int a; call valueOf on Integer with arguments of (int 1) → Integer 1; error → cannot implicit unbox Integer 1 to int 1 during assignment

    declare int a; call valueOf on Integer with arguments of (int 1) → Integer 1; error → cannot explicit unbox Integer 1 to int 1 during assignment

Promotion

edit

Promotion is when a single value is implicitly cast to a certain type or multiple values are implicitly cast to the same type as required for evaluation by certain operations. Each operation that requires promotion has a promotion table that shows all required implicit casts based on the type(s) of value(s). A value promoted to a def type at compile-time is promoted again at run-time based on the type the def value represents.

Errors

  • If a specific operation cannot find an allowed promotion type for the type(s) of value(s) given.

Examples

  • Uses of promotion.

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

    declare double d; promote int 2 and double 2.0 @0: result double; implicit cast int 2 to double 2.0 @1double 2.0 @1; add double 2.0 @1 and double 2.0 @0double 4.0; store double 4.0 to d

    declare def x; implicit cast int 1 to defdef; store def to x;

    declare float f; load from xdef; implicit cast def to int 1int 1; promote int 1 and float 2.0: result float; implicit cast int 1 to float 1.0float `1.0; add float 1.0 and float 2.0float 3.0; store float 3.0 to f; (note this example illustrates promotion done at run-time as promotion done at compile-time would have resolved to a def type value)

Allowed Casts

edit

The following tables show all allowed casts. Read the tables row by row, where the original type is shown in the first column, and each subsequent column indicates whether a cast to the specified target type is implicit (I), explicit (E), boxed/unboxed for methods only (A), a reference type cast (@), or is not allowed (-). See reference type casting for allowed reference type casts.

Primitive/Reference Types

O

N

T

b

y

s

c

i

j

f

d

B

Y

S

C

I

J

F

D

R

def

Object ( O )

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@

I

Number ( N )

I

-

-

-

-

-

-

-

-

-

-

@

@

-

@

@

@

@

@

I

String ( T )

I

-

-

-

-

-

-

-

-

-

-

-

-

E

-

-

-

-

-

I

boolean ( b )

A

-

-

-

-

-

-

-

-

-

A

-

-

-

-

-

-

-

-

I

byte ( y )

A

A

-

-

I

E

I

I

I

I

-

A

A

-

A

A

A

A

-

I

short ( s )

A

A

-

-

E

E

I

I

I

I

-

-

A

-

A

A

A

A

-

I

char ( c )

A

-

E

-

E

E

I

I

I

I

-

-

-

A

A

A

A

A

-

I

int ( i )

A

A

-

-

E

E

E

I

I

I

-

-

-

-

A

A

A

A

-

I

long ( j )

A

A

-

-

E

E

E

E

I

I

-

-

-

-

-

A

A

A

-

I

float ( f )

A

A

-

-

E

E

E

E

E

I

-

-

-

-

-

-

A

A

-

I

double ( d )

A

A

-

-

E

E

E

E

E

E

-

-

-

-

-

-

-

A

-

I

Boolean ( B )

A

-

-

A

-

-

-

-

-

-

-

-

-

-

-

-

-

-

@

I

Byte ( Y )

A

I

-

-

A

A

-

A

A

A

A

-

A

-

A

A

A

A

@

I

Short ( S )

A

I

-

-

-

A

-

A

A

A

A

-

-

-

A

A

A

A

@

I

Character ( C )

A

-

-

-

-

-

A

A

A

A

A

-

-

-

A

A

A

A

@

I

Integer ( I )

A

-

-

-

-

-

-

A

A

A

A

-

-

-

-

A

A

A

@

I

Long ( J )

A

-

-

-

-

-

-

-

A

A

A

-

-

-

-

-

A

A

@

I

Float ( F )

A

-

-

-

-

-

-

-

-

A

A

-

-

-

-

-

-

A

@

I

Double ( D )

A

-

-

-

-

-

-

-

-

-

A

-

-

-

-

-

-

-

@

I

Reference ( R )

I

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@

I

def Type

O

N

T

b

y

s

c

i

j

f

d

B

Y

S

C

I

J

F

D

R

def as String

I

-

I

-

-

-

E

-

-

-

-

-

-

-

E

-

-

-

-

@

def as boolean/Boolean

I

-

-

I

-

-

-

-

-

-

-

I

-

-

-

-

-

-

-

@

def as byte/Byte

I

-

-

-

I

I

E

I

I

I

I

-

I

I

E

I

I

I

I

@

def as short/Short

I

-

-

-

E

I

E

I

I

I

I

-

E

I

E

I

I

I

I

@

def as char/Character

I

-

-

-

E

E

I

I

I

I

I

-

E

E

I

I

I

I

I

@

def as int/Integer

I

-

-

-

E

E

E

I

I

I

I

-

E

E

E

I

I

I

I

@

def as long/Long

I

-

-

-

E

E

E

E

I

I

I

-

E

E

E

E

I

I

I

@

def as float/Float

I

-

-

-

E

E

E

E

E

I

I

-

E

E

E

E

E

I

I

@

def as double/Double

I

-

-

-

E

E

E

E

E

E

I

-

E

E

E

E

E

E

I

@

def as Reference

@

@

@

-

-

-

-

-

-

-

-

@

@

@

@

@

@

@

@

@