Java:折叠短;如果/否则“;用简单的;return";s和尾随“;扔;变成一个“单一的”;return";

Java:折叠短;如果/否则“;用简单的;return";s和尾随“;扔;变成一个“单一的”;return";,java,syntax,type-inference,short-circuiting,Java,Syntax,Type Inference,Short Circuiting,以下是一些或多或少属于“每日”模式的代码: 公共静态值getValue(){ 如果(条件1){ 返回值1; } 如果(条件2){ 返回值2; } 如果(第3条){ 返回值3; } 抛出新的AnyException(); } 乍一看,它似乎能够折叠成一个return语句来保存短路计算,如下所示: 公共静态值getValue(){ 返回条件1?val1: cond2?val2: cond3?val3: 抛出new AnyException()//它可能是Java中的一段合法代码 //如果'thro

以下是一些或多或少属于“每日”模式的代码:

公共静态值getValue(){
如果(条件1){
返回值1;
}
如果(条件2){
返回值2;
}
如果(第3条){
返回值3;
}
抛出新的AnyException();
}
乍一看,它似乎能够折叠成一个
return
语句来保存短路计算,如下所示:

公共静态值getValue(){
返回条件1?val1:
cond2?val2:
cond3?val3:
抛出new AnyException()//它可能是Java中的一段合法代码
//如果'throw'语句可以是一个表达式
;
}
但是,这是不合法的,因为
throw
是语句关键字,而不是表达式。我已使用通用方法尝试了以下解决方法:

//Exceptions.java
//只要假装让编译器认为它不是异常语句
公共静态T异常(E ex)抛出E{
掷骰子;
}
...
//Return.java
公共静态值getValue(){
返回条件1?val1:
cond2?val2:
cond3?val3:
Exceptions.exception(newanyexception());
}
return
语句的最后一行看起来很难看,因为:

  • 详细语法和所需的类型参数化
  • 此处不能使用静态导入指令
有没有一种优雅的方法可以让代码变得更好?提前谢谢

(我仍然必须使用Java6)

编辑:

好吧,三年后,这项功能令人惊讶地为我们实现了。我觉得它真的很有用,很自然,也不复杂。例如:

公共字符串GetFirstName()
{
var parts=Name.Split(“”);
返回零件。长度>0
?零件[0]
:抛出新的InvalidOperationException(“无名称!”);
}

幸运的C#伙计们。

如果您重新安排行并添加另一个
If
语句,您可以在仍然具有可读性的情况下最小化行数

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

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

如果在条件运算符之外使用了
exception
,那么类型推断将是正确的。在这里,您不必指定类型参数,只需将结果向下转换为
Value
,也可以是本地的
exception()

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

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

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

进行静态导入,还有一种方法可以在不使用泛型的情况下引发泛型异常

// 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
}
//Exceptions.java
//只要假装让编译器认为它不是异常语句
公共静态T异常(例如,类tClass){
Thread.currentThread()停止(ex);
返回null;
}
...
//Return.java
公共静态值getValue(){
返回条件1?val1:
cond2?val2:
cond3?val3:
异常(new AnyException(),Value.class);//导入静态异常
}
您还可以使用不安全的.throwException(e)


返回函数的缩写if-else。

为什么要编写如此复杂的代码??代码简单明了。我不认为您的第二个示例有任何优势,但它将很难调试和测试maintain@MaximShoustin但是
?:
对于短表达式来说也很简单明了…我的意思是
通配符
和链接代码,比如
?:?:。试着在
return
@MaximShoustin上设置制动点是的,我想折叠成一个单一的返回,这会杀死断点。这封信写得很好,谢谢可读性在这里是关于例程的:我个人一直都在使用这样的条件运算符,在阅读第二个示例时,我必须更加集中精力。这是因为第二个示例只有一个退出点,它在开始时用一个
返回值
+1或
如果(!cond1&&!cond2&&!cond3)
在这种情况下,最后一个
cond3
检查应该是多余的,它必须是真的。感谢您的回复,但这有几个问题:1)条件必须始终反映在两个地方,这使得代码比我预期的要复杂得多:我希望它尽可能短;2) condN可能代表函数调用。这会偷偷抛出异常,允许您在不声明已检查异常的情况下抛出已检查异常。我个人喜欢这个事实,并且经常使用基于泛型的“偷偷抛出”习惯用法,但OP可能不是:)事实上,我认为这是对OP问题的最好回答:将
作为第二个参数传递给
异常
方法是避免显式参数化的最好方法。因此,使用这个答案签名中的建议,我们可以简单地调用
异常(ex,Object.class)
,这比显式地参数化方法调用要短
Thread.currentThread().stop(ex)
可以替换为
throw ex
,以避免Marko Topolnik提到的选中/未选中问题。@Yura然后我会有两个变量:带类型标记参数和不带类型标记参数,因为在其他上下文(条件运算符之外)中,可以清楚地推断类型。但无论如何,使用类型标记与简单的向下转换相比并没有多大的好处。很明显,向下投射永远不会失败:)@MarkoTopolnik是的,你说得对-向下投射也是一个很好的方式来感谢你的答案,Marko,并指出我错过了结果的类型投射。这正是我想要的:缩短
// 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
}
int length = 1;
String s = "abc"

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