Why we can't do ListParent mylist = ArrayListchild();
Suppose we could. Then this program would have to be fine:
ArrayList<Banana> bananas = new ArrayList<Banana>();
List<Fruit> fruit = bananas;
fruit.add(new Apple());
Banana banana = bananas.get(0);
That's clearly not type safe - you've ended up with an apple in the collection of bananas.
What you can do is:
List<? extends Fruit> fruit = new ArrayList<Banana>();
this is safe, because the compiler won't then let you try to add to the list of fruit. It knows that it's a list of some kind of fruit, so you could write:
Fruit firstFruit = fruit.get(0);
but it doesn't know what exact kind of fruit it's a list of, and make sure you can't do the wrong thing.
See the Java generics FAQ another explanation.
Why does the field declaration of a list in a child class make it null?
In general, subclass initialization doesn't happen until superclass initialization is complete, to avoid having the subclass implementation see superclass components in an inconsistent state. The initialization of B
's myList
field doesn't look like it's attached to any constructor, but it actually happens in any B
constructor immediately after the superclass constructor call. This field is a completely separate field from the one declared by the superclass.
When A
's constructor tries to call self.init
, it gets the override from B
. B
's override tries to append to the private myList
field in B
, but that field isn't initialized yet.
It's generally best to avoid calling overrideable methods in a constructor.
Swap two children in method defined by ArrayList? extends Parent
It seems like it should be possible seeing as how we can guarantee that the object returned by passedList.get() is the right type to belong in the arraylist.
We can tell that it is correct, because we can look at the code and trace back to where swap
comes from. But the compiler cannot tell, because it is not guaranteed by the language. You are trying to put a Parent
in a List<? extends Parent>
, and the list may be some subtype, like List<Child>
.
Instead, you can accomplish this with wildcard capture:
static <P extends Parent> void swap(List<P> list, int i, int j) {
P temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
This lets you express that the type of temp
is the same as the actual type argument to list
.
See also:
- Wildcard Capture and Helper Methods
Java: Can't to generic List? extends Parent mylist
I believe you're looking for a method that takes a list, adds something to it, and then returns the list. The list is generic and you want the return type to match the type of the parameter.
Here's how you do it, in the general case:
public <T extends Parent> List<T> myfunction(List<T> myList) {
... // Add something to myList
return myList;
}
Specifically, you're trying to add new Child()
to myList
. This cannot work. myfunction()
may be called with many kinds of lists, whereas adding new Child()
can only work if the list is either a List<Parent>
or a List<Child>
. Here's an example for a List of different kind:
public static class Parent {}
public static class Child extends Parent {}
public static class OtherChild extends Parent {}
public <T extends Parent> List<T> myfunction(List<T> myList) {
myList.add(new Child());
return myList;
}
myfunction(new ArrayList<OtherChild>());
In the last line, myfunction()
is called with a List of OtherChild
objects. Obviously, adding a Child
object into such a list is illegal. The compiler prevents that by rejecting the definition of myfunction()
Appendix
If you want myfunction()
to be able to add an element to myList
you need to use a factory (since Java does not allow new T()
where T is a type parameter - due to type erasure). Here's how myfunction()
should look like:
public interface Factory<T> {
public T create();
}
public <T extends Parent> List<T> myfunction(List<T> myList,
Factory<? extends T> factory) {
myList.add(factory.create());
return myList;
}
And now, its usage:
public static class ChildOfOtherChild extends OtherChild {}
myfunction(new ArrayList<OtherChild>(), new Factory<ChildOfOtherChild>() {
@Override public ChildOfOtherChild create() { return new ChildOfOtherChild(); }
});
}
JAVA: How to compare child class in a List
The issue is with your if statement.
if(a instanceof Bear);
return true;
You have ended your if statement with a semicolon which means its an empty statement and the next line return true
is always executed. Remove the semicolon after the if statement.
Read more here: Semicolon at end of 'if' statement
how to use inheritence in ArrayList in java?
Inheritance in Generics works a bit differently.
In Java ArrayList<QGNode>
is not a subtype of ArrayList<GNode>
.
Generics in Java and Inheritance
ArrayList and Polymorphism
ChildClass
is-a Parent
, but ArrayList<ChildClass>
is-not-an ArrayList<Parent>
. If you consider this code, it shoud be clear why:
ArrayList<ChildClass> a3 = new ArrayList<>();
foo(a3);
ChildClass c = a3.get(0);
...
static void foo(ArrayList<Parent> obj) {
obj.add(new Parent());
}
If the above code happened to compile without error, it would be type-unsafe and actually fail at runtime with ClassCastException
.
So, for the relation "ArrayList<ChildClass>
is-a ArrayList<Parent>
" to actually make sense, these two facts would have to be simultaneously true:
ChildClass
is-aParent
;Parent
is-aChildClass
.
In general, that can be true only if ChildClass
is the same type as Parent
, under a different name. So we arrive at the real rule Java applies, which is called type invariance: it neither holds that ArrayList<ChildClass>
is-an ArrayList<Parent>
, nor that ArrayList<Parent>
is-an ArrayList<ChildClass>
.
Generics and Inheritance?
This is a very common misunderstanding. The fact the Child extends Parent does not make List<Child>
extend List<Parent>
. Sounds very unintuitive in cases like this one, but there it is. From the java tutorial:
Given two concrete types A and B (for example, Number and Integer),
MyClass< A> has no relationship to MyClass< B>, regardless of whether or
not A and B are related. The common parent of MyClass and
MyClass is Object.
Read this for details.
As for adding to the list, the short answer is: Imagine you have a another class Child2 extends Parent
, now, the list you are receiving as a parameter at method2(List<? extends Parent> list1)
could be either a List<Child1>
or a List<Child2>
. Thus, given that the second case is possible, adding a Child1 object is not type safe.
Now, the fact that you can't add does not mean that you can't do other useful stuff, like getting the size, etc.
Using parent classes in Java generics parameters
Here's the code which will compile successfully:
public static <B> void main(String[] args) {
Map<String, ? extends Collection<B>> map1 = test();
Map<String, ? extends List<B>> map2 = test();
Map<String, ArrayList<B>> map3 = test();
}
private static <B> Map<String, ArrayList<B>> test() {
return null;
}
You need to add ? extends Collection<B>
and ? extends List<B>
because writing ? extends Collection
means that the Object
which forms the value
of the Map
is a sub type
of Collection
class and thus the test()
will be called as it also returns a Map
whose value
is ArrayList
type, which is actually a sub type
of Collection
Also note that you need to add <B>
in the signatures of main
and test()
Hope it helps!
Related Topics
Apache Httpclient Digest Authentication
How to Change Size of Title's Text on Action Bar
Android - How to Create Clickable Listview
Java.Lang.Classnotfoundexception: Org.Postgresql.Driver, Android
Cannot Resolve Method Getmap()
Polyline Is Not on the Roads: It Goes Straight from One Point to Other
Firebase Realtime Database Search by Word in Between the Query
Using Asynctask with Passing a Value
Google Maps API and Custom Polyline Route Between Markers
Simple Date Format Returns Wrong Date Intermittently
Android Buildscript Repositories: Jcenter VS Mavencentral
How to Activate "Share" Button in Android App
Adding Header to All Request with Retrofit 2
Issue: Passing Large Data to Second Activity
Android - Imageloader Must Be Init with Configuration Before Using in Uil
Android Java.Net.Unknownhostexception: Host Is Unresolved (Strategy Question)
Install Xlsx and Rjava on MACos Mavericks 10.9.5
Android JSON Parsing of Multiple JSONobjects Inside JSONobject