【问题标题】:Bound mismatch error and java generic method绑定不匹配错误和java泛型方法
【发布时间】:2013-04-08 16:06:29
【问题描述】:

我收到以下错误:

Bound mismatch: The generic method constructPage(WebDriver, int, Class<T>) of type     
Page<T> is not applicable for the arguments (WebDriver, int, Class<HomePage>). The 
inferred type HomePage is not a valid substitute for the bounded parameter <T extends 
Page<T>>

我正在尝试登录,如果成功则返回主页,如果不使用泛型,则返回 LoginPage。

我有一个基类,页面,它由 SecuredPage 扩展,用于登录墙后面的页面。我写了一个通用的辅助方法,可以构造任何类型的页面。此方法由 LoginPage 上的 login 方法使用。 LoginPage 扩展 Page 和 HomePage 扩展 SecuredPage。 SecuredPage 扩展了 Page。如果返回 LoginPage,则 login 方法有效,但在尝试返回 HomePage 时出现上述错误。由于 HomePage 是 page 的子类,因为它的父类扩展了 Page,我很困惑为什么 HomePage 不是有界参数&lt;T extends Page&lt;T&gt;&gt; 的有效替代品。

public abstract class Page<T extends Page<T>> extends SlowLoadableComponent<T> {

    protected static final <T extends Page<T>> T constructPage(WebDriver driver, 
    int timeoutInSeconds, java.lang.Class<T> pageClass) 
    {
        Page<T> p = null;

        try {
            Constructor<T> pageConstructor = pageClass.getConstructor(
            WebDriver.class, String.class, Integer.TYPE);
            p = pageConstructor.newInstance(driver, driver.getCurrentUrl(), 
                timeoutInSeconds);
            p.get();

        } catch(Exception e) {

        }

        return pageClass.cast(p);       
    }
}

这是 SecuredPage 类:

public class SecuredPage extends Page<SecuredPage> {

    .....
}

这是主页:

public final class HomePage extends SecuredPage {
    ......
}

这是登录页面:

public final class LoginPage extends Page<LoginPage>  {


    public final HomePage loginWithGoodCredentials(final User user) {
        return login(user, HomePage.class);
    }

    public final LoginPage loginWithBadCredentials(final User user) {
        return login(user, LoginPage.class);
    }


    public final <T extends Page<T>> T login(final User user, final Class<T>     
            expectedPage) {
        enterUsername(user.getUsername());
        enterPassword(user.getPassword());
         loginButton.click();

        return Page.constructPage(getDriver(), getTimeoutInSeconds(), 
        expectedPage);
    }
}

【问题讨论】:

  • 绑定的 class Page&lt;T extends Page&lt;T&gt;&gt; 在 Java 中几乎没有用处

标签: java generics selenium-webdriver


【解决方案1】:

问题在于HomePagePage&lt;SecuredPage&gt; 而不是Page&lt;HomePage&gt;login 方法会从其通用签名中返回 Page&lt;HomePage&gt;

您必须使HomePage 的泛型参数与其自身相关,而不是SecuredPage。这将解决编译器错误。保持SecuredPage 通用,但确保其边界扩展SecuredPage&lt;T&gt;。然后将HomePage本身赋值给HomePage中的泛型参数T

class SecuredPage<T extends SecuredPage<T>> extends Page<T> {
...
}
class HomePage extends SecuredPage<HomePage>  {
...
}

【讨论】:

    【解决方案2】:

    调用login(user, SecuredPage.class) 有效,但login(user, HomePage.class) 无效。原因是:SecuredPage中的类型参数TSecuredPageHomePageSecuredPage的子类,所以HomePageT类型参数也是SecuredPage

    现在,您使用Page&lt;HomePage&gt; 致电login。但是这样的类是不存在的。 HomePagePage&lt;SecuredPage&gt; 的子类。

    【讨论】:

    • 那么,我需要在 SecuredPage 的类声明中做什么才能使其正常工作?显然,我对泛型不是很有经验....
    • 这样是否正确:public class SecuredPage> extends Page 然后 HomePage 可能是:public class HomePage extends SecuredPage
    • 所有超类必须有泛型参数T,只有具体的子类才能有自循环类型。我会实现一个AbstractSecuredPage&lt;T&gt; 和一个最终类SecuredPage
    • 感谢您的帮助。我接受了 rgettman 的回答,因为它解决了我的问题,而且我不能让 SecuredPage 成为最终课程。我需要能够扩展它。不幸的是,我无法投票支持您的答案,因为我没有足够的声誉,这太糟糕了,因为您指出了错误的原因。
    【解决方案3】:

    如果您仍希望 HomePage 在存在 Bounded Generics 的情况下扩展 SecuredPage,请传递“Generic Substitution”直到主页。

    不要将 Generic 替换为 SecuredPage,而是将 SecuredPage 替换为

    public class  SecuredPage<T extends Page<T>> extends Page<T> {
    
    }
    

    在创建HomePage 时,像这样声明泛型的值,

    public class HomePage extends SecuredPage<HomePage> {
    
    }
    

    这应该基本上解决了错误

    【讨论】:

      【解决方案4】:

      就您的constructPage 方法而言,您可以使用

      protected static final <T extends Page<?>> T constructPage(...) 
      {
          Page<?> p = null;
          //...
      }
      

      【讨论】:

      • 谢谢。我希望我能接受两个答案,因为你的答案突出了我花了很长时间才得到的关于泛型的一些东西。
      【解决方案5】:

      如果您仍然遇到同样的错误,请将编译器级别的 JDK 1.8 或最新版本从 Window > Preferences > Java > Compiler > "Compiler Compilation level" -> 1.8

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多