如果需要,如何调用将创建类对象的函数?



上下文:

我在我正在处理的 selenium 框架中发现了一个错误,其中 Web 浏览器(至少是 Chrome)意外崩溃,没有通知.
作为补丁,我正在重新初始化 WebDriver 以便它继续工作,但现在我正在创建一个新的 EdgeDriver,我想创建一个与之前相同类型的新 WebDriver(崩溃的那个)。

我想出了这种方法:

driver = Map.of(
ChromeDriver.class, getFunction(ChromeDriver.class),
EdgeDriver.class, getFunction(EdgeDriver.class),
FirefoxDriver.class, getFunction(FirefoxDriver.class),
OperaDriver.class, getFunction(OperaDriver.class)
).entrySet().stream().filter((e) -> e.getKey().isInstance(driver))
.map((e)->e.getValue().identity()).findFirst().orElseThrow(() -> new RuntimeException("WebDriver not detected"));

@SneakyThrows
static Function<Class<? extends RemoteWebDriver>, RemoteWebDriver> getFunction(Class<? extends RemoteWebDriver> driverClass){
return c -> {
try {
return c.getConstructor().newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
};
}

问题是我不能使用这种类型的呼叫

e.getValue().identity()

你知道我怎样才能做到这一点吗?

我正在使用Map方法,所以我不必指定一堆包含所有代码的if.
而且我正在使用一个单独的方法返回一个函数,所以我不必在需要之前(以及如果它们)花费资源来创建实例。

我以前遇到过这个问题,我很确定我会继续面对它,我几乎不知道我在函数式编程部分写了什么,因为我对它很陌生。我希望我走在正确的轨道上,但老实说,我对此表示怀疑。

作为一个额外的提示,如果你能提供一种成为Java函数式编程专家的方法,那就太好了,因为我一直在寻找一门课程或任何足够深入的资源,但到目前为止我还没有找到任何东西。不仅可以解决这个问题,还可以帮助我解决将来任何类似的问题。

由于getFunction(Class)返回一个Function<Class<? extends RemoteWebDriver>, RemoteWebDriver>因此您需要像e.getValue().apply(driver.getClass())一样称呼它。但是,Supplier<RemoteWebDriver>似乎更合适:

@SneakyThrows
static Supplier<RemoteWebDriver> getSupplier(Class<? extends RemoteWebDriver> driverClass){
return () -> {
try {
return driverClass.getConstructor().newInstance();
} catch (IllegalAccessException | InstantiationException e) {
throw new RuntimeException(e);
}
};
}

然后像....map((e)->e.getValue().get())一样使用它.

我从方法名称中更改了什么?

  • 返回一个Supplier<RemoveWebDriver>,该具有执行它的get()方法并返回结果
  • 由于供应商不接受争论,因此 lambda 从c -> { ... }变为() -> { ... }
  • c不再可用,但无论如何您都希望将参数"绑定"到 lambdagetSupplier(),这是可能的,因为它是"有效的最终"。这意味着您可以使用driverClass.getConstructor()而不是c.getConstructor()

但是,不需要所有这些复杂性 - 您只需将供应商直接放入地图中:

//the <Class<? extends RemoteWebDriver>, Supplier<? extends RemoteWebDriver>> is needed to help the compiler infer the generic types
Map.<Class<? extends RemoteWebDriver>, Supplier<? extends RemoteWebDriver>>of(ChromeDriver.class, ChromeDriver::new, 
EdgeDriver.class, EdgeDriver::new,
FirefoxDriver.class, FirefoxDriver::new,
OperaDriver.class, OperaDriver::new)
...

如果你不喜欢这个<Class<? extends RemoteWebDriver>, Supplier<? extends RemoteWebDriver>>你可以用一个类型为"baked in"的小方法来帮助编译器:

static Supplier<? extends RemoteWebDriver> supply(Supplier<? extends I> s) { return s ; }
Map.of(ChromeDriver.class, supply(ChromeDriver::new), 
EdgeDriver.class, supply(EdgeDriver::new),
FirefoxDriver.class, supply(FirefoxDriver::new),
OperaDriver.class, supply(OperaDriver::new))
...

您可以使用方法引用访问存储为Map.Entry::getValue但它不适用。

因为在map()中,您需要一个可以使用Map.Entry拨号的函数,但您的函数期望Class实例作为参数作为参数(即预期的参数不匹配)。

因此,正确的函数可以编写为以下lambda表达式:

e -> e.getValue().apply(e.getKey())

例:

RemoteWebDriver target = // initializing the target driver

RemoteWebDriver driver = Map.of(
ChromeDriver.class, getFunction(ChromeDriver.class),
EdgeDriver.class, getFunction(EdgeDriver.class),
FirefoxDriver.class, getFunction(FirefoxDriver.class),
OperaDriver.class, getFunction(OperaDriver.class)
)
.entrySet().stream()
.filter(e -> e.getKey().isInstance(target))
.map(e -> e.getValue().apply(e.getKey()))
.findFirst()
.orElseThrow(() -> new RuntimeException("WebDriver not detected"));

相关内容

  • 没有找到相关文章

最新更新