11 Type Conversion

orders orders backward   forward
comments comments
1997 The McGraw-Hill Companies, Inc. All rights reserved.
Any use of this Beta Book is subject to the rules stated in the Terms of Use.

Type Conversion

This chapter describes the instructions that convert values from one primitive type to another inside the Java Virtual Machine. It also looks at some of the idiosyncrasies of type conversion that arise from the virtual machine ­s limited support of byte s, short s, and char s.

Accompanying this chapter on the CD-ROM is an applet that interactively illustrates the material presented in the chapter. The applet, named Conversion Diversion , simulates the Java Virtual Machine executing a method that performs type conversion. At the end of this chapter, you will find a description of this applet and the bytecodes it executes.

The Conversion Opcodes

The Java Virtual Machine has many opcodes that convert from one primitive type to another. No operands follow the conversion opcodes in the bytecode stream. The value to convert is taken from the top of the stack. The Java Virtual Machine pops the value at the top of the stack, converts it, and pushes the result back onto the stack. Opcodes that convert between int , long , float , and double are shown in Table 11-1. There is an opcode for each possible from-to combination of these four types:

Table 11-1. Converting int s, long s, float s, and double s

Opcode Operand(s) Description
i2l (none) converts int to long
i2f (none) converts int to float
i2d (none) converts int to double
l2i (none) converts long to int
l2f (none) converts long to float
l2d (none) converts long to double
f2i (none) converts float to int
f2l (none) converts float to long
f2d (none) converts float to double
d2i (none) converts double to int
d2l (none) converts double to long
d2f (none) converts double to float

Opcodes that convert from an int to a type smaller than int are shown in Table 11-2. These opcodes pop one int off the operand stack, convert it to an int value that fits into a byte , short , or char , and push the resulting int back onto the operand stack. The i2b instruction truncates the popped int value to a byte , then sign-extends back out to an int . The i2s instruction truncates the popped int value to a short , then sign-extends back out to an int . The i2c instruction truncates the popped int value to a char , then zero-extends back out to an int .

Table 11-2. Converting int s, byte s, chars , and short s.

Opcode Operand(s) Description
i2b (none) converts int to byte
i2c (none) converts int to char
i2s (none) converts int to short

No opcodes exist that convert directly from a long , float , or double to the types smaller than int . Therefore converting from a float to a byte , for example, requires two steps. First the float must be converted to an int with f2i , then the resulting int can be converted to a byte with i2b .

Although opcodes exist that convert an int to primitive types smaller than int ( byte , short , and char ), no opcodes exist that convert in the opposite direction. This is because any byte s, short s, or char s are effectively converted to int before being pushed onto the stack. The instructions that retrieve byte , short , and char values from arrays or objects on the heap and push them onto the stack convert the values to int . These instructions are described in Chapter 15, "Objects and Arrays."

Arithmetic operations upon byte s, short s, and char s are done by first converting the values to int , performing the arithmetic operations on the int s, and being happy with an int result. This means that if you add 2 byte s you get an int , and if you want a byte result you must explicitly convert the int result back to a byte . For example, the following code won't compile:

 

begin

// On the CD-ROM in file opcodes/ex1/BadArithmetic.java

class BadArithmetic {

static byte addOneAndOne() {

byte a = 1;

byte b = 1;

byte c = a + b;

return c;

}

}

end

When presented with the above code, javac objects with the following remark:

 

begin

BadArithmetic.java(7): Incompatible type for declaration. Explicit

cast needed to convert int to byte.

byte c = a + b;

^

end

To remedy the situation, the you must explicitly convert the int result of the addition of a + b back to a byte , as in the following code:

 

begin

// On the CD-ROM in file opcodes/ex1/GoodArithmetic.java

class GoodArithmetic {

static byte addOneAndOne() {

byte a = 1;

byte b = 1;

byte c = (byte) (a + b);

return c;

}

}

end

This makes javac so happy it drops a GoodArithmetic.class file, which contains the following bytecode sequence for the addOneAndOne() method:

 

begin

0 iconst_1 // Push int constant 1.

1 istore_0 // Pop into local variable 0, which is a: byte a = 1;

2 iconst_1 // Push int constant 1 again.

3 istore_1 // Pop into local variable 1, which is b: byte b = 1;

4 iload_0 // Push a (a is already stored as an int in local

// variable 0).

5 iload_1 // Push b (b is already stored as an int in local

// variable 1).

6 iadd // Perform addition. Top of stack is

// now (a + b), an int.

7 i2b // Convert int result to byte (result still

// occupies 32 bits).

8 istore_2 // Pop into local variable 3, which is

// byte c: byte c = (byte) (a + b);

9 iload_2 // Push the value of c so it can be returned.

10 ireturn // Proudly return the result of the addition: return c;

end

Conversion Diversion: A Simulation

