Java 方法参数可选?
Java Optional for method argument?
我正在读这个 post 关于使用可选的方法参数和共识似乎是永远不要为此目的使用它们。
Guava Optional as method argument for optional parameters
但是在 API 方面(不是应用程序方面)是否完全没有此规则的例外情况?我想不出更简洁的方法来处理某些情况,尤其是在可能使用或不使用自变量参数的初始化情况下。
以我正在构建的这个枚举为例,它提供了我们业务使用的四个数据库连接。前三个不需要参数,因为 DbManager
工厂已经有了它需要的配置信息。但是对于正在使用的 SQLite 数据库,SQLite 连接需要 URL。因此,我需要将我的 Supplier
变成 Function<Optional<String>,DatabaseConnection>
。
这种使用 Optional
作为方法参数的情况是否合法?如果不是,我怎样才能使它可枚举?
private static enum DbConnectionSupplier {
ORACLE(optArg -> DbManager.getOracleConnection()),
MYSQL(optArg -> DbManager.getMySQLConnection()),
TERADATA(optArg -> DbManager.getTeradataConnection()),
SQLITE(optArg -> DbManager.getSQLiteConnection(optArg.get()));
private final Function<Optional<String>, DatabaseConnection> supplier;
private DbConnectionSupplier(Function<Optional<String>, DatabaseConnection> supplier) {
this.supplier = supplier;
}
}
首先,如果您使用的是 lambda 表达式,那么您正在使用 Java 8 进行编译,您可以使用 java.util.Optional
,而不是 Guava 的。
我想你有以下方法:
DatabaseConnection getConnection(String arg) {
return supplier.apply(Optional.of(arg));
}
DatabaseConnection getConnection() {
return supplier.apply(Optional.empty());
}
现在,它不能保护您免受呼叫 TERADATA.getConnection("BAR")
的人的伤害。另一方面,SQLITE.getConnection()
将在 optArg.get()
处以 NoSuchElementException
(Java8) 或 IllegalStateException
(Guava) 失败,因为可选的是空的。
从该异常中不清楚 getConnection
中预期的参数(好吧,它可能很清楚,但调用 Function.apply
时堆栈跟踪将是 "polluted")
以下实现避免使用 Optional
,并清楚地表明是否需要参数。
TERADATA(()-> DbManager.getTeradataConnection()),
SQLITE(arg -> DbManager.getSQLiteConnection(arg)),
FOO(()-> DbManager.getFooConnection(),
arg->DbManager.getFooConnection(arg));
//Foo supports both styles: with and without a parameter
private final Supplier<DatabaseConnection> supplier;
private final Function<String, DatabaseConnection> function;
private DbConnectionSupplier(Supplier<DatabaseConnection> supplier) {
this.supplier = supplier;
this.function = null;
}
private DbConnectionSupplier(Function<String, DatabaseConnection> function) {
this.function = function;
this.supplier = null;
} `
private DbConnectionSupplier(
Supplier<DatabaseConnection> supplier,
Function<String, DatabaseConnection> function) {
this.function = function;
this.supplier = supplier;
}
public DatabaseConnection getConnection(String arg) {
if (function==null) throw ...
return function.apply(arg);
}
public DatabaseConnection getConnection() {
if (supplier==null) throw ...
return supplier.get();
}
我正在读这个 post 关于使用可选的方法参数和共识似乎是永远不要为此目的使用它们。
Guava Optional as method argument for optional parameters
但是在 API 方面(不是应用程序方面)是否完全没有此规则的例外情况?我想不出更简洁的方法来处理某些情况,尤其是在可能使用或不使用自变量参数的初始化情况下。
以我正在构建的这个枚举为例,它提供了我们业务使用的四个数据库连接。前三个不需要参数,因为 DbManager
工厂已经有了它需要的配置信息。但是对于正在使用的 SQLite 数据库,SQLite 连接需要 URL。因此,我需要将我的 Supplier
变成 Function<Optional<String>,DatabaseConnection>
。
这种使用 Optional
作为方法参数的情况是否合法?如果不是,我怎样才能使它可枚举?
private static enum DbConnectionSupplier {
ORACLE(optArg -> DbManager.getOracleConnection()),
MYSQL(optArg -> DbManager.getMySQLConnection()),
TERADATA(optArg -> DbManager.getTeradataConnection()),
SQLITE(optArg -> DbManager.getSQLiteConnection(optArg.get()));
private final Function<Optional<String>, DatabaseConnection> supplier;
private DbConnectionSupplier(Function<Optional<String>, DatabaseConnection> supplier) {
this.supplier = supplier;
}
}
首先,如果您使用的是 lambda 表达式,那么您正在使用 Java 8 进行编译,您可以使用 java.util.Optional
,而不是 Guava 的。
我想你有以下方法:
DatabaseConnection getConnection(String arg) {
return supplier.apply(Optional.of(arg));
}
DatabaseConnection getConnection() {
return supplier.apply(Optional.empty());
}
现在,它不能保护您免受呼叫 TERADATA.getConnection("BAR")
的人的伤害。另一方面,SQLITE.getConnection()
将在 optArg.get()
处以 NoSuchElementException
(Java8) 或 IllegalStateException
(Guava) 失败,因为可选的是空的。
从该异常中不清楚 getConnection
中预期的参数(好吧,它可能很清楚,但调用 Function.apply
时堆栈跟踪将是 "polluted")
以下实现避免使用 Optional
,并清楚地表明是否需要参数。
TERADATA(()-> DbManager.getTeradataConnection()),
SQLITE(arg -> DbManager.getSQLiteConnection(arg)),
FOO(()-> DbManager.getFooConnection(),
arg->DbManager.getFooConnection(arg));
//Foo supports both styles: with and without a parameter
private final Supplier<DatabaseConnection> supplier;
private final Function<String, DatabaseConnection> function;
private DbConnectionSupplier(Supplier<DatabaseConnection> supplier) {
this.supplier = supplier;
this.function = null;
}
private DbConnectionSupplier(Function<String, DatabaseConnection> function) {
this.function = function;
this.supplier = null;
} `
private DbConnectionSupplier(
Supplier<DatabaseConnection> supplier,
Function<String, DatabaseConnection> function) {
this.function = function;
this.supplier = supplier;
}
public DatabaseConnection getConnection(String arg) {
if (function==null) throw ...
return function.apply(arg);
}
public DatabaseConnection getConnection() {
if (supplier==null) throw ...
return supplier.get();
}