Я часто обнаруживаю, что хочу написать общие определения классов формы
public class Foo<ActualType extends Foo<ActualType>>
Например, в настройке, подобной этой:
public interface ChangeHandler<SourceType> {
    public void onChange(SourceType source);
}
public class Foo<ActualType extends Foo<ActualType>> {
    private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();
    public void addChangeHandler(ChangeHandler<ActualType> handler) {
        handlers.add(handler);
    }
    @SuppressWarnings("unchecked")
    protected void reportChange() {
        for (ChangeHandler<ActualType> handler: handlers)
            handler.onChange((ActualType) this);
    }
}
public class Bar extends Foo<Bar> {
    // things happen in here that call super.reportChange();
}
public static void main(String[] args) throws IOException {
    Bar bar = new Bar();
    bar.addChangeHandler(new ChangeHandler<Bar>() {
        @Override
        public void onChange(Bar source) {
            // Do something with the changed object
        }
    });
}
Событие change здесь является лишь примером. Это более общая проблема, которая возникает у меня, когда я хотел бы позволить суперклассу предоставлять функциональность, которая "индивидуализирована" для каждого конкретного подкласса (не уверен, как это лучше выразить)... в примере выше "индивидуализации" заключается в том, что ChangeHandler вызывается с объектом фактического подтипа (Bar), а не с типом суперкласса (Foo), вызывающего обработчик).
Как-то этот подход кажется мне немного грязным. И это фактически разрешает потенциальные проблемы, поскольку ничто не мешает мне определить:
public class Baz extends Foo<Bar> { /* ... */ }
Есть ли более чистая альтернатива?
Священный Грааль будет некоторым параметром типа, который всегда определяется как содержащий текущий класс, как статическая версия this.getClass(), которая позволила бы мне написать что-то вроде этого:
public class Foo {
    private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();
    public void addChangeHandler(ChangeHandler<this.Class> handler) {
        handlers.add(handler);
    }
    protected void reportChange() {
        for (ChangeHandler<this.Class> handler: handlers)
            handler.onChange(this);
    }
}
Где this.Class будет равно Bar для классов типа Bar.