February 27th, 2012
9:32 am
Passing the “this” reference for a subclass from a self-referential generic superclass

Posted under Java
Tags , , ,

Update 7/12/22

Previously I have implemented a composite iterator for iterating a tree of tags from a search on a PropertyTree implementation. Note that in this case, the abstract base class for the composites was a TagTree, and the concrete subclasses were a TagList and a Tag. As a Tag did not need a list, the list of children was in the concrete TagList and not the TagTree. Therefore, the TagTree did not need to have generic references to self referential subtypes in the way the example below does – in fact it did not need to be generic at all. Therefore it did not suffer this problem. For further clarity see the example below from Angelika Langer here. In her code, the list is in the abstract superclass which is why it suffers the problem below and potentially needs the infamous getThis trick per below.

Original Post

Some generic classes are recursively self-referential, such as in the following abstract class statement for a tree node :-

public abstract class Node <N extends Node<N>>  {

}

In this situation it is sometimes necessary for example to pass a reference to this from the superclass to a specific subclass which expects an argument of type N :-

public void methodA(N node) {
//do something with the passed node
}

public void methodB(N node) {
node.methodA(this); // error – incompatible types
}

In the above fragment, the error is because this in the superclass has a type of Node<N> which does not match N.

Another related use case is where a fluent API returns a ‘this’ reference from each of the fluent methods. If for example a fluent method in an abstract base class needs to return a ‘this’, as above the reference needs to be for the concrete subclass so the same problem occurs.

The topic is discussed in detail in Java Generics and Collections, section 9.4 on the Strategy pattern. The section from the book may be viewed online at Flylib here.

Angelika Langer also discusses it in more detail her Generics FAQ here

In the above case, the problem can be solved with the so-called getThis trick. An abstract getThis method is defined in the superclass, and implemented in each subclass:-

Superclass

protected abstract N getThis();

Subclass

protected Subtype getThis() {return this}; // where Subtype is the concrete subtype of N

Now the superclass can obtain a type correct reference to this and pass it without error:-

public void methodB(N node) {
node.methodA(getThis()); // this time it works
}

As Angelika Langer points out in her examples, there can be other ways around this kind of problem depending on the situation, but sometimes you do need the getThis trick.

No Comments »

January 29th, 2012
3:26 pm
Cannot obtain a class literal for a concrete parameterised type

Posted under Java
Tags , , , , , ,

Update 30/1/2012

After further testing, I have found more issues trying to use a parameterised concrete class in a JPA constructor expression. EclipseLink was throwing MethodNotFoundException complaining that it could not find the constructor method for the class, due to the use of the parameterised type in one of the constructor arguments. The precise circumstances where this does and does not work are not clear.

My solution has been to not use a parameterised class at all in a JPA constructor expression. To avoid most of the code duplication, what I did was to subclass the parameterised class for each concrete type I was using, i.e. I created a concrete subclass which only contained a constructor calling the superclass constructor. This then allowed me to use a typed query in JPA, as the returned class was now non-parameterised and so I could create a class literal for it.

 

Original Post

Whilst in some situations this may be an issue, it is also a statement of fact!

This is due to type erasure at run time, and cannot be done.

It means, for example, that in some cases it is not possible to completely eliminate unchecked warnings.

One example of mine was the use of a parameterised type in a constructor expression class in JPA. I had a requirement to do fetches which involved returning an entity plus another column that could not be handled as a relationship/JPA entity property. The property in question was the count of children for a tree node entity. As I was using path enumeration to describe the tree, I could not use JPA relationships to handle it, and so had to return the child count separately. I had more than one type of tree, all handled polymorphically, and so wanted to re-use the constructor class by making it parameterised.

This all worked fine but the class could not have its class literal passed when created a TypedQuery to fetch the results back. The solution was to use some casting isolated in a specific method, and to suppress the generic warnings via @SuppressWarnings("unchecked").

The following posts detail this issue:-

http://stackoverflow.com/questions/2390662/java-how-do-i-get-a-class-literal-from-a-generic-type

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#Why is there no class literal for the concrete instantiation of a parameterized type?

No Comments »

March 23rd, 2011
3:24 pm
Java Generics–Class literals as run time type tokens

Posted under Java
Tags , , , ,

This post refers to the section on page 16 of the Generics tutorial document by Gilad Bracha.

The example here uses the Cojen dynamic bytecode generation library in order to create custom sort comparators. The advantage of Cojen is that you end up with a fully compiled comparator and therefore do not incur the performance hit of reflective code. Furthermore, comparators generated by Cojen can be cached in a map so that they are only generated once. This particular example borrows some code originally used for Icefaces table sorting, which I adapted for use with Primefaces. Whilst Primefaces does have its own table sorting, I had some issues with it. I wanted visibility of the current sort column and direction, and I wanted control over the sorting – I wanted to reapply the sort to a table when rows were added to it from another table, so that it was always maintained in order. Furthermore, I wanted to maintain the current sort column and direction that had been selected by the user via the column headers when applying the sort when new rows were added. As I had trodden this route before for Icefaces, it was straightforward to move the code over and incorporate it into a standard table controller class which I was already developing.

One issue which I had not previously bottomed out in the Icefaces version was making the code fully generic and fully eliminating all the generic warnings when using a class literal as a run time type token. With Cojen, you call a static forClass method on its BeanComparator to construct a comparator, passing in the class and the comparator ordering details:-

if (beanComparator == null) {
    beanComparator = BeanComparator.forClass(rowClass).orderBy(key);               
    comparatorMap.put(key, beanComparator);
}   

In my first Icefaces attempt, I pulled the first row out of the current row list for the table, and passed that to Cojen to create the class. The problem with this was that I could not do it generically this way. My second attempt, with the Primefaces version, passed the class in to an init method generically. As this tied up all the generics loose ends correctly, everything was happy and the class was recognised as having the correct parameterised type. The cost of this was the need to pass it explicitly as an argument to an init method (or a setter), but this was simple and made the parameterised type clear and explicit. This is the correct approach and one that I will use from now on.

The following code fragments illustrate the mechanism:-

Call Site


    private @Inject TableCtrl<Person, RowMetadata> personTable;

        personTable.init(Person.class, RowMetadata.class, this);

 

TableCtrlImpl.java

@Dependent
public class TableCtrlImpl<C, D extends RowMetadata> implements Serializable, TableCtrl<C, D>, Iterable<C> {

    private Class<C> rowClass;

    private Map<String, BeanComparator<C>> comparatorMap = new HashMap<String, BeanComparator<C>>();

@Override public void init(Class<C> rowClass, Class<D> rowMetadataClass, TableCtrlEvent<C, D> tableCtrlEvent) {       
    rowMeta = new RowMetaMap<C, D>();
    this.rowClass = rowClass;
    this.rowMetadataClass = rowMetadataClass;
    this.tableCtrlEvent = tableCtrlEvent;
}

    @Override public void sort() {
        if (sortColumn != null && !rows.isEmpty()) {
            String key = (sortAscending ? “” : “-“) + sortColumn;
            BeanComparator<C> beanComparator = comparatorMap.get(key);
            if (beanComparator == null) {
                beanComparator = BeanComparator.forClass(rowClass).orderBy(key);               
                comparatorMap.put(key, beanComparator);
            }
           
            Collections.sort(rows, beanComparator);
        }
    }

No Comments »