all*_*nru 5 java eclipse generics
让我们从3个接口开始.他们所做的并不重要.请注意,Car是参数化(),而Foo和Bar则不是.
interface Foo {void testFoo();}
interface Bar {void testBar();}
interface Car<A> {A testCar();}
Run Code Online (Sandbox Code Playgroud)
我想'复合'这些接口,如果我明确地创建这样的组合,这可以正常工作:
interface FooBar extends Foo,Bar {}
interface FooCar<A> extends Foo,Car<A> {}
Run Code Online (Sandbox Code Playgroud)
但是,我更喜欢通过各种方法的有界类型声明隐式组合接口.例如:
public <T extends Foo & Bar> T implicitFooBar() {return null;}
public <X, T extends Foo & Car<X>> T implicitFooCar() {return null;}
Run Code Online (Sandbox Code Playgroud)
工作原理:本implictFooBar()方法返回同时实现Foo和Bar接口(复合如果你愿意)类型T.对此方法的调用进行编译,我可以避免必须显式声明FooBar接口:
// implicit composition of Foo and Bar, GOOD
FooBar implicitFooBar = implicitFooBar();
implicitFooBar.testFoo();
implicitFooBar.testBar();
Run Code Online (Sandbox Code Playgroud)
FAILs:但是,对implicitFooCar()的调用无法编译.错误消息是"GenericsTest类型中的方法implicitFooCar()不适用于arguments()"(我将测试代码包装在一个名为GenericsTest的类中.)
// implicit composition of Foo and Car<X>, FAIL!
//Compiler says "The method implicitFooCar() in the type GenericsTest is not applicable for the arguments ()"
FooCar<Number> implicitFooCar = implicitFooCar(); //compile error on method call
implicitFooCar.testFoo();
Number n2 = implicitFooCar.testCar();
Run Code Online (Sandbox Code Playgroud)
编译器错误仅显示类型声明何时复合和参数化.例如,这两个编译都可以调用就好了:
public <X> Car<X> justCar() {return null;}
public <X, T extends Car<X>> T implicitCar() {return null;}
Run Code Online (Sandbox Code Playgroud)
我怀疑这与类型擦除有关,但我想了解这里发生了什么的细节.我已经阅读了Oracle泛型教程,但我没有看到implicitFooCar()方法违反了哪些规则组合,而implicitFooBar()和implicitCar()都没问题.我正在寻找一种学术风格的解释,而不仅仅是一种解决方法.
有趣的是,调用implicitFooCar()方法的以下变体可以工作(没有编译器错误.)这暗示了为什么其他版本不起作用,但我还没有连接这些点.
//variant... GOOD... but why?
implicitFooCar = this.<Number,FooCar<Number>>implicitFooCar();
Run Code Online (Sandbox Code Playgroud)
如果你想使用代码,这里它是一个单独的类.
public class GenericsTest {
public static interface Foo {void testFoo();}
public static interface Bar {void testBar();}
public static interface Car<A> {A testCar();}
public static interface FooBar extends Foo,Bar {}
public static interface FooCar<A> extends Foo,Car<A> {}
public <X> Car<X> justCar() {return null;}
public FooBar explicitFooBar() {return null;}
public <T extends Foo & Bar> T implicitFooBar() {return null;}
public <X> FooCar<X> explicitFooCar() {return null;}
public <X, T extends Foo & Car<X>> T implicitFooCar() {return null;}
public <X, T extends Car<X>> T implicitCar() {return null;}
public void test() {
justCar().testCar();
// explicit composition of Foo and Bar, GOOD
FooBar explicitFooBar = explicitFooBar();
explicitFooBar.testFoo();
explicitFooBar.testBar();
// explicit composition of Foo and Car<X>, GOOD
FooCar<Number> explicitFooCar = explicitFooCar();
explicitFooCar.testFoo();
Number n1 = explicitFooCar.testCar();
// implicit composition of Foo and Bar, GOOD
FooBar implicitFooBar = implicitFooBar();
implicitFooBar.testFoo();
implicitFooBar.testBar();
// implicit composition of Foo and Car<X>, FAIL!
//Compiler says "The method implicitFooCar() in the type GenericsTest is not applicable for the arguments ()"
FooCar<Number> implicitFooCar = implicitFooCar(); //compile error on method call
implicitFooCar.testFoo();
Number n2 = implicitFooCar.testCar();
//variant... GOOD... but why?
implicitFooCar = this.<Number,FooCar<Number>>implicitFooCar();
// implicit (no composition) Car<X>, GOOD
Car<Number> implicitCar = implicitCar();
Number n3 = implicitCar.testCar();
}
}
Run Code Online (Sandbox Code Playgroud)
这与javac版本1.8.0_60(和每个注释_45)一起编译,但是在编译器ECJ中内置的Eclipse(版本4.4.2.M20150204-1700)报告了上述错误. 我在这个问题上添加了一个eclipse标签,因为这可能是一个EJC问题.
首先,直接回答我的问题......可以声明一个具有绑定参数化类型的方法,该类型结合了两个接口,其中一个接口本身是参数化的。
我的示例中的implicitFooCar ()方法失败了,因为Luna(4.4 版Eclipse)中使用的Eclipse 编译器ECJ 中存在错误。使用 javac 编译器 (v 1.8.0_60) 和下一个版本的 Eclipse Mars (4.5) 编译相同的代码。
其次,我希望避免显式声明我所认为的临时或中间复合接口,这是短视的。Louis Wasserman指出,该方法在某些时候需要返回一个符合该复合规范的对象,因此此时我需要一个显式版本。