Reputation: 55
I have a client class which I cannot change.
List<Integer> list1= Arrays.asList(1,2,3);
System.out.println("Total sum is:"+sum(list1));
printlist(list1);
List<Double> list2=Arrays.asList(1.0,2.0,3.0);
System.out.println("Total sum is:"+sum(list2));
printlist(list2);
I have the business logic here
private static Object sum(List<? extends Number> list) {
double sum = 0;
for (Number i: list) {
sum+=i.doubleValue();
}
return sum;
}
So I want to return 6 for integer and 6.0 for a double. How can I do that? I am thinking to typecast sum as int or double based on type but due to type erasure all the info is lost. Can someone help me?
Upvotes: 0
Views: 336
Reputation: 8363
It is dangerous to assume that a Number
subclass instance can be represented with double
. To do this safely, you need to check for all possible types.
@SuppressWarnings("unchecked")
private static <T extends Number> T sum(List<T> list) {
Objects.requireNonNull(list);
if (list.isEmpty() || list.contains(null))
throw new IllegalArgumentException();
Class<T> clazz = (Class<T>) list.get(0).getClass();
if (clazz == Integer.class) {
return (T) (Integer) list.stream().mapToInt(i -> (Integer) i).sum();
}
else if (clazz == Double.class) {
return (T) (Double) list.stream().mapToDouble(i -> (Double) i).sum();
}
/* And other Number subclass types */
// Not possible if all types covered
throw new IllegalStateException();
}
Here is a question/answer related to this.
Upvotes: 0
Reputation: 8813
The objects in the list still have type information associated to them at run time. The only erased types are those of the generics (i.e. List
in your example). The generics are checked at compile time, but are not maintained in the generated bytecode. That means you can use instanceof
to check the contents of the collection:
private static Object sum(List<? extends Number> list) {
Integer integerSum = 0;
Double doubleSum = 0.0;
boolean hasDouble = false;
for (Number i: list) {
if (i instanceof Integer) {
integerSum += i.intValue();
} else {
doubleSum += i.doubleValue();
hasDouble = true;
}
}
if (hasDouble)
return doubleSum + integerSum;
return integerSum;
}
The code has some peculiarities to handle mixed lists, and doesn't handle Long
, Short
, Byte
etc. properly.
Upvotes: 5
Reputation:
Use 'instanceof"
if( i instanceof Double) {
System.out.println("param is a Double");
}
else if( i instanceof Integer) {
System.out.println("param is an Integer");
}
Upvotes: 4