Page 1 of 1
About Question enthuware.ocpjp.v7.2.1265 :
Posted: Tue Aug 19, 2014 11:20 am
by bluster
Apologies for what is most likely a stupid question. (I checked the code in the given answer and of course the compiler agrees).
This is the right answer:
List<String> list = new ArrayList<>();
list.add("A");
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
My confusion is with the "? extends String" in the attribution for list2, on this line:
Code: Select all
List<? extends String> list2 = new ArrayList<>();
From my clearly incorrect reading, it would seem that when the ArrayList "list" gets asked to add "list2" on the last line, the fact that "list2" is typed to <? extends String> while "list" is typed to <String> would prevent an addition, restricting access to read-only methods such as get().
Can someone explain why it works. Thanks.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Tue Aug 19, 2014 7:57 pm
by admin
It is fine because anything that extends String is-a String. So a List of Strings can contain any subclass of String.
However, list2.addAll(list) will not work because list2 is a List of something that extends String. So you can't put String objects in it because you don't know the exact class that list2 is meant to contain.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Wed Aug 20, 2014 12:08 pm
by bluster
Thanks for the reply!
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Sat Aug 08, 2015 12:43 pm
by gk_javauser
How is it possible to extend String? I thought it was a final class.
Thanks.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Sat Aug 08, 2015 6:48 pm
by admin
You cannot extend String. It is a hypothetical situation.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Fri Dec 04, 2015 3:55 pm
by fariz.siracli
second option compiles and run without exception.
List<String> list = new ArrayList<>();
list.add("A");
list.addAll(new ArrayList<>());
But in explanation it says "In this option, the last line will not compile because list.addAll() method expects Collection<? extends String> and so the compiler cannot infer the generic type for ArrayList."
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Fri Dec 04, 2015 8:31 pm
by admin
It compiles with Java 8 but not with with Java 1.7.
-Paul.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Mon Dec 21, 2015 2:04 pm
by Sergiy Romankov
Please help, I don`t get it:
Normally with generics inheritance doesn`t work in this way, I mean
ArrayList<Object> list = new ArrayList<String>();//ERROR
but in this case, list adds list2, which is actually can be sybtype class of String.
(String is final, but in theory ???)
List<String> list = new ArrayList<>();
list.add("A");
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Mon Dec 21, 2015 2:46 pm
by admin
Sergiy Romankov wrote:Please help, I don`t get it:
Normally with generics inheritance doesn`t work in this way, I mean
ArrayList<Object> list = new ArrayList<String>();//ERROR
but in this case, list adds list2, which is actually can be sybtype class of String.
(String is final, but in theory ???)
List<String> list = new ArrayList<>();
list.add("A");
List<? extends String> list2 = new ArrayList<>();
list.addAll(list2);
Let's assume for a moment that String is not final. So now,
list is a List of Strings and list2 is a List of someclass that extends String lets say SpecialString.
If you add elements of list2 to list, does it really affect the consumers of the elements of list? No. Because they can still consume the elements of list as if they were Strings. That is why it is allowed.
You may want to read this :
viewtopic.php?f=2&t=473
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Thu Nov 23, 2017 8:30 am
by phusztek
Although this is valid code but it is not a good usage of generics because when you do new HashMap(), you create a raw HashMap and it will produce a warning at compile time. Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond operator. i.e. You must do new HashMap<>() in this case.
Actually it is not clear for me because I can't see any difference apart from the compile warning between these two declaraiotn:
Map<String, String> myMap = new HashMap();
Map<String, String> myMap2 = new HashMap<>();
When I try to add an String - Integer entry, I get teh compile error in both cases:
myMap.put("2", 5);
myMap2.put("2", 5);
The method put(String, String) in the type Map<String,String> is not applicable for the arguments (String, int)
Based on this it seems that myMap is treated as generic as well which sounds reasonable for me bacause of the reference type. So the only difference is the warning?
Thanks!
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Sat Feb 13, 2021 5:58 pm
by OliviaJohnson
I don't know why this option is allowed to compile?
Code: Select all
List<String> list = new ArrayList<>(); //2
list.add("A"); //2
list.addAll(new ArrayList<>()); //3
I thought the ArrayList object on line 3 would be typed to ArrayList<Object>, so it should not fit into a List<String>.
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Mon Feb 15, 2021 4:55 am
by admin
new ArrayList<>() uses the diamond operator i.e. <>. It is automatically resolved by the compiler to the appropriate type as required by the context. So, in this case new ArrayList<>() will be interpreted by the compiler as new ArrayList<String>()
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Wed Dec 27, 2023 10:11 am
by yulinxp
Admin, can you please help? I have same question here... Even though compile gives raw use warning, it still uses lhs type to prevent entering wrong info.
phusztek wrote: ↑Thu Nov 23, 2017 8:30 am
Although this is valid code but it is not a good usage of generics because when you do new HashMap(), you create a raw HashMap and it will produce a warning at compile time. Note that to take advantage of automatic type inference during generic class instantiation, you must specify the diamond operator. i.e. You must do new HashMap<>() in this case.
Actually it is not clear for me because I can't see any difference apart from the compile warning between these two declaraiotn:
Map<String, String> myMap = new HashMap();
Map<String, String> myMap2 = new HashMap<>();
When I try to add an String - Integer entry, I get teh compile error in both cases:
myMap.put("2", 5);
myMap2.put("2", 5);
The method put(String, String) in the type Map<String,String> is not applicable for the arguments (String, int)
Based on this it seems that myMap is treated as generic as well which sounds reasonable for me bacause of the reference type. So the only difference is the warning?
Thanks!
Re: About Question enthuware.ocpjp.v7.2.1265 :
Posted: Wed Dec 27, 2023 8:38 pm
by admin
The warning generated by the compiler is only for the assignment of new HashMap(); to the myMap variable.
myMap is treated as generic because that is how it is declared. There is no issue with the variable itself.