gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 20:16:42 24 4
gpt4 key购买 nike

我在使用 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com