List cannot be converted to List [duplicate] - java

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 3 years ago.
Why this is not allowed?
error: incompatible types: List<TextBook> cannot be
converted to List<Book>
process(textBooks);
import java.util.*;
class Book {}
class TextBook extends Book {}
public class Sample {
public static void process(List<Book> books) {}
public static void main(String[] args) {
List<Book> books = new ArrayList<>();
process(books);
System.out.println(“OK”)
List<TextBook> textBooks = new ArrayList<>();
process(textBooks); # what is the problem in this statement?
System.out.println(“OK”);
}
}

You are trying to pass a List<TextBook> into a method whose signature expects a List<Book>. This fails at compile time, because if the Java compiler were to allow it, then your process() method might try to use the contents of the list in the wrong way. Instead, use this version of process():
public static void process(List<? extends Book> books) {}
Now you may pass in any instance of Book, or any subclass of Book.

This is not allowed because you started out with an arraylist of Textbook. However you passed it to process as a list of Book. The process function could add something which is not a textbook to the list. At this point your original list would not be an arraylist of Textbook.

Related

Why I can not overload this method? [duplicate]

This question already has answers here:
Method has the same erasure as another method in type
(8 answers)
Closed 1 year ago.
Here is the code:
public class Test {
private static void print(List<Plant> plants) {
}
private static void print(List<Animal> animals) {
}
}
class Animal {
}
class Plant {
}
When I want to overload print method in Test class for Animal and Plant lists, the compiler says that "both methods have same erasure". When I research "method erasure", I could not relate it to my situation.
Because both List<Plant> and List<Animal> are List (raw type) using type erasure, so compiler sees 2 print methods are identical.

The component type of a list turns to be String which actually is declared to be Duration [duplicate]

This question already has answers here:
What is the concept of erasure in generics in Java?
(7 answers)
Closed 2 years ago.
I have a customized object including fields:
private List<Duration> durations;
private Duration single;
When debugging, I evaluate the following expression and the result is java.lang.String which is different from the declared type. Why?
durations.get(0).getClass()
As a comparison, the class of single is Duration, same as declared type.
If any help, I got the data deserialized from MySQL.
getClass gives you the runtime class of the Object.
Here is a short example:
import java.util.ArrayList;
import java.util.List;
class T {
String sam = "jack";
public String getSam() {return sam;}
public void setSam(String sam) {this.sam = sam;}
}
public class Test {
public static void main(String[] args) {
List<T> list = new ArrayList<T>();
T t = new T();
list.add(t);
Class<? extends T> c = list.get(0).getClass();
System.out.println(list.get(0).getSam().getClass());
}
}
Which means you can't operate normal operations on the variable as you do when you initialize a class variable with the keyword new.
So, t.getSam() is possible whereas c.getSam() is invalid.
If you need further clarification, then provide the full class Duration and what objective that you are looking for.

Java - Using "<? extends Interface>" vs Interface only [duplicate]

This question already has answers here:
Whats the use of saying <? extends SomeObject> instead of <SomeObject>
(5 answers)
Closed 6 years ago.
I have seen some code as follows
public interface IBean {
}
and its usage at some places as
public void persist(List<? extends IBean> beansList) {
}
However same can achieved with following code
public void persist(List<IBean> beansList) {
}
So what is the difference between both methods, both are excepting objects that must inherit IBean interface?
Here are the bean classes
public class Category implement IBean {
//related fields
}
public class Product implement IBean {
//related fields
}
You can pass a List<Category> to public void persist(List<? extends IBean> beansList), but you cannot pass a List<Category> to public void persist(List<IBean> beansList).
On the other hand, you can pass a List<IBean> to both methods.
The reason is that generics are invariant. This means for example that you can't use a List<Integer> where a List<Number> is expected.
But when turning to wildcards, you can circumvent that restriction. Therefore, when you really have a List<Product> you will not be able to pass that into a method that expects List<IBean> - you would have to somehow convert the list first. To be precise: you would do a "hard" cast; as there is no point in "converting" generic lists, as type erasure kicks in at runtime anyway!
By using the wildcard on the method definition, you can allow for passing Lists that use "real" sub classes of the extended type; without the need of ugly casts.

Java: Why can't List<Integer> be passed to function (List<Number>)? [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 6 years ago.
Why can't we pass List<X> to a function which has List<superclass of X>? For a normal variable this is possible.
Consider the MWE below. Why can we pass Integer to a function with a Number argument, and can't we not pass List<Integer> to List<Number>?
Questions:
How can I efficiently/nicely (so without constructing a new List) work around this?
What is the rationale of this language design decision?
MWE:
import java.util.ArrayList;
import java.util.List;
public class Tester {
public static void main(String[] args) {
Integer i = new Integer(2);
// This works fine.
processNumber(i);
List<Integer> l = new ArrayList<Integer>();
// ERROR "The method processNumberList(List<Number>) in the type
// Tester is not applicable for the arguments (List<Integer>)"
processNumberList(l);
}
private static void processNumber(Number n) {
}
private static void processNumberList(List<Number> l) {
}
}
Replace your declaration with this:
private static void processNumberList(List<? extends Number> l) {...}
How can I efficiently/nicely (so without constructing a new List) work
around this?
Simply change the signature of your method as next:
private static <T extends Number> void processNumberList(List<T> l) {
}

Up-casting template argument types [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 7 years ago.
Why does Java not support automatic up-casting for template argument types?
For example, the following class will not compile unless the newly created Derived instance will be manually casted to a Base instance:
public class Example implements Iterable<Base> {
#Override
public Iterator<Base> iterator() {
return Arrays.asList(new Derived()).iterator();
}
private class Base {
}
private class Derived extends Base {
}
}
No need to cast.
The problem here is that Arrays.asList(new Derived()) naturally tries to create a List<Derived>,
and then calling .iterator() on a List<Derived> naturally gives an Iterator<Derived>,
which is not a sub-type of Iterator<Base>, so you get a compilation error.
You can specify that you want a List<Derived>, using Arrays.<Base>asList.
This works,
because you can certainly put a Derived instance into a List<Base>,
and then calling .iterator() on a List<Base> naturally gives an Iterator<Base>.
class Example implements Iterable<Base> {
#Override
public Iterator<Base> iterator() {
return Arrays.<Base>asList(new Derived()).iterator();
}
}

Categories

Resources