当泛型方法 returns 'nothing' 但 null 不能 returned 时,return 怎么办?
What to return when generic methods returns 'nothing' but null can't be returned?
假设我有这样一个库方法(非常简短):
public static <V> Optional<V> doSomethingWith(Callable<V> callable) {
try {
return Optional.of(callable.call());
} catch (Exception ex) {
// Do something with ex
return Optional.empty();
}
}
我想要一些没有 return 值的东西,例如:
Library.</*What1*/>doSomethingWith(() -> {
foo();
return /*what2*/;
});
我对没有 return 值的泛型方法的第一直觉是使类型 Void
和 returning null
,但是因为结果是包装在 Optional
中,这会引发异常。
/*What1*/
和 /*what2*/
的合理占位符是什么,它们看起来不像 Integer
和 0
那样完全随机?
[编辑]
我试图避免 Optional.ofNullable
因为这里使用 empty 表示 callable.call()
没有正常完成。
如果您需要一个永远不会被使用的通用参数的类型提示,您可以使用 Void
,JDK 在某些情况下也会这样做,例如将 Runnable
转换为 CompletableFuture<T>
时,它对 T.
使用 Void
如果你使用 Optional.ofNullable
那么你可以 return null
for what2,这是 Void
.
的唯一有效值
[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
那么您使用了错误的工具来完成这项工作。 CompletionStage
或 CompletableFuture
具有正确的语义。
对return类型使用Void
,这是"nothing"的合理选择,但实际上return是Void
的一个实例。
虽然 javadoc for Void
说是:
...an uninstantiable placeholder class...
你仍然可以实例化它:
try {
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();
} catch (Exception perfunctory) {
return null; // won't happen
}
您也可以创建自己的类型,类似于 Void
public class Result {
public static final Result OK = new Result();
private Result(){}
}
然后 return Result.OK
.
如果需要,您还可以增强此类型以表示错误。
但如果您不需要任何特殊的东西,也许使用 java Void
更可取。
我通常使用 Boolean.TRUE
来标记成功,但您也可以 return Void.class
。两者都很便宜,因为并非每个 return 都会创建一个要丢弃的新对象。虽然 Class<Void>
不仅仅是 Void
,但它也可以用于将某些东西标记为 void
。
如前所述,您也可以创建自己的 Result-class/-enum。
或者您当然也可以 return Optional.<Void>nothing()
。这会导致一些 Optional<Optional<Void>>
,但也可以解决问题。
如果您认为以上所有内容都很丑陋,我担心 API 可能无法很好地满足您的需求。提出 issue/pull 请求或寻找其他东西。
假设我有这样一个库方法(非常简短):
public static <V> Optional<V> doSomethingWith(Callable<V> callable) {
try {
return Optional.of(callable.call());
} catch (Exception ex) {
// Do something with ex
return Optional.empty();
}
}
我想要一些没有 return 值的东西,例如:
Library.</*What1*/>doSomethingWith(() -> {
foo();
return /*what2*/;
});
我对没有 return 值的泛型方法的第一直觉是使类型 Void
和 returning null
,但是因为结果是包装在 Optional
中,这会引发异常。
/*What1*/
和 /*what2*/
的合理占位符是什么,它们看起来不像 Integer
和 0
那样完全随机?
[编辑]
我试图避免 Optional.ofNullable
因为这里使用 empty 表示 callable.call()
没有正常完成。
如果您需要一个永远不会被使用的通用参数的类型提示,您可以使用 Void
,JDK 在某些情况下也会这样做,例如将 Runnable
转换为 CompletableFuture<T>
时,它对 T.
如果你使用 Optional.ofNullable
那么你可以 return null
for what2,这是 Void
.
[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
那么您使用了错误的工具来完成这项工作。 CompletionStage
或 CompletableFuture
具有正确的语义。
对return类型使用Void
,这是"nothing"的合理选择,但实际上return是Void
的一个实例。
虽然 javadoc for Void
说是:
...an uninstantiable placeholder class...
你仍然可以实例化它:
try {
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();
} catch (Exception perfunctory) {
return null; // won't happen
}
您也可以创建自己的类型,类似于 Void
public class Result {
public static final Result OK = new Result();
private Result(){}
}
然后 return Result.OK
.
如果需要,您还可以增强此类型以表示错误。
但如果您不需要任何特殊的东西,也许使用 java Void
更可取。
我通常使用 Boolean.TRUE
来标记成功,但您也可以 return Void.class
。两者都很便宜,因为并非每个 return 都会创建一个要丢弃的新对象。虽然 Class<Void>
不仅仅是 Void
,但它也可以用于将某些东西标记为 void
。
如前所述,您也可以创建自己的 Result-class/-enum。
或者您当然也可以 return Optional.<Void>nothing()
。这会导致一些 Optional<Optional<Void>>
,但也可以解决问题。
如果您认为以上所有内容都很丑陋,我担心 API 可能无法很好地满足您的需求。提出 issue/pull 请求或寻找其他东西。