简体   繁体   中英

Is there an elegant way to convert List<Double> into List<Number>?

I have a function whose arguments are:

 myFn(String, List<Number>, List<Number>)

The calling function has two objects of List which I want to use as the 2nd and third argument of the function. I get the compilation error:

The method myFn(String, List<Number>, List<Number>) in the type MyLib is not applicable for the arguments (String, List<Double>, List<Double>)

Is there an easy way to overcome this? Is there an easy way to cast the list of Double into a List of Number?

You cannot cast List<Double> to a List<Number> because the following code would break your List<Double>

List<Double> list = new List<Double>();
List<Number> list1 = list; // This does not work
list1.add(new Integer(0));
Double d = list.get(0);// Hu-hoh you received an Integer, not a Double!!
List<? extends Number> list2 = list; // This does work

What you could do, is change

myFn(String, List<Number>, List<Number>)

to

myFn(String, List<? extends Number>, List<? extends Number>)

将myFn定义更改为<T extends Number> myFn(String, List<T>, List<T>, Class<T> type) ,您可以将其称为myFn(String, List<Double>, List<Double>, Double.class)

If you know that the list won't get modified by the method, just use

List<Number> unmodifiableView = Collections.unmodifiableList(doubleList);

which runs in constant time and returns a view. It's perfectly type-safe, efficient, and legal -- so long as you know the list won't get modified.

If you can't change the myFn method, then cheating is an option:

private <returntype> myFnAdapter(String s , List<Double> l1Double, List<Double> l2Double) {

  // the following lines do create warnings
  // it's safe, because all list items always extend Number.
  List l1TypeErased = l1Double; 
  List<Number> l1Number = l1TypeErased;

  List l2TypeErased = l2Double;
  List<Number> l2Number = l2TypeErased;

  return myFn(s, l1Number, l2Number);
}

You should see some warnings, that's all. But we know that we get lists of Double s and that all items of those lists extend Number , so it won't cause trouble at runtime. Just add a comment to explain the type erasure. It's cheaper then copying all values to new lists.

You can use

myFn(String, List<? extends Number>, List<? extends Number>) 

or call your function with

myFn(String, (List) list1, (List) list2); // produces a warning. 

You cannot cast Collections like this. This Java tutorial gives you the full explanation.

As a solution, where you are calling the method just create a new List with the Double List as a parameter:

List<Double> doubleList = new ArrayList<Double>();

myFn(new ArrayList<Number>(doubleList));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM