• Post Reply Bookmark Topic Watch Topic
  • New Topic

Searching/Removing arbitrary object in Generics  RSS feed

 
Ranch Hand
Posts: 361
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I came across the following statement in Java SCJP 6.0 Khalid Mughal.


Note that we can only add an object of a specific type (E). However, a collection
allows us to determine whether it has an element equal to any arbitrary object,
or remove an element that is equal to any arbitrary object.



I tried the following program.



I am not clear as to why the Generics allow Searching/Removing arbitrary object, when in the above case it can only store String.

Please advise.
 
Bartender
Posts: 11445
18
Android Eclipse IDE Google Web Toolkit Java Mac Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Naresh Chaurasia wrote:
I am not clear as to why the Generics allow Searching/Removing arbitrary object, when in the above case it can only store String.

Why shouldn't it allow?
Consider a list of friends. Imagine they are stored as 'Friend' object.
Suppose you are no longer on talking terms with someone and you do not consider him as your 'friend' How would you remove him from the list if this search/remove ability did not exist?

Does this clear your doubt or did you mean something else?
 
Naresh Chaurasia
Ranch Hand
Posts: 361
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I mean in String array, I should be only allowed to search for String, and not integers
 
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why? What is wrong with this sort of code?And what happens if you change the two occurrences of the word String to Object? Why should that not work?
 
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell: What is wrong with that is that a List<String> never contains Integer objects. If it does, something is very wrong... it should not even be possible to add anything else than String objects to a List<String>. I know it's possible because of type erasure and when you do casts, but... And an array (instead of a List) of Strings can really never contain an Integer, because the JVM checks at runtime what you put into an array. If you try to put an Integer in a String[] you will get an ArrayStoreException.

Also, you should never create different classes which can be equal() to each other. It will cause you a lot of headaches...

Naresh: If you look at interface java.util.List<E> you'll see that it has a contains() method which takes an Object instead of an E.

This is because of backward compatibility. Generics have not been in the Java language since the start. They were added in Java 5. The collections interfaces and classes have been modified to support generics, but not all changes could be made without breaking backward compatibility. So, Oracle (or Sun at that time) decided to not change the method contains(Object obj) to contains(E obj), because it might have caused a compile error when compiling old code with the new Java version.

If they would redesign the API without regard for backward compatibility, there would probably have been a method contains(E obj) instead, but that's never going to happen - Oracle takes backward compatibility very seriously.
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you.

Can you actually write a List#contains(E e) method? Would't it count as override‑equivalent with contains(Object)? In which case your String[] and your List<String> would be found not to contain that Integer.
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 16060
88
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oracle couldn't just add a contains(E) method:

Error:

C:\Temp>javac MyList.java
MyList.java:5: error: name clash: contains(E) and contains(Object) have the same erasure
boolean contains(E e);
^
where E is a type-variable:
E extends Object declared in interface MyList
1 error

 
Bartender
Posts: 2087
44
Firefox Browser IntelliJ IDE Java Linux Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jesper de Jong wrote:Oracle couldn't just add a contains(E) method


They could have added a method that takes E with slightly different name and deprecate contains.

But why bother? Until today I was not aware that contains takes Object! And I've been using it a lot...
 
Campbell Ritchie
Marshal
Posts: 56600
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I still think contains(Object) is simpler. It might work better without erasure, then you could implement it like this:-
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!