EdW
EdW

Reputation: 11

Java generics: Set vs. Set<Object>

In Java, what's the difference between declaring a variable a Set versus a Set<Object>? Shouldn't the two be equivalent? Why is there a compile-time error when one assigns a Set<Object> variable to a Set?

Upvotes: 1

Views: 4678

Answers (5)

paulsm4
paulsm4

Reputation: 121799

No: Set<> is generic, and Set isn't. Logically, Set<Object> might be equivalent to Set (implicitly, Set of Object), but the bytecode is quite different :)

Suggestion:

Run javap command on your sample program and verify this for yourself.

Upvotes: 1

brabster
brabster

Reputation: 43590

The two are not equivalent. When you assign a Set<Object> you increase the compilers' ability to detect unsafe manipulation of the set that would otherwise fail at runtime.

This is covered in Josh Bloch's excellent Effective Java, Second Edition, from which this example is unashamedly inspired:

public static void main(String[] args) {
    List<String> typesafeStrings = new ArrayList<String>();
    unsafeAdd(typesafeStrings, new Integer(0)); // can add a Integer to a List<String>!
    String s = typesafeStrings.get(0); // fails at runtime, not safe

    typesafeStrings = new ArrayList<String>();
    safeAdd(typesafeStrings, new Integer(0)); // compiler error, safe!
    s = typesafeStrings.get(0);

}

static void unsafeAdd(List list, Object o) {
    list.add(o);
}

static void safeAdd(List<Object> list, Object o) {
    list.add(o);
}

Upvotes: 0

Rob Di Marco
Rob Di Marco

Reputation: 44962

Here is where the are not equivalent...

Set<String> s_str = new HashSet<String>();
Set s_plain = s_str;  // This is valid, although you will get a compiler warning

// This is invalid, the Set<String> cannot be implicitly cast to object even though
// it's *contents* are all objects.
Set<Object> s_obj = s_str;  

Now let's say you wanted to have to take a generic Set for example as an argument to a function. You can use extends

function void foo(Set<? extends Object> s) {}

In this case, a Set, a Set<Object> and a Set<String> could all be passed in to the function, even though they are all different.

Upvotes: 2

Ryan Stewart
Ryan Stewart

Reputation: 128899

That isn't a compile-time error. It's just a warning. I.e this compiles fine:

Set s = new HashSet();
Set<Object> so = new HashSet<Object>();
s = so;

And incidentally, so does

so = s;

And they are basically the same from a usage perspective.

Upvotes: 3

Kal
Kal

Reputation: 24910

Its the difference between Java 1.4 and below and 1.5 and above.

There's plenty of information out there on why.

http://download.oracle.com/javase/1,5.0/docs/guide/language/generics.html

Upvotes: 1

Related Questions