【问题标题】:Java - Getting a more specific type than "Class<?>" for a parameterized generic classJava - 为参数化泛型类获取比“Class<?>”更具体的类型
【发布时间】:2016-01-13 23:47:52
【问题描述】:

我有一个使用类型R 参数化的基本接口,扩展了相同的基本接口:

public interface IWidget<R extends IWidget<R>> {}

然后以同样的方式参数化另一个接口:

public interface IWidgetManager<R extends IWidget<R>> {}

最后,一个类实现了第二个接口。此类将在声明时收到IWidget implementation 类:

public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R> {}

我的问题:

我们可以使用什么更具体的类型来指定MyWidgetManager

Class&lt;?&gt; 当然可以:

public Class<?> ok() {
    return MyWidgetManager.class;
}

但它非常通用,我想要更具体的东西......

那些尝试无法编译:


public Class<? extends IWidgetManager<?>> fails() {
    return MyWidgetManager.class;
}

==> 类型不匹配:无法从 Class 转换为 Class>


public <R extends IWidget<?>> Class<? extends IWidgetManager<R>> fails() {
    return MyWidgetManager.class;
}

==> 类型不匹配:无法从 Class 转换为 Class>


public <R extends IWidget<R>> Class<? extends IWidgetManager<R>> fails() {
    return MyWidgetManager.class;
}

==> 类型不匹配:无法从 Class 转换为 Class>


public Class<? extends IWidgetManager<? extends IWidget<?>>> fails() {
    return MyWidgetManager.class;
}

==> 类型不匹配:无法从 Class 转换为 Class>>


有什么方法可以让Class&lt;?&gt; 的类型比MyWidgetManager.class 更具体?

更新: 我更改了接口的名称。最后一个类不是一个小部件本身,这在我最初的问题中并不清楚......抱歉造成混淆。

更新 2:

确实,使用具体类型时事情会更容易。

这确实是针对我目前的情况,但我想我会通过将MyWidgetManager&lt;R extends IWidget&lt;R&gt;&gt; implements IWidgetManager&lt;R&gt; 转换为没有实现任何东西的WidgetManagerBase 来解决我的“问题”。然后提供一个带有具体 Widget 类的默认实现。最后,get 方法可以很容易地被覆盖(顺便说一句,这是我从一开始的主要目标!)。所以:

public interface IWidget<R extends IWidget<?>> {}
public interface IWidgetManager<R extends IWidget<R>> {}
public class WidgetManagerBase {}

// Default implementation
public class WidgetA implements IWidget<WidgetA> {}
public class AWidgetManager extends WidgetManagerBase implements IWidgetManager<WidgetA> {}

// default get method
public Class<? extends IWidgetManager<?>> getWidgetManagerClass() {
    return AWidgetManager.class;
}

// 然后可以用 : 覆盖默认的 get 方法:

public class WidgetB implements IWidget<WidgetB> {}
public class BWidgetManager extends WidgetManagerBase implements IWidgetManager<WidgetB> {}

@Override
public Class<? extends IWidgetManager<?>> getWidgetManagerClass() {
    return BWidgetManager.class;
}

【问题讨论】:

  • 为什么不public interface IBaseWidget&lt;R extends IBaseWidget&lt;R&gt;&gt; {}
  • @EpicPandaForce 好点,完成!谢谢。
  • 您是否需要比Class&lt;?&gt; 更具体的类型?除了以类型安全的方式获取 Constructor&lt;T&gt; 对象和枚举常量(在枚举类型的情况下)之外,使用更具体的 Class&lt;...&gt; 类型并不能做太多事情。它只会使您的界面复杂化。我建议坚持使用Class&lt;?&gt;,除非真的有必要。
  • @Nándor Előd Fekete 问题是这是一种可以被覆盖的方法。我希望尽可能具体地作为它的返回类型,以尽可能地帮助子类实现者。
  • 在使用递归泛型类型定义之前,请确保您确实需要它。如果只要求类型参数是IWidget 的子类,那么使用IWidget&lt;R extends IWidget&lt;?&gt;&gt;(它仍然保持类型安全)可以省去很多类型匹配的麻烦。仅在确实必须使用类型递归时才使用它。

标签: java generics


【解决方案1】:

由于Java Type Erasure,与MyWidget.class 最具体的匹配是Class&lt;? extends IWidget&gt;

public Class<? extends IWidget> test() {
    return MyWidget.class;
}

如果你想比你应该使用具体类型参数扩展 MyWidget 更具体:

public class ConcreteBaseWidget implements IBaseWidget<ConcreteBaseWidget> {
}

public class ConcreteWidget extends MyWidget<ConcreteBaseWidget> {
}

然后所有这些方法都会起作用:

public Class<? extends IWidget<? extends IBaseWidget<? extends IBaseWidget<?>>>> test1() {
    return ConcreteWidget.class;
}

public Class<? extends IWidget<? extends IBaseWidget<ConcreteBaseWidget>>> test2() {
    return ConcreteWidget.class;
}

public Class<? extends IWidget<? extends ConcreteBaseWidget>> test3() {
    return ConcreteWidget.class;
}

【讨论】:

  • 我没有预先的具体类型,这就是重点。但是public Class&lt;? extends IWidget&gt; test() 确实适用于@SuppressWarnings("rawtypes")。谢谢!
【解决方案2】:

我真的认为你只是在寻找

public interface IBaseWidget<R extends IBaseWidget<R>> {}

public interface IWidget<R extends IWidget<R>> extends IBaseWidget<R> {} //not sure about this one.

public class MyWidget implements IWidget<MyWidget> {}

这样您就可以将MyWidget.class 视为Class&lt;R&gt;

这是您要找的,还是我误解了您的意图?

编辑:

在这种情况下,

public interface IWidgetManager<R extends IWidget<R>> {}

public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R> {}

可以替换为

public interface IWidgetManager<R extends IWidget<R>, WM extends IWidgetManager<R, WM>> {}

public class MyWidgetManager<R extends IWidget<R>> implements IWidgetManager<R, MyWidgetManager> {}

因为这样您能够以Class&lt;WM&gt; 的身份访问MyWidgetManager.class

【讨论】:

  • 我修改了接口的名称,因为我的问题不够清楚......最后一个接口(名称为MyWidget)本身不是小部件!我将其重命名为IWidgetManager。不过,我的问题仍然存在......
  • 关于您的编辑:WM extends IWidgetManager&lt;WM&gt; 不起作用,因为IWidgetManager 有两个参数。
  • 对,我把它弄混了,但现在我已经修好了
  • MyWidgetManager 的最后一次出现时缺少&lt;B&gt;,但实际上在我可以看到它为Class&lt;MyWidgetManager&gt;Class&lt;? extends IWidgetManager&gt; 之后。但我不想使用具体类型。谢谢你的帮助。
猜你喜欢
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多