Java: 隐式类型转换,或隐式 toString() 调用

Java: implicit type conversion, or implicit toString() invocation

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

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

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

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

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

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

注意,我不能更改第 3 方代码(无论如何不能没有字节码操作),并且我想保留我的设计 return Either 从我的方法。

有没有办法简化我的代码并使其看起来像

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

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

实际上,如果我不得不这样做,我并不介意

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

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

给定一个 either,不难看出它代表 Right 还是 Left,只需检查哪一侧有 null.

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

我能够通过 AspectJ 捕获 my.calculateEither() 的 return 值,但我看不到如何使用 @AfterReturning 之类的建议让编译器理解我的方法想要returnmy.calculateEither().getLeft(),即String.....

有什么想法吗?

添加辅助方法。由于您无法将新方法添加到 their,因此您必须将 static 添加到您自己的 class。

伪代码:

public static void thirdParty(Their their, Either either) {
    if (either.isLeft())
        their.thirdPartyExpectsString(either.getLeft());
    else
        their.thirdPartyExpectsDouble(either.getRight());
}

您现在可以拨打:

MyHelper.thirdParty(their, my.calculateEither())

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

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

请注意,我故意忽略了有关未经检查的转换的警告,如果您在与外部 API 接口的地方使用它,确实会导致 ClassCastException left 值,但您在包含 right 值的 Either 实例上调用它。此方法将根据您的使用位置进行 隐式转换 。它将转换为 T 类型,您将其传递给另一个需要类型 T 参数的方法,或者您尝试将方法 return 值分配给类型 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 对象包含的实际值的所有地方。不幸的是,你只能在 运行 时间 发现,如果不是这样的话。