在我的Java应用程序中,我创建了返回Either<String, T>对象的方法。

这是因为在某些地方,我将这些方法作为(第3方)方法的参数调用,这些方法希望将String参数作为输入。
在其他地方,我将这些方法作为(第三方)方法的参数调用,这些方法需要其他一些参数类型(T)作为输入。

因此,根据我调用创建的方法的位置,代码如下所示:

their.thirdPartyExpectsString(my.calculateEither().getLeft());
their.thirdPartyExpectsString(my.calculateEither() + "");


要么

their.thirdPartyExpectsDouble(my.calculateEither().getRight());


(我将Either.toString()定义为Either.getLeft())。

请注意,我无法更改第三方代码(无论如何不能没有字节码操作),并且我希望保持我的设计能够从方法中返回Either

有没有一种方法可以简化我的代码并使它看起来像

their.thirdPartyExpectsString(my.calculateEither());
their.thirdPartyExpectsDouble(my.calculateEither());


也就是说,不必一直添加getLeft()/getRight()+ ""吗?

其实,如果我必须做的话,这不会打扰我

their.thirdPartyExpectsDouble(my.calculateEither().getRight());


因为我不必经常这样做。但是我想摆脱当getLeft()返回+ ""(字符串)时调用my.calculateEither()Left的需要。

给定either,只需检查哪一侧具有Right,就不难发现它代表的是Left还是null

但是问题出在类型转换上,即thirdPartyExpectsString()需要String但得到Either时的编译错误。

我可以通过AspectJ捕获my.calculateEither()的返回值,但是我看不到如何使用类似@AfterReturning的建议的方式来使编译器理解我要返回my.calculateEither().getLeft()(即String)的方法。 ...

有任何想法吗?

最佳答案

将以下方法添加到Either类的实现中:

@SuppressWarnings("unchecked")
public <T> T whichever() {
    return (T) (isLeft() ? getLeft() : getRight());
}


请注意,我故意忽略有关未经检查的强制转换的警告,并且如果在与之交互的外部API需要左值但在ClassCastException实例上调用它的地方使用它,的确会导致Either其中包含一个正确的值。此方法将根据使用位置进行隐式转换。它将转换为T类型,然后将其传递给另一个需要T类型参数的方法,或者尝试将方法返回值分配给T类型的变量。

因此,下面的演示代码:

Either<String, Double> containsString = Either.<String, Double>left("first");
Either<String, Double> containsDouble = Either.<String, Double>right(2d);

their.expectsString(containsString.whichever());
their.expectsDouble(containsDouble.whichever());
their.expectsDouble(containsString.whichever());


可以在第一次调用中很好地工作,并且会在第三次调用中导致ClassCastException,就像我们期望的那样,因为我们认为这是非法用例。

总之,很高兴知道它将在所有我们隐式转换为T类型的对象都可以分配给Either对象所包含的实际值的地方使用。不幸的是,如果不是这种情况,您将只能在运行时查找。

关于java - Java:隐式类型转换或隐式toString()调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35953155/

10-13 08:03