开发者

Taming the type checker in Java Generics

I thought I understood Generics pretty well, but apparently I didn't.

Here is the test case of the problem:

import java.util.ArrayList;

class Job<J extends Job<J,R>, R extends Run<J,R>> {}
class Run<J extends Job<J,R>, R extends Run<J,R>> {}

class Job2 extends Job<Job2,Run2> {}
class Run2 extends Run<Job2,Run2> {}

class RunList<J extends Job<J,R>, R extends Run<J,R>> extends ArrayList<R> {}

class Foo {
    // #1 problem
    public void test1(RunList<Job,Run> why) {}
    // #2 this doesn't work either
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {}
    // #3 this works
    public void test3(RunList<Job2,Run2> why) {}
}

The compiler doesn't allow the test1 method above, saying that "Job" is not within its type bounds. I kinda sorta understand it --- Job as a raw type doesn't extend Job<Job,Run>, hence the error. In contrast, test3 works.

Now, the question is, how do I make this work? I've tried #2, but that doesn't work either. The p开发者_JAVA技巧roblem I suppose is really similar with #1 --- Job<Job,Run> is not within the bounds because its type argument Job is a raw type.

Does anyone know how to make the type checker happy, other than resorting to the raw type? Or is it just not attainable in the Java type system?


Maybe:

public <J extends Job<J, R>, R extends Run<J, R>> void test(RunList<J, R> why) {}


If you change the type parameter to ArrayList then you can add new Run();


You're right, not sure what I was thinking there! Your comment inspired me to think about it further and I tested it and the cause of the problem has something to do with the recursive definition of the type variables Job<J extends Job<J..., but I'm not entirely clear why. One solution, remove the 'use' of J and R from your definitions.

Longer answer:

import java.util.ArrayList;

class Job<J extends Job, R extends Run> {}
class Run<J extends Job, R extends Run> {}

class Job2 extends Job<Job2,Run2> {}
class Run2 extends Run<Job2,Run2> {}

class RunList<J extends Job, R extends Run> extends ArrayList<R> {}

class Foo {
    // #1 works now
    public void test1(RunList<Job,Run> why) {}
    // #2 works now too
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {}
    // #3 still works
    public void test3(RunList<Job2,Run2> why) {}
    // #4 generic method
    public <J extends Job, R extends Run> void test4(RunList<J,R> why) {}

    public static void main(String[] args) {
        // Calling them even works...
        new Foo().test1(new RunList<Job,Run>());
        new Foo().test2(new RunList<Job<Job,Run>,Run<Job,Run>>());

        // Calling the generic method works too
        new Foo().test4(new RunList<Job,Run>());
        new Foo().test4(new RunList<Job<Job,Run>,Run<Job,Run>>());
        new Foo().test4(new RunList<Job2,Run2>());

        // ...sort of

        // This doesn't work
        //new Foo().test1(new RunList<Job<Job,Run>,Run<Job,Run>>());

        // This doesn't work
        //new Foo().test1(new RunList<Job2,Run2>());

    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