Укрощение элемента проверки типов в Java Generics

Я думал, что я хорошо разбираюсь в Generics, но, видимо, я этого не сделал.

Вот тестовый пример проблемы:

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) {}
}
</job2,run2></job,run></job<job,run></job,run></r></j,r></j></job2,run2></job2,run2></j,r></j></j,r></j>

Компилятор не разрешает выше описанный выше метод test1, говоря, что "Job" не входит в рамки своего типа. Я вроде как понимаю это --- Job, поскольку необработанный тип не расширяет Job, следовательно, ошибка. Напротив, test3 работает.

Теперь, вопрос в том, как мне сделать эту работу? Я пробовал # 2, но это тоже не работает. Проблема, которую я предполагаю, действительно похожа на # 1 --- Job, не находится в пределах границ, потому что ее аргумент типа Job является сырым типом.

Кто-нибудь знает, как сделать проверку типа счастливой, кроме обращения к необработанному типу? Или это просто не достижимо в системе типа Java?

3 ответа

Может быть:

public <j extends="" job<j,="" r="">, R extends Run<j, r="">> void test(RunList<j, r=""> why) {}
</j,></j,></j>


Если вы измените параметр типа на ArrayList, вы можете добавить новый Run();


Ты прав, не уверен, что я там думал! Ваш комментарий вдохновил меня задуматься об этом дальше, и я протестировал его, и причина проблемы связана с рекурсивным определением переменных типа Job<j extends="" job<j...<="" code="">, но я не совсем понимаю, почему. Одно решение, удалите "использование" J и R из ваших определений.</j>

<p>Дольше ответ:</p> <pre class="prettyprint linenums">import java.util.ArrayList; class Job<j extends="" job,="" r="" run=""> {} class Run<j extends="" job,="" r="" run=""> {} class Job2 extends Job<job2,run2> {} class Run2 extends Run<job2,run2> {} class RunList<j extends="" job,="" r="" 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="" 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>()); } } </job2,run2></job,run></job<job,run></job2,run2></job,run></job<job,run></job,run></job,run></job<job,run></job,run></j,r></j></job2,run2></job,run></job<job,run></job,run></r></j></job2,run2></job2,run2></j></j></pre>

licensed under cc by-sa 3.0 with attribution.