【问题标题】:Initialize variable with complex expression [closed]用复杂的表达式初始化变量[关闭]
【发布时间】:2017-05-18 14:57:06
【问题描述】:

Java 8 中有没有一种方法可以同时使用复杂表达式的结果声明和初始化 final 变量?

换句话说,是否可能出现以下情况?

final int x = [capturedVariable] {
    switch (capturedVariable) {
    case 1: return 42;
    case 2: return 84;
    default: return 66;
    }
};

虽然语法显然是“创造性的”,但我希望意图是明确的。

编辑 1:虽然这个特定示例可以使用三元运算符编写,但它只是一个复杂表达式的示例,我正在寻找一个通用的解决方案。

编辑 2:也许以下是看待这个问题的争议较小的方式:在 Java 8 中同时声明和调用 lambda/闭包的语法是什么?

【问题讨论】:

  • 写一个方法? final int x = someMethod(capturedVariable);
  • 这当然是一个有效的解决方案,但我正在寻找一种方法来做到这一点,而无需引入一次性功能(这也打破了从上到下的阅读顺序)。
  • 您可以轻松写final int x; { switch (capturedVariable) { case 1: x=42; break; case 2: x=84; break; default: x=66; } }。它比你建议的语法短……

标签: java lambda anonymous-inner-class


【解决方案1】:

我看不出 Java 8 在这里有什么意义,你可以在多个地方分配一个 final 变量,只要你总是分配它并且只分配一次,例如这是合法的 Java 代码(假设 blah 是有效的布尔值):

final int test;
if (blah) {
  test = 1;
} else {
  test = 2;
}

只要编译器能够确定性地证明您总是将变量初始化一次且仅一次,表达式可以随心所欲地复杂化。 (例如循环会使其失败)。

【讨论】:

  • 谢谢!我的任务是在工作中编写 Java,但几十年来我没有使用过这种语言。来自 C++ 背景,我期待 final local 变量必须在声明时初始化,就像 C++ 中的 const 变量一样,但我猜不是 :) 谢谢你的回答.
  • 我不知道为什么我读到这个选项不在桌面上的问题(我认为是我,而不是问题)。如果不是(不考虑),这是显而易见的最佳方式。
  • @T.J.Crowder 这个问题可以用多种不同的方式阅读,所以我认为我们应该确保涵盖最简单的选项:D
  • @FrançoisBeaune Java 还具有“有效最终”的概念,您可能会觉得阅读起来很有趣。
【解决方案2】:

看起来有点矫枉过正,但你可以使用Supplier

final int x = new Supplier<Integer>() {
    public Integer get() {
        // Complexity here
        return result;
    }
}.get();

我确定是我的 Java-fu 太弱了 (我猜不是),但我能让 lambda 版本正常工作的唯一方法是拥有一个可重用的call 某处的实用函数:

class Utils {
    public static <T> T call(Supplier<T> x) {
        return x.get();
    }
}

...然后:

final int x = Utils.call(() -> {
    // Complexity here
    return result;
});

Matthias 在评论中指出(由Aominè 完善),您可以避免该中间功能,但它并不比上面的第一个解决方案更漂亮:

final int x = ((Supplier<Integer>) () -> {
    // Complexity here
    return result;
}).get();

...但至少它不需要生成类。

【讨论】:

  • 这个的 lambda 版本看起来并不好 final Integer a = ((Supplier)(() -> { return 1; })).get();
  • @Matthias:谢谢。我真的希望有比上面的 call 函数更整洁的方法。
  • 感谢 T.J.Crowder 和 @Matthias,至少您的回答显示了这是如何使用 lambdas 完成的,并且在 Java 中没有很好的解决这个问题的方法。
  • 有很多不错的解决方案,只是你不喜欢它们。这使得整个问题基于意见,如果不是,答案都将是变化的,因此相同的方法并且都会被赞成。
【解决方案3】:

你可以创建你自己的接口一个 create init 方法,它接受一个 init 并返回另一个 int 例如:

Init i = (x) -> {
    switch (x) {
        case 1:
            return 42;
        case 2:
            return 84;
        default:
            return 66;
    }
};
final int x = i.init(1);

...

interface Init {
    int init(int x);
}

【讨论】:

  • 对这次快速否决投票有何解释?
  • 这对于未经训练的人来说可能看起来不像是有效的代码。或者有人对你不能内联 lambda 感到失望。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 1970-01-01
  • 2016-02-12
  • 2013-05-28
  • 1970-01-01
相关资源
最近更新 更多