Conversions and promotions are not something that the typical user of ClassMaker
need worry themselves about. In most cases, ClassMaker
will do the same thing as java.
In the few situations where ClassMaker
does not do the same thing as java the value
may be cast to the correct type.
The conversion and promotion strategies used by ClassMaker
are a subset of those
used in java.
Method Invocation Conversion may be applied to the type of each parameter of a method call after it
has been pushed onto the stack. Note that this differs from java where method invocation conversion is
applied as parameters are pushed onto the stack. This means that some conversions are not supported,
for example, an int cannot be promoted to a long, float or double. The conversions that are supported
are those that do not require modification of the value on the stack.
In practice what happens is that the Method Invocation Converter is used by the Method Resolver to
eliminate candidates from the list of methods with the same name. The parameters
of each overloaded method are compared to the parameters on the call stack and if any actual
parameter cannot be converted to the corresponding formal parameter then the method is excluded.
Hopefully, this process eliminates all candidates but one. The byte-code to invoke the selected
candidate is generated and all the parameters are assumed to be correct.
Method Invocation Conversion involves:
* promoting a primitive type along the sequence from byte or char to short to int
* converting a reference type to another compatable reference type, without requiring a cast.
The specific rules for this conversion are detailed in the MethodInvocationConversion
class.
Assignment Conversion is applied to a value as it is assigned to a variable. The variable
may be a local, class or static variable or an array element.
The assignment converter determines whether the type of a value on the stack can be
converted to the type of the storage location and then generates any byte-code
required to perform the conversion.
Assignment Conversion involves:
StringBuffer
to a String
.Conversions to long, float or double require byte-code to be generated.
The specific rules for this conversion are detailed in the AssignmentConversion
class.
Casting Conversion is applied to a value by explicitly calling the Cast
method.
Casting Conversion involves:
* explicitly converting a primitive type to another primitive type
* explicitly converting a reference type to another reference type
* some other specific conversions as described in the Java Language Specification.
Such conversions are not always valid and the Casting Conversion checks that a particular
conversion is plausable and complains if it is not.
The specific rules for this conversion are detailed in the CastingConversion
class.
Numeric promotion may be applied whenever an operator is applied to a value.
Numeric Promotion involves:
* promoting byte, short or char to int whenever a unary or binary operator is applied to them
* promoting a primitive type along the sequence from int to long to float to double so that
both operands of certain binary operators are the same type.
Note that the operands of all unary and binary operators are promoted to int
where possible.
Unary operators that promote their operand to int are:
* Neg
- arithmetic negate
* Inv
- bitwise invert
Binary operators that promote both operands to the same type are:
* Add
- arithmetic add
* Subt
- arithmetic subtract
* Mult
- arithmetic multiply
* Div
- arithmetic divide
* Rem
- arithmetic remainder
* Xor
- bitwise exclusive or
* And
- bitwise and
* Or
- bitwise or
The binary operators that do not promote both operands to the same type are:
* SHL
- bitwise shift left
* SHR
- bitwise shift right
* USHR
- bitwise unsigned shift right.
The left and right hand operands are independently promoted to int
if they are of a smaller type.
The specific rules for this conversion are detailed in the NumericPromotion
class.
An automatic StringBuffer
is created when String
s are concatenated using the Add
operator.
The automatic StringBuffer
must be converted back to a String
when it is assigned or used as a
parameter in a method call.
String operator conversion involves:
* If either operand to the Add
operator is a String
an automatic StringBuffer
is created and both operands are appended to it,
e.g. Add(Literal(24), Literal(" degrees"));
* If the left operand to the Add
operator is an automatic StringBuffer
the right operand is appended to it.
String assignment conversion involves:
* An automatic StringBuffer
is converted to a String when it is assigned,
e.g. Add(Literal("Hello"), Literal(" World"));
* An automatic StringBuffer
is converted to a String when it is used as an actual parameter to a method call,
e.g. Call("System.out", "println", Push(Add(Literal("Hello"), Literal(" World"))));
The specific rules for this conversion are detailed in the StringConversion
class.