I've a problem with argument type mismatch while I'm try to set a values like it is presented using generics in hard section.
public static void Main(String... args) {
int intValue = 1;
开发者_Go百科 long longValue = 1l;
Foo foo = new Foo();
// Easy
foo.setIntValue(intValue);
foo.setLongValue(longValue);
invokeSet(foo, "setIntValue",intValue);
invokeSet(foo, "setLongValue",longValue);
//Medium
foo.setLongValue(intValue);
invokeSet(foo, "setLongValue",intValue);
//Hard
foo.setIntValue((int)longValue); //How to implement this in generic way ?
invokeSet(foo, "setIntValue",longValue);
}
class Foo {
int intValue = 0
long llongValue = 0;
setIntValue(int i) {
this.intValue = i;
}
setLongValue(long l) {
this.longValue = l;
}
}
The thing is that I had to anticipate the explicit cast ?
EDIT
Is there any possibility to anticipate the narrowing primitive conversions might take place and perform it in dynamic way using reflection types class etc.?
FYI:
When we are working with reflection on primitive types they are no longer primitive.
private static void invokeSet(Object bean, String methodName, Object value) throws Exception {
Method m = retriveMethod(bean, methodName);
m.invoke(bean,value); //More or less there is a type wrapper to change primitive to object class
}
EDIT2
One way to achieve this is to change the value to string and then using the string constructor in specific type number pass the string with value.
int intValue = 0;
long longValue = 0l;
Integer intObject = i;
Long longObject = l;
intValue = (int)longValue;
intOBject = new Integer(String.valueOf(longObject)); // intObject = (Integer) longValue; this is not allowed
intObject = longObject.intValue(); //Target to achieve with out writing bad code.
Casting long
to int
is a narrowing primitive conversion that may result in precision loss, therefore it will never be done implicitly. (With the exception of constant expressions, but this is irrelevant in this situation.)
/**
* Function that solve the problem with Numbers and narrowing primitive conversion.
* @param outputType - The type of output
* @param value - Number object to be narrowed.
*/
private static Number NarrovingNumberConversion(Class<? extends Number> outputType, Number value) {
if(value == null) {
return null;
}
if(Byte.class.equals(outputType)) {
return value.byteValue();
}
if(Short.class.equals(outputType)) {
return value.shortValue();
}
if(Integer.class.equals(outputType)) {
return value.intValue();
}
if(Long.class.equals(outputType)) {
return value.longValue();
}
if(Float.class.equals(outputType)) {
return value.floatValue();
}
if(Double.class.equals(outputType)) {
return value.doubleValue();
}
throw new TypeMismatchException();
}
If you want to pass the cast from caller to the class, then overload setIntValue()
:
setIntValue(long l) {
this.intValue = (int) l;
}
but, since you're hiding the narrowing from your callers, be sure this is the right thing to do in all cases.
精彩评论