No, they are not the same. Here's the basic difference:
Set<?> s = HashSet<String>();
s.add(2); // This is invalid
Set s = HashSet<String>();
s.add(2); // This is valid.
The point is, the first one is a unbounded parameterized type Set
. Compiler will perform the check there, and since you can't add anything but null
to such types, compiler will give you an error.
While the second one being a raw type, the compiler won't do any check while adding anything to it. Basically, you lose the type safety here.
And you can see the result of loosing type safety there. Adding 2
to the set will fail at compile time for Set<?>
, but for a raw type Set
, it will be successfully added, but it might throw exception at runtime, when you get the element from the set, and assign it to say String
.
Differences apart, you should avoid using raw types in newer code. You would rarely find any places where you would use it. Few places where you use raw type is to access static
fields of that type, or getting Class
object for that type - you can do Set.class
, but not Set<?>.class
.