This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
I have this code:
ArrayList<A> objects = new ArrayList<A>();
objects.add(new B());
where B is a child class o A. It gives me a compile time error like so:
The method add(A) in the type ArrayList is not applicable for the arguments (B)
This compiles and runs fine:
import java.util.ArrayList;
class A {
}
class B extends A {
}
class Test {
public static void main(String[] args) {
ArrayList<A> arraylist = new ArrayList<A>();
arraylist.add(new B());
}
}
Have another look at your code. Perhaps you got it backwards and A extends B?
Related
This question already has answers here:
What does the question mark in Java generics' type parameter mean? [duplicate]
(6 answers)
When to use generic methods and when to use wild-card?
(9 answers)
Closed 3 months ago.
interface Shape { }
class Circle implements Shape { }
class ShapeContainer<T extends Shape> {
T sh;
public ShapeContainer(T newInstance) {
sh = newInstance;
}
...
}
class Main {
public static void main(String[] a) {
ShapeContainer<Shape> A = new ShapeContainer(new Circle());
ShapeContainer<? extends Shape> B = new ShapeContainer(new Circle());
}
}
What are the pros and cons of declaring the variable as ShapeContainer<Shape> A vs ShapeContainer<? extends Shape> B
What condition should each one be preferred?
This question already has answers here:
How to write a generic method that takes two arguments of the same types in java?
(4 answers)
Closed 3 years ago.
I'm currently building a class with a Pair-Structure. I want to somehow guarantee that each member of the pair has the exact same type.
My question goes in the direction of: How type inference work for method calls?
Following code illustrates my problem:
public class MyClass {
public class MyPair<E> {
private E oldObj;
private E newObj;
MyPair(E pOldObj, E pNewObj) {
oldObj = pOldObj;
newObj = pNewObj;
}
}
public class MyObject {
List<MyPair<?>> listWithPairs = new ArrayList<>();
public <T> void addPair(T oldObj, T newObj) {
listWithPairs.add(new MyPair<T>(oldObj, newObj));
}
}
public static void main(String[] args) {
MyObject pairHolder = new MyObject();
pairHolder.addPair(12L, "asdf");//Call 1
pairHolder.<Long>addPair(12L, 12L);//Call 2
}
}
Is there a way in Java to make Call 1 impossible and always require a type specification like in Call 2?
perhaps by declaring your method like that way
public <T extends Number> void addPair(T oldObj, T newObj) {
listWithPairs.add(new MyPair<T>(oldObj, newObj));
}
This question already has answers here:
Generic extend can't add the same type
(3 answers)
What is PECS (Producer Extends Consumer Super)?
(16 answers)
How to create a generic <T> class so that T extends Collections<String>?
(2 answers)
Generic concept of extends and super
(2 answers)
Closed 4 years ago.
I understand the difference between wildcard ? and type T
However unable to understand below code where in the method m3 I am passing a collection of type String.
Now in the method m3 when I try to add a String to the collection it does not allow me with an exception:
The method add(T) in the type List is not applicable for the arguments (String)
However in method m4 we are extracting an Element from the List and then adding it again.
<1>
if T extends String then in method m3 why is it not allowing to add a String ?
<2>
in method m4 when I am extracting an object from the List - and adding it again - this is allowed.
Is it because when I extract the object is of type T and hence when adding it is allowed ?
Kind of strange behavior - I think I am getting a faint idea of why this happens but would be great to hear thoughts from others ?
package generics.wildcardVsT;
import java.util.ArrayList;
import java.util.List;
public class Ex1 {
public static void main(String[] args) {
System.out.println("hello");
List <String> list1 = new ArrayList<String>();
List <String> list2 = new ArrayList<String>();
List <String> list3 = new ArrayList<String>();
List <String> list4 = new ArrayList<String>();
list4.add("abc");
m1(list1);
m2(list2);
m3(list3);
m4(list4);
}
/** no compilation errors **/
public static void m1(List<String> list) {
list.add("abc");
}
/** this will not compile because of wildcard - this is understood **/
public static void m2(List<? extends String> list) {
list.add("abc");
}
/** this is not understood - why will this not compile ? **/
public static <T extends String>void m3(List<T> list) {
list.add("abc");
}
/** strangely this actually compiles ! **/
public static <T extends String>void m4(List<T> list) {
list.add(list.get(0));
}
}
m3 takes T, some class that happens to extend String but list.add("abc"); is adding a String to a list of T
T could be class SuperCoolString extends String { ... } in which case list.add("abc"); would be wrong.
m4 is just adding a T element to list
I don't think that you can/should normally extend String but that's not really important here ...
This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
What are my options, if I what the following code to work?
class Garage<X>{}
class Vehicle {}
class Car extends Vehicle {}
class Bike extends Vehicle {}
class A {
public static void main(String[] args) {
Garage<Car> car = new Garage<>();
Garage<Bike> bike = new Garage<>();
Garage<Vehicle> vehicle = new Garage<>();
//what are the options to do this?
vehicle=car;
vehicle=bike;
}
}
What I'm after is to try upcast(?) car and bike to vehicle. Is this even possible with this kind generic class type?
In order to do what you desire, you need to change
Garage<Vehicle> vehicle = new Garage<>();
to
Garage<? extends Vehicle> vehicle = new Garage<>();
This question already has answers here:
Difference between <? super T> and <? extends T> in Java [duplicate]
(14 answers)
Closed 6 years ago.
import java.util.*;
class Test
{
public static class Base
{
}
public static class Derived1
extends Base
{
}
public static class Derived2
extends Base
{
}
public static void main (String[] args)
{
//Example1.
List<? extends Base> e = new ArrayList<Base>();
e.add(new Derived1()); //this won't compile
//Example2.
List<? super Base> b = new ArrayList<Base>();
b.add(new Derived1()); //this compiles
}
}
List<? super Base> b can be assigned either a List<Base> or a List<Object>. A Derived1 instance can be added to both, so the b.add(new Derived1()) statement passes compilation.
On the other hand, List<? extends Base> e may be assigned a List<Derived2>, so the compiler doesn't allow to add a Derived1 instance to it.
See What is PECS (Producer Extends Consumer Super)?.
If you are adding something to a List<T>, then the list is a consumer of the thing you are adding. As such, the type of the list elements, T, must be the same as the thing you are trying to add or a supertype.