Can可选用于捕获ConversionException的替代方法

问题描述 投票:0回答:3

如何重构下面的读取属性文件的代码,以便它根据读取值返回int,double或String?

    public static <T> T readFromConfig(String keyName) {
    PropertiesConfiguration config = new PropertiesConfiguration();
    String propertiesFilePath = "src/main/resources/application.properties";
    try {
        config.load(propertiesFilePath);
        try {
            Integer value = config.getInt(keyName);
            return (T) value;
        } catch (ConversionException notInteger) {
            try {
                Double value = config.getDouble(keyName);
                return (T) value;
            } catch (ConversionException notDouble) {
                return (T) config.getString(keyName);
            }
        }
    } catch (ConfigurationException e) {
        logger.warn("Could not parse " + propertiesFilePath);
        return (T) "";
    }
}
java monads optional
3个回答
1
投票

正如作者认为的那样:Optional<>在这里不是一个选项,因为,正如另一个答案所示:它将导致返回Optional<Object>,它提供更少的类型信息。

但老实说,从干净的代码角度来看,甚至是想法

public static <T> T readFromConfig(String keyName) {

有点瑕疵。这种方法买什么?没有。因为调用者说:我期望一个Integer回来,但你推回一个Double或甚至String。你看,编译器被告知“方法应该返回Integer,或者Double,......”,然后它会看到:“是的,可能的”。但这与运行时发生的事情完全脱钩。

如果你走的话:

Integer intVal = readFromConfig("keyPointingToDoubleValue");

编译器不会抱怨。因为它看到:你想要一个整数;嘿,该方法可以返回一个Integer。

在运行时?检索值并且不是Integer时,将返回Double或String。不知道这里会发生什么(类强制转换异常,或者可能是一些堆栈违规)。但它不应该在运行时工作。

所以,真正的解决方案是这样的:

要么有多种方法,例如:

public static Integer readIntegerFromConfig(String keyName) throws SomeException ...
public static Integer readIntegerFromConfig(String keyName, Integer Default) throws SomeException ...

或者可能:

public static Object readFromConfig(String keyName) {

要么

public static <T> T readFromConfig(String keyName, T default)

换句话说:您需要一个API,允许其用户真正说出他们想要的内容,并始终为他们提供他们想要的内容。或者你完全避免在该级别上的不同类型,并返回字符串,并让客户端代码进行转换。

正如你所说的那样,你当前的方法是以一种误导性的,复杂的API为代价购买任何东西。


1
投票

以下是我可以建议您这也明显违反单一责任原则(SRP),因为它试图转换为三种不同的类型,应该避免使用更清晰的代码:

public static Optional<Object> readFromConfig(String keyName) {
    PropertiesConfiguration config = new PropertiesConfiguration();
    String propertiesFilePath = "src/main/resources/opf.properties";
    try {
        config.load(propertiesFilePath);

        return Stream.<Supplier<Optional>>of(
                () -> Optional.of(config.getInt(keyName)),
                () -> Optional.of(config.getDouble(keyName)),
                () -> Optional.of(config.getString(keyName)))
                .map(Supplier::get)
                .filter(Optional::isPresent)
                .map(Optional::get)
                .findFirst();

    } catch (Exception e) {
        return Optional.empty();
    }
}

0
投票

那么,这就是讨论的结束。问题的答案“Can Optional可用于替代catchException吗?”没有

© www.soinside.com 2019 - 2024. All rights reserved.