Interface with a Builder with a Factory and inheritance
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Jan 20 14:10:46 UTC 2016
So, there's a short answer and a long answer :-)
The short answer is to simply add this line:
@SuppressWarnings("unchecked")
before the variable declaration - as in:
@SuppressWarnings("unchecked")
B2<I2,?> BImpl = (B2<I2,?>)f.getB();
This should help in removing the warning.
That said, I think this warning also reveals a potential design issue in
your classes; without diving too much in the details of your code, I
note that you want factories for B - where B is a generic class with two
type-variable.
Unfortunately the factory interface is very simple, and does not fully
reflect those constraints - i.e. an instance of F can return any B,
regardless of the parameterization; I don't think that's correct. I
think that instead of:
interface F {
B <? extends I,? extends B<?,?>> getB();
}
You might want something more precise, like:
interface F<S extends I>
{
B<S, ?> getB();
}
And then, Impl would become as follows:
static class Impl implements F<I2> {
...
@Override
public B2<I2, ?> getB() {
return new BImpl();
}
}
And the code that now is throwing a warning would simply become:
B2<I2,?> BImpl = f.getB(); //no cast needed
I'm not saying that this is 100% the code you want - but I'm trying to
point out how it could be made more precise when it comes to types.
Maurizio
On 20/01/16 13:47, Wang Weijun wrote:
> I am working on an Interface with a Builder with a Factory, and involving inheritance. The actual case can be viewed here [1], but I've distilled everything below in a single file.
>
> I've never written something with so many <> symbols. Although the code works, I am not sure if those ?s are used correctly, and there is still a warning
>
> $ javac -Xlint A1.java
> A1.java:4: warning: [unchecked] unchecked cast
> B2<I2,?> BImpl = (B2<I2,?>)f.getB();
> ^
> required: B2<I2,?>
> found: B<CAP#1,CAP#2>
> where CAP#1,CAP#2 are fresh type-variables:
> CAP#1 extends I from capture of ? extends I
> CAP#2 extends B<CAP#1,CAP#2> from capture of ? extends B<?,?>
> 1 warning
> $ java A1
> <N,C>
> <Nn,Cc>
>
> How can I make this warning going away?
>
> Thanks
> Max
>
> --
>
> public class A1 {
> public static void main(String[] args) throws Exception {
> F f = new Impl();
> B2<I2,?> BImpl = (B2<I2,?>)f.getB();
> I2 dad = BImpl.setName("N").setColor("C").build(null);
> I2 son = BImpl.setName("n").setColor("c").build(dad);
> System.out.println(dad);
> System.out.println(son);
> }
>
> // Base interface and builder
> interface I { String name(); }
> interface B <S extends I, T extends B<S,T>> {
> T setName(String s);
> S build(S parent);
> }
>
> // Extended interface and builder
> interface I2 extends I { String color(); }
> interface B2<S extends I2, T extends B2<S,T>> extends B<S,T> {
> T setColor(String s);
> }
>
> // Builder factory interface
> interface F {
> B <? extends I,? extends B<?,?>> getB();
> }
>
> // Implementation
> static class Impl implements F {
> static class C implements I2 {
> String color, name;
>
> public String color() {
> return color;
> }
>
> C(String name, String color) {
> this.color = color;
> this.name = name;
> }
>
> public String name() {
> return name;
> }
>
> public String toString() {
> return "<" + name + "," + color + ">";
> }
> }
>
> static class BImpl implements B2<I2,BImpl> {
> String color;
> String name;
>
> public BImpl setColor(String s) {
> this.color = s;
> return this;
> }
>
> public BImpl setName(String s) {
> this.name = s;
> return this;
> }
>
> public I2 build(I2 parent) {
> if (parent == null) {
> return new C(name, color);
> } else {
> return new C(parent.name() + name, parent.color() + color);
> }
> }
> }
>
> public B <? extends I,? extends B<?,?>> getB() {
> return new BImpl();
> }
> }
> }
>
> [1] http://cr.openjdk.java.net/~weijun/8058778/webrev.09/specdiff/java/security/cert/package-summary.html
More information about the compiler-dev
mailing list