6

Why am i not allowed to do this?

public abstract class A {} public class B extends A {} ... public ArrayList<A> foo() { return new ArrayList<B>(); } 

I changed to public since there are so many people that love to point stupid errors.

Why should i have to write ALL this code. Just to satisfy Java's non-senses?

public List<A> foo() { List<A> aList = new ArrayList<A>(); List<B> bList = new ArrayList<B>(); /* fill bList*/ for (B b : bList) { aList.add(b); } return aList; } 
0

3 Answers 3

13

An ArrayList<B> is not an ArrayList<A>. You can't add any arbitrary A into it, for example. Or as I like to think of it: a bunch of bananas isn't a fruitbowl. When you try to add an apple to a bunch of bananas, it rolls off...

You can use wildcards to make it work though:

public ArrayList<? extends A> foo() { return new ArrayList<B>(); } 

See the Java Generics FAQ for more details.

EDIT: To answer your specific question of why you need to write all that extra code: you don't. Just create an ArrayList<A> within foo() to start with. There's no need to copy the contents of one list to another.

If you still object to Java's behaviour, what would you want to happen with the following code?

// Doesn't compile, fortunately... List<String> strings = new List<String>(); List<Object> objects = strings; objects.add(new Date()); String string = strings.get(0); // Um, it's a Date, not a String... 
Sign up to request clarification or add additional context in comments.

5 Comments

I know wildcards but it messes my superclasses definitions. It's stupid to have to specify 'extends' when you already specified it somewhere else. Whatever ... if i keep on arguing I will be trollified.
@Gabriel: Well, do you want to force the method to return a genuine ArrayList<A> or not? If not, use a wildcard. If so, change the body of the method...
@Gabriel: And my answer still applies. I've explained why you can't just treat an ArrayList<B> as an ArrayList<A> - it wouldn't be typesafe to do so.
@Jon Skeet: typesafe? what are you talking about? if B extends A, i can use B as if it was an A object. There are no castings, no tricky code in the example i posted.
@Gabriel: See the end of my post for an example of what can go wrong if you expect to be able to treat ArrayList<B> as ArrayList<A> just because B extends A.
3

a) For one thing, function does not exist in Java. Java methods have the format

modifiers <type_parameters[,type_parameter]*>? return_type method_name ( [parameter[,parameter]*]? ) [throws exceptiontype[, exceptiontype]*]{ method_body } 

b) Here's how to do it:

public List<? extends A> foo() { return new ArrayList<B>(); } 

c) I changed the method signature to List. It's bad practice to have implementation types in your class' external API if an appropriate interface exists.

Comments

2

because ArrayList<B>() is not ArrayList<A>. it is not extended from it

B extends A doesn't mean ArrayList<B>() extends ArrayList<A>()

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.