Why We Can't Do List<Parent> Mylist = Arraylist<Child>();

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

Inheritance and generics from Oracle documentation

How it works from Oracle documentation

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:

  1. ChildClass is-a Parent;
  2. Parent is-a ChildClass.

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



Leave a reply



Submit