The Conversion Diversion applet, shown in Figure 11-1, demonstrates a Java Virtual Machine executing a sequence of bytecodes. The applet is embedded in a web page on the CD-ROM in file applets/ConversionDiversion.html . The bytecode sequence in the simulation was generated by javac for the Convert() method of the class shown below:

 

begin

// On CD-ROM in file opcodes/ex1/Diversion.java

class Diversion {

static void Convert() {

byte imByte = 0;

int imInt = 125;

for (;;) {

++imInt;

imByte = (byte) imInt;

imInt *= -1;

imByte = (byte) imInt;

imInt *= -1;

}

}

}

end

The bytecodes generated by javac for Convert() are shown below:

 

begin

0 iconst_0 // Push int constant 0.

1 istore_0 // Pop to local variable 0, which is

// imByte: byte imByte = 0;

2 bipush 125 // Expand byte constant 125 to int and push.

4 istore_1 // Pop to local variable 1, which

// is imInt: int imInt = 125;

5 iinc 1 1 // Increment local variable 1 (imInt) by 1: ++imInt;

8 iload_1 // Push local variable 1 (imInt).

9 i2b // Truncate and sign extend top of stack so it

// has a valid byte value.

10 istore_0 // Pop to local variable 0 (imByte):

// imByte = (byte) imInt;

11 iload_1 // Push local variable 1 (imInt) again.

12 iconst_m1 // Push integer -1.

13 imul // Pop top two ints, multiply, push result.

14 istore_1 // Pop result of multiply to local variable 1 (imInt):

// imInt *= -1;

15 iload_1 // Push local variable 1 (imInt).

16 i2b // Truncate and sign extend top of stack so it has

// a valid byte value.

17 istore_0 // Pop to local variable 0 (imByte):

// imByte = (byte) imInt;

18 iload_1 // Push local variable 1 (imInt) again.

19 iconst_m1 // Push integer -1.

20 imul // Pop top two ints, multiply, push result.

21 istore_1 // Pop result of multiply to local variable 1 (imInt):

// imInt *= -1;

22 goto 5 // Jump back to the iinc instruction: for (;;) {}

end

The Convert() method demonstrates the manner in which the Java Virtual Machine converts from int to byte . imInt starts out as 125. Each pass through the while loop, it is incremented and converted to a byte . Then it is multiplied by -1 and again converted to a byte . The simulation quickly shows what happens at the edges of the valid range for the byte type.

The maximum value for a byte is 127. The minimum value is -128. Values of type int that are within this range convert directly to byte . As soon as the int gets beyond the valid range for byte , however, things get interesting.

The Java Virtual Machine converts an int to a byte by truncating and sign extending. The highest order bit, the "sign bit," of long s, int s, short s, and byte s indicate whether or not the integer value is positive or negative. If the sign bit is zero, the value is positive. If the sign bit is one, the value is negative. Bit 7 of a byte value is its sign bit. To convert an int to a byte , bit 7 of the int is copied to bits 8 through 31. This produces an int that has the same numerical value that the int 's lowest order byte would have if it were interpreted as a byte type. After the truncation and sign extension, the int will contain a valid byte value.

The simulation applet shows what happens when an int that is just beyond the valid range for byte types gets converted to a byte . For example, when the imInt variable has a value of 128 (0x00000080) and is converted to byte , the resulting byte value is -128 (0xffffff80). Later, when the imInt variable has a value of -129 (0xffffff7f) and is converted to byte , the resulting byte value is 127 (0x0000007f).

To drive the Conversion Diversion simulation, use the Step, Reset, Run, and Stop buttons . Each time you press the Step button, the simulator will execute the instruction pointed to by the pc register. If you press the Run button, the simulation will continue with no further coaxing on your part until you press the Stop button. To start the simulation over, press the Reset button. For each step of the simulation, a panel at the bottom of the applet contains an explanation of what the next instruction will do. Happy clicking.

figure 11-1

On the CD-ROM

The CD-ROM contains the source code examples from this chapter in the opcodes directory. The Conversion Diversion applet is contained in a web page on the CD-ROM in file applets/ConversionDiversion.html . The source code for this applet is found alongside its class files, in the applets/JVMSimulators and applets/JVMSimulators/COM/artima/jvmsim directories.

The Resources Page

For more information about the material presented in this chapter, visit the resources page: http://www.artima.com/insidejvm/typeconv.html .

orders orders backward   forward
comments comments

 COMPUTING MCGRAW-HILL Beta Books Contact Us Order Information Online Catalog

Computing McGraw-Hill is an imprint of the McGraw-Hill Professional Book Group.


a division of the mcgraw-hill companies
Copyright 1997 The McGraw-Hill Companies. All rights reserved. Any use is subject to the Terms of Use; the corporation also has a comprehensive Privacy Policy governing information we may collect from our customers.


Inside the Java virtual machine
Inside the Java 2 Virtual Machine
ISBN: 0071350934
EAN: 2147483647
Year: 1997
Pages: 28
Authors: Bill Venners

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net