Taming a Type Checker Element in Java Generics

I thought I was good at Generics, but apparently I didn’t.

Here is a test case for 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 does not allow the test1 method described above, saying that "Job" is not within its scope. I kind of understand how it is --- Job , because the raw type does not extend Job<Job,Run> , hence the error. On the contrary, test3 works.

Now, the question is, how do I do this job? I tried # 2, but that does not work either. The problem I assume is really similar to # 1 --- Job<Job,Run> is not within the bounds because its argument of type Job is a raw type.

Does anyone know how to make type checking happy except calling a raw type? Or is it just not achievable in a system like Java?

+6
java generics
source share
3 answers

May be:

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

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

0
source share

You're right, not sure what I was thinking there! Your comment inspired me to think about this further, and I tested it, and the cause of the problem is related to the recursive definition of variables like Job<J extends Job<J... , but I do not quite understand 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>()); } } 
-one
source share

All Articles