Consider the following code :

class R2<E>
{
	E a;
	E get()
	{
		return a;
	}
	void set(E a)
	{
		this.a=a;
	}
}
class R3
{
	void doit(R2 a)                // (1)
	{
		a.set(new Integer(5));
	}
}

When I compile the file containing class R3, it rightly gives an unchecked warning because the compiler can't know for sure what was the element type of a (if any) i.e its a raw type. But if we replace (1) with :

void doit(R2<?> a)

In this case, the compiler complains. My question is that the wildcard ? denotes all types, so it should accept every type. The exact error is :

R3.java:7: set(capture#537 of ?) in R2<capture#537 of ?> cannot be applied to (java.lang.Integer)
		a.set(new Integer(5));
		 ^
1 error

Recommended Answers

All 5 Replies

Member Avatar for coil

I'm guessing it has something to do with line 17, where you assign an integer value to the variable a , which, because of the use of the wildcard character, has no type.

The wildcard <?> is a shorthand notation for <? extends Object> hence the normal rules apply.

private void traverse(final List<?> lst) {
    final Object o = lst.get(0);
    lst.add(new Object());  // compile time error
}

This is the same reason why you can do a "get" but not a "set". The logic being, since the type parameter of R can be anything (or not known if you prefer it that way), setting any value might corrupt the state of the object since the actual type is not know. However, a 'get' is safe since any object can be assigned to the Object reference type.

Thanks. In both the following cases :

public void traverse<List<?> ob)

and

public void traverse <List ob>

, the compiler doesn't know what the type parameter of the object passed to ob (if any) was. But in the first case, it flags it as error if we add something to ob, whereas in the second case, it simply gives a warning. I guess it is done so that the legacy code may not break. Otherwise, both present the same dilemma to the compiler. Isn't it ?

The second case is basically a free-for-all case which is still valid to support legacy code. You can do whatever you want with the passed in list. The first one is a valid usage of generics which allows traversal but not manipulation of the list.

So yes, to answer your question, the final byte-code generated is AFAICT the same with the restriction enforced at compile time.

Thanks.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.