简体   繁体   中英

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 ?

That isn't a compile-time error. It's just a warning. Ie 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.

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.

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.

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

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM