Monday, 17 September 2007

Type Variables In Java

Continuing Reading Java Language Specification turned to section Types, Values, and Variables Again.

Reading more about Type Variable:

What is the output of the following program?

class C {
void mCDefault() {}
public void mCPublic() {}
private void mCPrivate() {}
protected void mCProtected() {}
}

interface I {
void mI();
}

class CE extends C implements I {

public void mI() {
System.out.println("In M1()");
}
}

public class TypeVariables {

public static void main(String[] args) {
new TypeVariables().test(new CE());
}

void test(T t) {
t.mI();
t.mCDefault();
t.mCPublic();
t.mCPrivate();
t.mCProtected();
}

}

Output:
Well private methods cannot be accessed outside the class.So if we comment t.mCPrivate(); then all should be fine.

Wondering what this expression meant ??

It refers to Type Variable: As JLS states:

A type variable is an unqualified identifier. Type variables are introduced by generic class declarations generic interface declarations generic method declarations and by generic constructor declarations.

The type variable T has the same members as the intersection type C & I, which in turn has the same members as the empty class CT, defined in the same scope with equivalent supertypes. The members of an interface are always public, and therefore always inherited (unless overridden). Hence mI is a member of CT and of T. Among the members of C, all but mCPrivate are inherited by CT, and are therefore members of both CT and T.

If C had been declared in a different package than T, then the call to mCDefault would give rise to a compile-time error, as that member would not be accessible at the point where T is declared.

Hence in our example Type variable T when defined which extends both interface I and class C which is class CE in our example.

WHat is Heap Pollution:
It is possible that a variable of a parameterized type refers to an object that is not of that parameterized type. This situation is known as heap pollution. This situation can only occur if the program performed some operation that would give rise to an unchecked warning at compile-time.

For example, the code:

List l = new ArrayList();
List ls = l; // unchecked warning


Navigating to Section Erasures and Raw Types.Can you predict which lines gives unchecked warnings in the below code?

class NonGenericExample {

Collection myNumbers(){
return null;
}
}

abstract class RawMembers extends NonGenericExample implements Collection {
static Collection cng = new ArrayList();

public static void main(String[] args) {
RawMembers rw = null;
Collection cn = rw.myNumbers();
Iterator is = rw.iterator();
Collection cnn = rw.cng;

}
}

Well rw.iterator() gives us unchecked warnings. If we read closely what JLS states:

RawMembers inherits the method

Iterator iterator()

from the Collection superinterface. However, the type RawMembers inherits iterator()
from the erasure of its superinterface, which means that the return type of the member iterator()
is the erasure of Iterator<, Iterator. As a result, the attempt to assign to rw.iterator()
requires an unchecked conversion (§5.1.9) from Iterator to Iterator, causing an unchecked warning to be issued.

In contrast, the static member cng retains its full parameterized type even when accessed through a object
of raw type (note that access to a static member through an instance is considered bad style and is to be discouraged). Hence in our example Collection cnn = rw.cng; this statements works expect the fact that we should access it in static way.

The member myNumbers is inherited from the NonGenericExample (whose erasure is also NonGeneric) and so retains its full parameterized type.

The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized invocations.

The type of a constructor, instance method , or non-static field M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

The rules for generating warnings when accessing members or constructors of raw types are as follows:

An invocation of a method or constructor of a raw type generates an unchecked warning if erasure changes any of the types of any of the arguments to the method or constructor.
An assignment to a field of a raw type generates an unchecked warning if erasure changes the field's type.

Hope this explanation helps and any suggestions please suggest.

No comments: