0

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;
   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.
5
  • What do you mean by "in a generic way"? If you don't have the explicit cast, the compiler correctly complains, because you're trying to force a long into an int. What do you want it to do? Commented Feb 8, 2011 at 14:29
  • What is "invokeSet"? A function to set a value on your bean using reflection? Can you be more specific in your question? Commented Feb 8, 2011 at 14:30
  • @Oli Using reflection. My error. @Luciano, yes it is a function to set the value to bean using reflection. Commented Feb 8, 2011 at 14:33
  • It's really not clear what you are trying to do here. Can I suggest you post the code that you would like to be able to write. If bizclop didn't answer this. Commented Feb 8, 2011 at 14:34
  • @DJClayworth, the code is something that i need to came up with. Commented Feb 8, 2011 at 14:43

3 Answers 3

4

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.)

Sign up to request clarification or add additional context in comments.

4 Comments

Thats is true, never then less when such situation occur in the code it should not finish with an exception, but using the narrowing primitive conversion convert the number and proceed.
@Vash That depends on the application really. True, Java won't throw an exception on over- or underflow but you might want your application to do so. For example I wouldn't trust a financial application that dooesn't throw an exception on overflows.
Totaly right, i wanted to eddit my comment but was to late, instead of writing generally i should wrote in my code this should be handled this way.
@Vash Fair enough. :) But you still have to cast it explicitly somewhere, there's no getting away from it. Or you can trick autoboxing into doing it for you: Number num = l; this.intvalue = num.intValue();
4
 /**
     * 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();

    }

Comments

1

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.

2 Comments

@Yishai - thanks for the edit. Not enough coffee yet this morning :-)
I cant do this because i will don't know on which method this code will be used. But thank for you point of view.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.