Java 无法从Guava解析泛型参数TypeToken

Java 无法从Guava解析泛型参数TypeToken,java,generics,guava,Java,Generics,Guava,我正在为Selenium测试框架开发一个构建泛型菜单的框架,我一直在使用Guava TypeToken来解析泛型参数的类型,但现在我遇到了一个问题,类型标记无法解析参数: 我有一个摘要base类,用于生成菜单选项的生成器: public abstract class AbstractMenuOptionBuilder<O extends IClickable> { protected final TypeToken<AbstractMenuOptionBuilder

我正在为Selenium测试框架开发一个构建泛型菜单的框架,我一直在使用Guava TypeToken来解析泛型参数的类型,但现在我遇到了一个问题,类型标记无法解析参数:

我有一个
摘要
base
,用于生成菜单选项的生成器:

public abstract class AbstractMenuOptionBuilder<O extends IClickable>  {

    protected final TypeToken<AbstractMenuOptionBuilder<O>> typeToken = new
            TypeToken<AbstractMenuOptionBuilder<O>>(getClass()) { };

    public abstract O create();
}
我有一个菜单的
abstract
base
class
,它有一个返回菜单选项列表的方法:

public abstract class AbstractMenu<O extends IClickable> {

    public final List<O> getOptions() {

        //This is where my plan doesn't work. The runtime type is given by
        //a concrete menu class which extends AbstractMenu, but that runtime
        //type doesn't seem to pass through to the abstract base class for the builder.
        MenuOptionBuilder<O> builder = new MenuOptionBuilder<O>(new MenuOptionBean()){};

             <.... snip ....>
    }

}
我希望
MenuOptionBuilder
中的变量
genericOptionParam
将解析为
Link
,但它没有,而是解析为
O
,泛型类型参数的名称,而不是它的运行时类型
Link
。如果我像这样创建一个附加的base
,则泛型参数将正确解析:

public abstract class AbstractSimpleLinkedMenu extends AbstractMenu<Link> {

    public final List<Link> getOptions() {

        MenuOptionBuilder<Link> builder = new MenuOptionBuilder<Link>(new MenuOptionBean()){};
        <.... snip ....>
    }
} 
公共抽象类AbstractSimpleLinedMenu扩展了AbstractMenu{
公共最终列表getOptions(){
MenuOptionBuilder=new MenuOptionBuilder(new MenuOptionBean()){};
}
} 

我不想添加额外的基类,比如
AbstractSimpleLinekedMenu
,那么这里是否有我遗漏或做得不正确的地方?我认为抽象构建器的匿名内部类应该知道运行时类型,但如果使用泛型参数声明构建器,则不会知道。运行时类型由具体菜单
class
SimpleMenu
指定,但它似乎没有过滤到菜单选项的
abstract
builder类。

这就是
TypeToken
“hack”的工作方式。它使用(或
getGenericSuperInterface
)。它的javadoc声明

如果超类是参数化类型,则返回
type
对象 必须准确反映源中使用的实际类型参数 代码。

在这种情况下,即
O
,此处

public abstract class AbstractMenuOptionBuilder<O extends IClickable>
然后您将获得
链接

在这种情况下

MenuOptionBuilder<O> builder = 
    new MenuOptionBuilder<O>(new MenuOptionBean()){};
MenuOptionBuilder=
新建MenuOptionBuilder(新建MenuOptionBean()){};
您已经硬编码了
O
,因此这就是您将得到的结果

以下是我在类型标记主题上写的更多内容:


    • 这就是
      TypeToken
      “hack”的工作原理。它使用(或
      getGenericSuperInterface
      )。它的javadoc声明

      如果超类是参数化类型,则返回
      type
      对象 必须准确反映源中使用的实际类型参数 代码。

      在这种情况下,即
      O
      ,此处

      public abstract class AbstractMenuOptionBuilder<O extends IClickable>
      
      然后您将获得
      链接

      在这种情况下

      MenuOptionBuilder<O> builder = 
          new MenuOptionBuilder<O>(new MenuOptionBean()){};
      
      MenuOptionBuilder=
      新建MenuOptionBuilder(新建MenuOptionBean()){};
      
      您已经硬编码了
      O
      ,因此这就是您将得到的结果

      以下是我在类型标记主题上写的更多内容:


      事实上,这条线很管用。这是一个没有:
      MenuOptionBuilder=new MenuOptionBuilder(new MenuOptionBean()){}。当我用具体类型(如
      Link
      )声明构建器时,其底层
      abstract
      base
      class
      中的类型标记可以将运行时类型解析为
      Link
      。但是,我不能使用像
      O
      这样的泛型类型参数来声明它,也不能依赖类型标记来解析conrete菜单
      class
      extensing
      AbstractMenu
      @Selena指定的运行时类型。我之前无法处理您的评论。但后来我又重读了所有的东西,完全如我所说。在
      MenuOptionBuilder
      中,源代码使用具体类型
      Link
      作为参数,因此
      getGenericSuperclass
      将返回该类型。在
      MenuOptionBuilder
      中,源代码包含类型参数
      O
      作为类型参数。所以,同样,这就是将要返回的内容。@Selena但我将编辑我所说的内容以澄清,因为我看到我的最后一句话不是我的意思。我怀疑是这样的。我一直希望TypeToken能够从具体的菜单声明中派生出运行时类型,但这显然不会发生。不管怎样,我找到了一种绕过这个限制的方法。事实上,这条线是有效的。这是一个没有:
      MenuOptionBuilder=new MenuOptionBuilder(new MenuOptionBean()){}。当我用具体类型(如
      Link
      )声明构建器时,其底层
      abstract
      base
      class
      中的类型标记可以将运行时类型解析为
      Link
      。但是,我不能使用像
      O
      这样的泛型类型参数来声明它,也不能依赖类型标记来解析conrete菜单
      class
      extensing
      AbstractMenu
      @Selena指定的运行时类型。我之前无法处理您的评论。但后来我又重读了所有的东西,完全如我所说。在
      MenuOptionBuilder
      中,源代码使用具体类型
      Link
      作为参数,因此
      getGenericSuperclass
      将返回该类型。在
      MenuOptionBuilder
      中,源代码包含类型参数
      O
      作为类型参数。所以,同样,这就是将要返回的内容。@Selena但我将编辑我所说的内容以澄清,因为我看到我的最后一句话不是我的意思。我怀疑是这样的。我一直希望TypeToken能够从具体的菜单声明中派生出运行时类型,但这显然不会发生。无论如何,我找到了一种绕过这个限制的方法。
      MenuOptionBuilder<O> builder = 
          new MenuOptionBuilder<O>(new MenuOptionBean()){};