2

Here is some code that is more or less a "daily" pattern:

public static Value getValue() {    
    if ( cond1 ) {
        return val1;
    }
    if ( cond2 ) {
        return val2;
    }
    if ( cond3 ) {
        return val3;
    }
    throw new AnyException();
}

At the very first glance, it seems to be able to collapse into a single return statement preserving short-circuit computation like this:

public static Value getValue() {    
    return cond1 ? val1 :
           cond2 ? val2 :
           cond3 ? val3 :
           throw new AnyException() // it could be a legal piece of code in Java
                                    // if the `throw` statement could be an expression
           ;
}

However, it's not legal, because throw is a statement keyword, not an expression. I've tried the following workaround using a generic method:

// Exceptions.java
// Just pretend to let the compiler think it's not an exception statement
public static <T, E extends Throwable> T exception(E ex) throws E {
    throw ex;
}

...
// Return.java
public static Value getValue() {    
    return cond1 ? val1 :
           cond2 ? val2 :
           cond3 ? val3 :
           Exceptions.<Value, AnyException>exception(new AnyException());
}

The the last line in the return statement looks ugly because:

  • verbose syntax and required type parameterization;
  • a static import directive cannot be used here.

Is there an elegant way to make that code a little nicer? Thanks in advance.

(I still must use Java 6)

EDIT:

Well, three years later, this feature is suprisingly implemented for C# 7.0. I find it really useful and natural, and not complicated. Example:

public string GetFirstName()
{
    var parts = Name.Split(" ");
    return parts.Length > 0
        ? parts[0]
        : throw new InvalidOperationException("No name!");
}

Lucky C# guys.

4

4 回答 4

5

如果您exception在条件运算符之外使用,那么类型推断会做正确的事情。在这里,您可以直接将结果向下转换为 ,而不是指定类型参数Value,或者在本地为exception()

return cond1 ? val1 :
       cond2 ? val2 :
       cond3 ? val3 :
       (Value)exception(new AnyException());

或全局,对于整个条件表达式:

return (Value) (
       cond1 ? val1 :
       cond2 ? val2 :
       cond3 ? val3 :
       exception(new AnyException()));

就优雅而言,这仍然不是黄金,但我认为它还有很长的路要走。请注意,在这种情况下,您可以对exception().

于 2013-09-16T13:13:58.357 回答
2

如果您重新排列行并添加另一个if语句,则可以最大限度地减少行数,同时仍然具有可读性。

if(!(cond1 || cond2 || cond3)) throw new AnyException();
return cond1 ? val1 :
       cond2 ? val2 :
       cond3 ? val3;

我必须说你把事情复杂化了。可读的代码几乎总是比真正简洁的代码更好。在您的第一个示例中,我立即看到您要做什么。在你的第二个例子中,我实际上必须集中注意力。

于 2013-09-16T12:30:11.453 回答
2

还有另一种方法可以在没有泛型的情况下引发泛型异常。

// Exceptions.java
// Just pretend to let the compiler think it's not an exception statement
public static <T> T exception(E ex, Class<T> tClass) {
    Thread.currentThread().stop(ex);
    return null;
}

...
// Return.java
public static Value getValue() {    
    return cond1 ? val1 :
           cond2 ? val2 :
           cond3 ? val3 :
           exception(new AnyException(), Value.class); // import static Exception
}

你也可以使用 Unsafe.throwException(e);

于 2013-09-16T13:16:11.103 回答
0
int length = 1;
String s = "abc"

return (length == s.length())? length: length+1;

返回函数的 if else 简写。

于 2020-05-08T11:59:40.520 回答