java - 不同 Java 库中的重复类导致编译错误

标签 java selenium generics compiler-errors appium

我在使用 Appium java 客户端时遇到了问题,因为他们的项目似乎做了一些奇怪的事情。

基本上,他们在他们的项目中使用了 Selenium,这应该可以正常工作,但是他们从 Selenium 中复制了一个包的一部分到他们的项目中 (org.openqa.selenium) 并对类做了一些小的调整里面。基本上,他们向接口(interface)添加了泛型。现在我们在不同库的同一个包中有重复的类,这当然会导致问题。

我创建了一个简单的 Gradle 项目来演示这一点。 按照我的build.gradle:

plugins {
    id 'java-library'
}

dependencies {
    api 'io.appium:java-client:6.1.0'
}

repositories {
    jcenter()
}

还有我的类(class) Interactions.java:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class Interactions {

    public static void touchWebElement(By by, WebDriver driver) {
        touchWebElement(driver.findElement(by), driver);
    }

    public static void touchWebElement(WebElement element, WebDriver driver) {
        // DO SOMETHING
    }
}

现在,如果我编译该项目,我会收到以下错误:

The method touchWebElement(By, WebDriver) is ambiguous for the type Interactions    Interactions.java   line 8

我认为它有歧义,因为接口(interface) WebElement 存在两次。

我该如何解决这个问题?

  • 使用 appium-client <= 4.0.0 可以,但我需要更新的版本。
  • 目前,我只是从 jar 中删除了重复的包,并将这个 jar 包含到我的项目中。我真的只是用 7zip 删除了它。这清除了编译错误,但我可能很快就会遇到其他问题,因为 appium jar 不完整,如果没有该包,appium 项目甚至无法编译。
  • Selenium 人员可能不会改变任何东西 (https://github.com/SeleniumHQ/selenium/pull/863)。
  • Appium 的人可能不知道如何解决这个问题,我也是:https://github.com/appium/java-client/issues/1021

解决方案:

在接受的答案的帮助下,我能够解决这些问题。 尽管我需要想出一个稍微不同的解决方案。 我面临的问题是,称为我的 Interactions.java 的类也需要那些会导致 1000 多个改编的类型转换。为了防止这种情况,我更改了方法以将 Object 作为参数:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class Interactions {
    public static void touchWebElement(Object object, WebDriver driver){
        WebElement webElement = castObjectToWebElement(element, driver);
        //DO SOMETHING
    }

    private static WebElement castObjectToWebElement(Object object, WebDriver driver) {
        if (object instanceof WebElement) {
            return (WebElement) object;
        } else if (object instanceof By) {
            return driver.findElement((By) object);
        }
        throw new IllegalArgumentException("Invalid type");
    }
}

它可能不是最佳解决方案,但它可以工作并且不需要在我们所有其他类中进行更改,并且到目前为止每个人都可以使用这些交互方法。

最佳答案

问题不在于重复类,而在于泛型的使用方式。这里有一点 MCVE复制 Appium 中的情况 WebDriver类:

package de.scrum_master.stackoverflow;

public interface WebElement {}
package de.scrum_master.stackoverflow;

public interface WebDriver {
  <T extends WebElement> T findElement();
}
package de.scrum_master.stackoverflow;

public class Application {
  static WebDriver webDriver;

  static void myOverloadedMethod(String text) {}
  static void myOverloadedMethod(WebElement text) {}

  public static void main(String[] args) {
    // These 3 variants work
    myOverloadedMethod("test");
    myOverloadedMethod((WebElement) webDriver.findElement());
    WebElement webElement = webDriver.findElement();
    myOverloadedMethod(webElement);

    // This one does not work
    myOverloadedMethod(webDriver.findElement());
  }
}

解释:由于type erasure doSomething的通用返回类型 <T extends WebElement>评估为 Object ,因此当尝试使用该结果调用 myOverloadedMethod(..) 时编译器不知道选择哪种方法。

解决方案:您需要通过转换或显式声明包含方法参数的变量的类型来提供帮助。

附注:如果您要修改 interface WebDriver 中的接口(interface)定义至 interface WebDriver<T> ,编译错误就会消失。但是 Appium 的实现并没有这样做,可能是因为他们想尽可能地与原始的 Selenium 类保持兼容(?)。你必须问他们。


更新:因为 OP 似乎无法理解我的答案,或者认为我没有尝试他的示例代码,我当然用它来重现和理解他的问题:

package de.scrum_master.appium;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class Interactions {
  public static void touchWebElement(WebElement element, WebDriver driver) {}

  public static void touchWebElement(By by, WebDriver driver) {
    // Works
    WebElement webElement = driver.findElement(by);
    touchWebElement(webElement, driver);
    // Works
    touchWebElement((WebElement) driver.findElement(by), driver);
    // Ambiguous due to type erasure -> does not work
    touchWebElement(driver.findElement(by), driver);
  }
}

这里绝对不需要重命名方法、重新打包任何类或执行其他类型的 Maven/Gradle 特技。

关于java - 不同 Java 库中的重复类导致编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54604601/

相关文章:

scala - 从 Azavea Numeric 获取隐式 scala Numeric

swift - 如何使用通用参数对函数执行 "optional unwrapping"

java - 使用空对象引用调用静态方法时会发生什么?

java - 期待编程的 future ,但不知道从哪里开始

java - org.openqa.selenium.NoSuchElementException 即使 xpath 正确并且添加了等待

c# - 如何检查通用列表中的空项目

java - 兰顿 Ant 算法

java - Java 环境(Resin+Quercus)中的 WordPress 无需任何额外的代码调整?

java - 将 BrowserMob 代理传递给 Sauce Labs - "The proxy server is refusing connections"错误

java.lang.NoClassDefFoundError : org/w3c/dom/ElementTraversal 错误