This is why I don't like to rely on auto-boxing. Java Collections cannot store primitives (for that you will need a third party API like Trove). So, really, when you execute code like this:
hashSet.add(2);
hashSet.add(5);
What is really happening is:
hashSet.add(new Integer(2));
hashSet.add(new Integer(5));
Adding a null to the hash set is not the problem, that part works just fine. Your NPE comes later, when you try and unbox your values into a primitive int:
while(it.hasNext()){
int i = it.next();
System.out.print(i+" ");
}
When the null value is encountered, the JVM attempts to unbox it into an the int primitive, which leads to an NPE. You should change your code to avoid this:
while(it.hasNext()){
final Integer i = it.next();
System.out.print(i+" ");
}
Answer from Perception on Stack OverflowThis is why I don't like to rely on auto-boxing. Java Collections cannot store primitives (for that you will need a third party API like Trove). So, really, when you execute code like this:
hashSet.add(2);
hashSet.add(5);
What is really happening is:
hashSet.add(new Integer(2));
hashSet.add(new Integer(5));
Adding a null to the hash set is not the problem, that part works just fine. Your NPE comes later, when you try and unbox your values into a primitive int:
while(it.hasNext()){
int i = it.next();
System.out.print(i+" ");
}
When the null value is encountered, the JVM attempts to unbox it into an the int primitive, which leads to an NPE. You should change your code to avoid this:
while(it.hasNext()){
final Integer i = it.next();
System.out.print(i+" ");
}
1) Are you sure about you get compile time error? I don't think so, I guess the code throws NPE at runtime at
int i = it.next();
2) As a matter of fact java.util.Set interface does not forbid null elements, and some JCF Set implementations allow null elements too:
Set API - A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.
HashSet API - This class permits the null element.
LinkedHashSet API - This class provides all of the optional Set operations, and permits null elements
TreeSet.add API - throws NullPointerException - if the specified element is null and this set uses natural ordering, or its comparator does not permit null elements
Firstly, you never set an object to null. That concept has no meaning. You can assign a value of null to a variable, but you need to distinguish between the concepts of "variable" and "object" very carefully. Once you do, your question will sort of answer itself :)
Now in terms of "shallow copy" vs "deep copy" - it's probably worth avoiding the term "shallow copy" here, as usually a shallow copy involves creating a new object, but just copying the fields of an existing object directly. A deep copy would take a copy of the objects referred to by those fields as well (for reference type fields). A simple assignment like this:
ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = list1;
... doesn't do either a shallow copy or a deep copy in that sense. It just copies the reference. After the code above, list1 and list2 are independent variables - they just happen to have the same values (references) at the moment. We could change the value of one of them, and it wouldn't affect the other:
list1 = null;
System.out.println(list2.size()); // Just prints 0
Now if instead of changing the variables, we make a change to the object that the variables' values refer to, that change will be visible via the other variable too:
list2.add("Foo");
System.out.println(list1.get(0)); // Prints Foo
So back to your original question - you never store actual objects in a map, list, array etc. You only ever store references. An object can only be garbage collected when there are no ways of "live" code reaching that object any more. So in this case:
List<String> list = new ArrayList<String>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
map.put("Foo", list);
list = null;
... the ArrayList object still can't be garbage collected, because the Map has an entry which refers to it.
To clear the variable
According to my knowledge,
If you are going to reuse the variable, then use
Object.clear();
If you are not going to reuse, then define
Object=null;
Note: Compare to removeAll(), clear() is faster.
Please correct me, If I am wrong....
Better than extending a particular implementation, you can easily write a proxy implementation of Set that checks for nulls. This analogous to Collections.checkedSet. Other than being applicable to any implementation, you can also be sure that you have overridden all applicable methods. Many flaws have been found by extending concrete collections which then have additional methods added in later versions.
I would say use composition instead of inheritance... it might be more work but it'll be more stable in the face of any changes that Sun might make to the Collections Framework.
public class NoNullSet<E> implements Set<E>
{
/** The set that is wrapped. */
final private Set<E> wrappedSet = new HashSet<E>();
public boolean add(E e)
{
if (e == null)
throw new IllegalArgumentException("You cannot add null to a NoNullSet");
return wrappedSet.add(e);
}
public boolean addAll(Collection<? extends E> c)
{
for (E e : c) add(e);
}
public void clear()
{ wrappedSet.clear(); }
public boolean contains(Object o)
{ return wrappedSet.contains(o); }
... wrap the rest of them ...
}
Note that this implementation does not depend on addAll calling add (which is an implementation detail and should not be used because it cannot be guaranteed to remain true in all Java releases).
Why do you set variables to null? instead just blank?
String x;
VS.
String x = null;
The simplest way would be to enumerate the Set and check for nulls.
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) throw new NullPointerException("plugIns");
for (PlugIn plugIn : plugIns) {
if (plugIn == null) throw new NullPointerException("plugIns null element");
}
}
Create a HashSet from plugIns and check for the existence of null
public void scan(Set<PlugIn> plugIns) {
if (plugIns == null) throw new NullPointerException("plugIns");
Set<PlugIn> copy = new HashSet<PlugIn>(plugIns);
if (copy.contains(null)) {
throw new NullPointerException("null is not a valid plugin");
}
}