I am following examples in "Effective Java" and came across the following code:
abstract static class Builder<T extends Builder<T>>
and its implementation:
public static class Builder extends Pizza.Builder<Builder>
Why is this declared T extends Builder<T> and not T extends Builder. Is it really needed to add the template <T>? What is the impact if I just use Builder<T extends Builder>?
It is called as "generic type". That declaration means T can be any type that is subclass of Builder<T>.
The goal of implementing Generics is finding bugs in compile-time other than in run-time. Finding bugs in compile-time can save time for debugging java program, because compile-time bugs are much easier to find and fix.
What is the impact if we just use Builder<T extends Builder>?
It transforms into raw type. And type safety goes off.
Builder<T extends Builder<T>> means that,
The class T passed in must implement the Builder interface / extend Builder class, and the generic parameter of Builder must be T itself.
I have some examples to show that actually the difference is not that big. I think the OP wants to know the difference between T extends Builder<T> and T extends Builder.
public abstract class Builder2<T extends Builder2> {
//doesn't compile either, because String is not a subtype of Builder2
static class WrongHouseBuilder extends Builder2<String> {}
//all ok
static class RawHouseBuilder extends Builder2 {}
static class HouseBuilder1 extends Builder2<RawHouseBuilder> {}
static class HouseBuilder2 extends Builder2<HouseBuilder1> {}
static class HouseBuilder3 extends Builder2<HouseBuilder2> {}}
Now with Builder<T>:
public abstract class Builder<T extends Builder<T>> {
//all ok
static class RawCarBuilder extends Builder {}
static class CarBuilder extends Builder<CarBuilder> {}
//ok as well, T doesn't have to be CarBuilder2
static class CarBuilder2 extends Builder<CarBuilder> {}
//doesn't compile because CarBuilder2 is not a subtype of Builder<CarBuilder2>
static class CarBuilder3 extends Builder<CarBuilder2> {}}
Of cause with T extends Builder<T>, you have more protection, but not that much.
UPDATE
Just to clarify, we should not use raw type. #Radiodef has provided an interesting example in the comment. And a quote from that answer to help you understand it:
In simpler terms, when a raw type is used, the constructors, instance methods and non-static fields are also erased.
Minor: It looks more natural to me to use Builder as an interface, not an abstract class. This is a sort of recursive type declaration. It is used for type safety to prevent nasty things like the following happens:
public abstract Builder<T extends Builder<T>> {
T build();
}
public class Entity extends Builder<String>{ // does not compile
#Override
public String build() {
return null;
}
}
public class Entity extends Builder<Entity>{ //ok
#Override
public Entity build() {
return null;
}
}
Anyway more naturally looking version (from my point of view) is:
public interface Buildable<T extends Buildable<T>> {
T build();
}
public final class Entity implements Buildable<Entity>{
//other methods
#Override
public Entity build() {
//implementation
}
}
I see that the question is about the <T> part in Builder<T>. Without this <T>, you simply get a raw type, and your IDE might complain.
But in my answer, I'd like to explain what's the purpose of T extends Builder<T>, because other answers do not seem to cover it (maybe you know this already).
T extends Builder<T> serves the purpose of returning appropriate Builder.this in all the Builder methods (except build() method, of course).
I usually use it with a protected abstract method like T thisInstance().
Example:
abstract class NamedBuilder<T extends NamedBuilder<T>> {
private String name;
T name(String name) {
this.name = name;
return thisInstance();
}
protected abstract T thisInstance();
}
final class MoreSpecificBuilder extends NamedBuilder<MoreSpecificBuilder> {
#Override
protected MoreSpecificBuilder thisInstance() {
return this;
}
}
Thanks to such approach, you do not have to redefine name() method in all the NamedBuilder subclasses to return the specific subclass.
Without such constraint type parameter T, you would have:
abstract class NamedBuilder {
NamedBuilder name(String name);
}
and you would need to override all such methods in subclasses like that:
final class MoreSpecificBuilder extends NamedBuilder {
#Override
MoreSpecificBuilder name(String name) {
super.name(name);
return this;
}
}
EDIT: Without the constraint extends Builder<T> on type parameter T:
abstract class NamedBuilder<T> {
// ...
}
this would work fine, although such design would be less intuitive and more error-prone.
Without such constraint, compiler would accept anything as T (e.g. String), so the constraint acts simply as a compile-time check for the implementors of NamedBuilder.
Related
Background
I was trying to use Annotation Processors, to generate implementations of specific Factory interfaces. Those interfaces look the following:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
and
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
The Annotation Processor is doing the correct thing and generates a factory for each matching class, that is annotated with an corresponding annotation.
The Problem
The output of the Annotation Processor is the following:
public final class TestViewImplFactory implements ViewFactory {
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
and the corresponding other class:
public final class TestPresenterImplFactory implements PresenterFactory {
public final TestPresenter create() {
return new TestPresenterImpl();
}
}
The TestViewImplFactory however cannot be compiled. The error message is:
"Class 'TestViewImplFactory' must be declared abstract or implement
abstract method create(S) in 'ViewFactory'"
Java says, the following is correct:
#Override
public View create(Presenter presenter) {
return new TestViewImpl(presenter);
}
which would not work at all, considering that the user wants to know, which View will be returned and which Presenter is required. I would have expected that:
either both of the autogenerated files are wrong
or both are correct
because they both are really similar. I expected the first to be true.
What am I missing here?
If I add the Generic type to the TestViewImplFactory like this:
public final class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public <S extends Presenter<TestView>> TestView create(S presenter) {
return new TestViewImpl(presenter);
}
}
The problem arises, that the constructor Parameter (which is of the Type TestPresenter) is incorrect. Changing the S to a concrete TestPresenter will, again, make the class not compilable for the same reason as above.
So, I stumbled across an "solution" that can be compiled.
What basically has to be done, is to change the ViewFactory interface to the following:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
So the class definition has the same Generic type, as the method in the Question above.
After compilation (this time with generic type specification), the output looks like this:
public final class TestViewImplFactory implements ViewFactory<TestView, TestPresenter> {
public TestViewImplFactory() {
}
public final TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
This can be compiled and runs successfully.
This however does not answer the original question. Why is the generic explicitly stated in the type definition correct, but inherited and specified in the method declaration wrong and not compilable?
To be concrete: Why can Java inherit one Generic automatically (within the PresenterFactory) and the other ones not (within the ViewFactory, at the method and at the type declaration)?
Why it is not working:
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
This signature causes the compiler to infer S at the location where create() is called. S will be what ever you assign create() to as in:
FancyPresenter fp = presenterFactory.create();
SomeOtherPresenter sop = presenterFactory.create();
This implies that:
public TestPresenter create(){...}
is not an implementation of:
<S extends Presenter<T>> S create();
but a method override. There is no implementation of the interface' method. It's not even possible to provide any implementation with a concrete S. It's similar with:
public interface ViewFactory<T extends View> {
<S extends Presenter<T>> T create(S presenter);
}
Here the generic is again inferred on method invocation. So an implementation must accept every subtype of Presenter<T>. The only valid implementation for this is:
public interface ViewFactory<T extends View> {
T create(Presenter<T> presenter);
}
But the return type is dependent on the parameter presenter. This might work if presenter provides you with a method to create an instance of T only.
Why does the other solution work:
Binding the method's generic via the type means that an implementation of the interface provides the concrete type. So for one object you don't need to provide multiple different bindings. No matter where you call the create() method of PresenterFactory<TestView, TestPresenter<TestView>> the return type's generic is bound to TestPresenter<TestView>. So there is a possible implementation for each subtype of PresenterFactory<...>.
I think the very first part of your problem statement should be addressed as I notice your annotation processor is implementing the raw ViewFactory type. I guess with type erasure, since it's generated code, it doesn't make a real difference in practice. But if the processor could generate implementations using the parameterized type, it would at least be easier to reason about the problem.
So, given a message signature <S extends Presenter<T>> T create(S presenter), you could have it generate:
public class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public <S extends Presenter<TestView>> TestView create(S presenter) { ... }
}
Or more minimally:
public class TestViewImplFactory implements ViewFactory<TestView> {
#Override
public TestView create(Presenter presenter) { ... }
}
But then, with either of those, you cannot restrict the parameter to TestPresenter. You would have to change ViewFactory to something like
public interface ViewFactory<T extends View, U extends Presenter<T>>
and them implement ViewFactory<TestView, TestPresenter>. You kind of have to use the type parameters in the implementation to achieve the type restrictions you want.
I'm new to the art of designing fluent, extensible interfaces. I have a chain of builder classes that implement interfaces and both the interfaces and the builder implementations take self-referential type parameters.
Note: This is related to my previous question in which I had attempted to design the interfaces slightly differently before trying this approach in which the interfaces take a self-referential type parameter as well:
Here is the interface:
public interface ILoadableBuilder<C extends ILoadable,T extends ILoadableBean, B extends ILoadableBuilder<C,T,B>> {
T getState();
B setComponentClass(final Class<C> componentClass);
B setDriver(final WebDriver driver);
B setLoadTimeoutInSeconds(final #Nonnegative int loadTimeoutInSeconds);
B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator);
}
Here is an implementation, which also takes a self-referential type parameter. The reason the class implementation takes the parameter is that I want it to be extensible so that other builders can then extend this class and inherit all its behavior, and that the setters can be called in any order and the return type will be correct:
public class LoadableBuilder<C extends ILoadable,T extends ILoadableBean,B extends ILoadableBuilder<C,T,B>> implements
ILoadableBuilder<C,T,B> {
private final T componentBean;
private IEnumeratorBean<? extends IEnumerable<?>,?> enumerator;
private Class<C> componentClass;
public LoadableBuilder(final T componentBean) {
this.componentBean = componentBean;
}
public final T getState() {
return componentBean;
}
public final B setComponentClass(final Class<C> componentClass) {
this.componentClass = componentClass;
return (B)this;
}
public final B setDriver(final WebDriver driver) {
getState().setDriver(driver);
return (B)this;
}
public final B setLoadTimeoutInSeconds(final int loadTimeoutInSeconds) {
getState().getLoadTimeoutInSeconds();
return (B)this;
}
public B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator) {
this.enumerator = enumerator;
return (B)this;
}
}
My question is, how the heck do you instantiate an instance of this implementation without having to pass a type parameter to the client class? Say, I want to declare a member variable in a class that uses the builder like so:
public ClientClass<C,T> {
private ILoadableBuilder<C,T,_what do I put here????_> builder = new LoadableBuilder<C,T,_what do I put here?????_>();
}
For a method, it's no big deal because I can do this:
public <B extends ILoadableBuilder<C,T,B>> void useABuilder() {
ILoadableBuilder<C,T,B> builder = new LoadableBuilder<C,T,B>();
}
EDIT:
ClientClass would want to build an object that implements the ILoadable interface. I have lots of builders that extend ILoadableBuilder to build objects that implement interfaces which are sub-types of ILoadable. The idea is that I want to be able to get a builder for any object in the inheritance hierarchy underneath ILoadable, which themselves are extensible where necessary.
You have two options:
Make LoadableBuilder not extensible, and just declare it as
public class LoadableBuilder<C extends ILoadable, T extends ILoadableBean>
implements ILoadableBuilder<C,T,LoadableBuilder<C,T>>
If you want to let it be extensible, then make it always necessary to extend it. Let LoadableBuilder be "abstract". Define a bare-bones implementation that just subclasses it with no extra stuff for the "basic" behavior:
public abstract class LoadableBuilder<C extends ILoadable,
T extends ILoadableBean, B extends ILoadableBuilder<C,T,B>>
implements ILoadableBuilder<C,T,B> {
//...
}
public class BasicLoadableBuilder<C extends ILoadable, T extends ILoadableBean>
extends LoadableBuilder<C,T, BasicLoadableBuilder<C,T>> {
}
Let's say I've got a parent abstract animal trainer class:
public abstract class Trainer
<A extends Animal,
E extends Enum<E> & Trainables>{
protected EnumSet<E> completed;
public void trainingComplete(E trainable){
trainingComplete.add(trainable);
}
I want concrete extensions of the parent animal trainer to complete training for only the trainables defined by it. So if I have a concrete Dog Trainer as follows:
public class DogTrainer extends Trainer<Dog, DogTrainer.Tricks>{
public enum Tricks implements Trainables {
FETCH, GROWL, SIT, HEEL;
}
}
With the current definition of DogTrainer I can only do trainingComplete for parameters of the DogTrainer.Tricks type. But I want to enforce that anyone who creates a concrete Trainer should allow trainingComplete() for Trainables that it defines within itself.
In other words, the problem with my current design is, if I had another trainer as follows:
public class PoliceDogTrainer extends Trainer<Dog, PoliceDogTrainer.Tricks>{
public enum Tricks implements Trainables {
FIND_DRUGS, FIND_BOMB, FIND_BODY;
}
}
There is nothing preventing someone from defining another rouge trainer that tries to teach the dog, police tricks:
public class RougeTrainer extends Trainer<Dog, PoliceDogTrainer.Tricks>{
...
}
I want to prohibit this and allow extending class to use ONLY Trainables they themselves specify.
How can I do that?
You can make the enums non-public but that cannot be enforced by the abstract base class. An alternative is to make Trainables generic by adding a type parameter which must match the Trainer class. This does not enforce the enum to be an inner class (that’s impossible) but for a conforming sub class, no RogueTrainer can be created then.
Enforcing constraints on the type of this inside the base class or interface lies somewhere between tricky and impossible. One commonly known example is the Comparable interface which cannot be declared in a way to prevent implementations like class Foo implements Comparable<String>.
One way to circumvent this problem is to make the Trainer reference a parameter, e.g.
public interface Trainables<T extends Trainer<?,? extends Trainables<T>>>
…
public abstract class Trainer
<A extends Animal,
E extends Enum<E> & Trainables<? extends Trainer<A,E>>> {
protected EnumSet<E> completed;
void trainingCompleteImpl(E trainable) {
completed.add(trainable);
}
public static <A extends Animal, T extends Trainer<A,E>,
E extends Enum<E> & Trainables<T>> void trainingComplete(T t, E trainable) {
t.trainingCompleteImpl(trainable);
}
}
public class PoliceDogTrainer
extends Trainer<Dog, PoliceDogTrainer.Tricks> {
public enum Tricks implements Trainables<PoliceDogTrainer> {
FIND_DRUGS, FIND_BOMB, FIND_BODY;
}
}
The public static method can only be invoked with the right combination of Trainer and Trainables. The trainingCompleteImpl method can be invoked and overridden by trusted subclasses within the same package. If you don’t want this you can inline the code of the method and remove the instance method completely.
_
An alternative is to create a type parameter for the Trainer and enforce a match between the parameter and this at runtime:
public interface Trainables<T extends Trainer<?,T,? extends Trainables<T>>>
…
public abstract class Trainer
<A extends Animal, T extends Trainer<A,T,E>,
E extends Enum<E> & Trainables<T>> {
protected EnumSet<E> completed;
/** sub-classes should implements this as {#code return this}*/
protected abstract T selfReference();
void trainingComplete(E trainable) {
if(selfReference()!=this) throw new IllegalStateException();
completed.add(trainable);
}
}
public class PoliceDogTrainer
extends Trainer<Dog, PoliceDogTrainer, PoliceDogTrainer.Tricks> {
public enum Tricks implements Trainables<PoliceDogTrainer> {
FIND_DRUGS, FIND_BOMB, FIND_BODY;
}
#Override
protected final PoliceDogTrainer selfReference()
{
return this;
}
}
So, for a non-conforming Trainer implementation selfReference() cannot be implemented as return this; which can be detected easily. For a conforming implementation the JVM will inline the selfReference method and see this==this then which will be optimized away; so this check has no performance impact.
I thought I understood how to do this but I'm getting some unexpected behavior so apparently I'm missing something. Here's the problem boiled down.
Base Class:
public abstract class Base<T>
{
abstract public void foo(List<? extends T> l);
}
Derived Class:
public class Derived<T> extends Base
{
#Override
public void foo(List<? extends T> l) { return; }
}
The Base class complies fine, but when I compile the Derived class I get:
Derived.java:3: Derived is not abstract and does not override abstract method foo(java.util.List) in Base
public class Derived extends Base
^
Derived.java:5: method does not override or implement a method from a supertype
#Override
^
2 errors
The generics of the parameter List<? extends T> appears to be the cause of the problem. If I replace that part in both signatures with the basic type int it comples fine.
Can anybody tell me what's going on here?
You should do
public class Derived<T> extends Base<T>
You need to specify <T> for Base otherwise you will have to override method by simply declaring List i.e.without generics
You can also pass the type parameter in your class declaration like this:
public class Derived extends Base<SomeConcreteType> {
#Override
public void foo(List<SomeConcreteType> l) {
// ...
}
}
if you no longer need the generic part of the abstract class because you are going to use a concrete type in your derived class. Otherwise you have to do what the other answer stated.
I have the following class structure:
public class Team {
...
}
public class Event {
}
public abstract class Fixture<T extends Team> implements Event {
...
}
public abstract class Forecast<Event> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{
}
I am trying to model sports events of all kinds (i.e. a 'Fixture' is for a particular game between two participants play against each other, whereas another type of 'Event' may have many participants), along with predictions for the outcome of particular 'Events'. I have a generic method:
public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {
}
I want to be able to return a MyPrediction instance which has the generic type of the fixture argument, but I can't seem to do so. For example, if I do something like the following, then I get a compilation error:
SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);
I am willing to change my class structure to incorporate this feature. How can I do so?
Change the signature of getMyPrediction to
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)
This tells the compiler that the fixture types in the argument and result are the same, allowing type-checking to pass.
Here is a complete example, with some other minor changes to get it to compile. It introduces the class Predictor to hold the getMyPrediction method and a doit method to show sample use:
public interface Team {
}
public interface Event {
}
public abstract class Fixture<T extends Team> implements Event {
}
public abstract class Forecast<T> {
}
public class MyPrediction<T extends Fixture<? extends Team>> extends
Forecast<Fixture<? extends Team>> {
}
public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}
public class SoccerTeam implements Team {
}
public class EnglishSoccerTeam extends SoccerTeam {
}
public class Predictor {
public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
return new MyPrediction<T>();
}
public void doit() {
SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
}
}
As noted elsewhere, you might need to introduce one or more factory objects to perform meaningful work in the MyPrediction implementation.
Java's type system is not powerful enough to do directly what you propose, because of type erasure (the generic parameters are not available at runtime.
The usual solution is to create a separate EventFactory class, which you can then pass in to any method which needs to create a specific Event subtype instance.