Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an Iterable<? extends String> ever contain anything other than Strings?

Tags:

java

generics

I am quite new to Java, it seems to me that

Iterable<? extends String>

can only ever be an

Iterable<String>

since String is final, and cannot be derived from. Am I wrong?

like image 755
endian Avatar asked Mar 14 '23 22:03

endian


2 Answers

Your observation is true and valid, not much to add to it.

So I'll anticipate the next question (as I did in my comment, just as an answer for formatting reasons): why would one use Iterable<? extends String> if the only possible definition would be Iterable<String>?

To be honest: with Iterable you don't have any methods that add anything so it wouldn't make much sense. But lets replace Iterable with List.

What's the difference between List<? extends String> and List<String>?

With List<String> the compiler knows that the list is meant to contain String objects and thus it would allow you to call add("newStringLiteral").

But with List<? extends String> the compiler isn't so sure anymore. Of course we can't extend String but the compiler doesn't check that and hence would have to assume it were possible.

Now let's pretend we were able to write a class SpecialString extends String. If we'd call List<? extends String> l = new ArrayList<SpecialString>() we'd want to restrict the list to only contain SpecialString objects. But the compiler only sees List<? extends String> so it assumes there might be a restriction on the actual type and thus considers add("newStringLiteral") to be an error.

So using List<? extend String> would basically make the parameter a list you can't add anything to (just read and remove).

like image 54
Thomas Avatar answered Apr 26 '23 15:04

Thomas


The other answers already explained that your assumption regarding ? extends String is correct. But there is a catch when you ask

Can an Iterable<? extends String> ever contain anything other than Strings?

You can easily construct a Iterable<String> which can contain any object, not just Strings:

ArrayList a = new ArrayList();
a.add(Boolean.TRUE);

@SuppressWarnings("unchecked")
Iterable<String> i = a; 

Object elem = i.iterator().next();
assert elem == Boolean.TRUE;
like image 43
wero Avatar answered Apr 26 '23 16:04

wero