After over three hours on the ground, the flight finally left for Newark.
when to made several rotations around an arbitrary area
then redirected to Boston.
This is not Judy's day.
![]() | ![]() |
![]() | ![]() |
public interface Model{T extends Model{T}} {
T read(InputStream in);
T write(OutputStream out);
}
public class MyModel implements Model{MyModel}Thanks to the covariance, I can write a method chain like this:{
public MyModel read(InputStream in) {
...
}
public MyModel write(OutputStream out) {
...
}
public MyModel setName(String name) {
...
return this;
}
public String getName() { ... }
}
new MyModel()
.read(in)
.setName("foo")
.setStopAtMain(false)
...
.write(out);
public interface Model {And the method chain would result in a syntax error:
Model read(InputStream in);
Model write(OutputStream out);
}
class MyModel implements Model {
public Model read(InputStream in) { ... }
public Model write(OutputStream out) { ... }
...
}
public static void foo() {Which you could hack around with an ugly cast:
new MyModel()
.read(in)
.setName("foo")
^ The method setName(String) is undefined
for the type Model.
.write(out);
}
public static void foo() {Back to the Java 5 example: My point is just this: covariant return types don't require generics. All that messy code in version 1 could look much simpler because covariant return types exist on their own without generics:
((MyModel) new MyModel()
.read(in))
.setName("foo")
.write(out);
}
public interface Model{{T extends Model{T}}
TModel read(InputStream in);
TModel write(OutputStream out);
}
public class MyModel implements ModelLesson learned: I know generics fairly well, but there's a difference between knowing when it's useful and when it isn't. Said another way: when you have a Generic hammer everything looks like a generic nail.{{MyModel}
public MyModel read(InputStream in) {
...
}
public MyModel write(OutputStream out) {
...
}
public MyModel setName(String name) {
...
return this;
}
public String getName() { ... }
}