java - 大小写类型(带返回值的开关)

标签 java switch-statement

问题Switch over type in java考虑如何根据对象的类型打开要执行的代码。

现在我想要一个 case 语句,就像在许多函数式语言中使用的那样:

r = case x of
   String s -> s
   Int i -> toString i

也就是我要switch类型,也把switch语句当成一个表达式(即应该有结果)。

就像在 switch 中一样,应该允许多个 case 匹配,但评估将从头到尾检查并返回第一个匹配的值(如果没有匹配则返回 null)。

可以是this answer的样式对于上述使用 Java 8 功能特性的问题:

switchType(x,
    caze(String.class, v -> print("String: " + v),
    caze(Integer.class, v -> print("Int: " + v));

最佳答案

类似于this answer中的改编通过仅执行第一个匹配项来调整上述解决方案,可以添加一个额外的类型参数 R对于返回类型并使用 Function<T,R>而不是 Predicate<T> :

  public static <R> R caseType(Object obj, Function<Object, Optional<R>>... functions) {
        for (Function<Object, Optional<R>> f : functions) {
            Optional<R> res = f.apply(obj);
            if (res.isPresent()) {
                return res.get();
            }
        }
        return null; // Default case (no match)
    }

    public static <T, R> Function<Object, Optional<R>> of(Class<T> cls, Function<T, R> f) {
        // Wrap the function with a type check
        return obj -> {
            if (cls.isInstance(obj)) {
                return Optional.of(f.apply((T) obj)); // As we must return a function taking an Object, we have to convert here
            } else {
                return Optional.empty();
            }
        };
    }

以下示例演示了用法和行为:

    String s = "Hello World";
    Integer i = 5;
    Double d = 1.0 / 3;

    Object x = s;
    Object y = i;
    Object z = d;

    String res1 = caseType(x,
            of(String.class, v -> v.substring(0, 5)),
            of(Integer.class, v -> String.format("%d", v)),
            of(Double.class, v -> String.format("%1.4f", v)));

    String res2 = caseType(y,
            of(String.class, v -> v.substring(0, 5)),
            of(Integer.class, v -> String.format("%d", v)),
            of(Double.class, v -> String.format("%1.4f", v)));

    String res3 = caseType(z,
            of(String.class, v -> v.substring(0, 5)),
            of(Integer.class, v -> String.format("%d", v)),
            of(Double.class, v -> String.format("%1.4f", v)));

    String firstMatch = caseType(x,
            of(String.class, v -> "first case"),
            of(String.class, v -> "second case"));

    String resNull = caseType(z,
            of(String.class, v -> v.substring(0, 5)),
            of(Integer.class, v -> String.format("%d", v)));

    String resDefault = caseType(z,
            of(String.class, v -> v.substring(0, 5)),
            of(Integer.class, v -> String.format("%d", v)),
            of(Object.class, v -> "unknown"));

    String resSubtype1 = caseType(y,
            of(Number.class, v -> String.format("%1.4f", v.doubleValue())),
            of(Object.class, v -> "unknown"));

    String resSubtype2 = caseType(z,
            of(Number.class, v -> String.format("%1.4f", v.doubleValue())),
            of(Object.class, v -> "unknown"));

    System.out.println("res1:        " + res1);
    System.out.println("res2:        " + res2);
    System.out.println("res3:        " + res3);
    System.out.println("firstMatch:  " + firstMatch);
    System.out.println("resNull:     " + resNull);
    System.out.println("resDefault:  " + resDefault);
    System.out.println("resSubtype1: " + resSubtype1);
    System.out.println("resSubtype2: " + resSubtype2);

输出:

res1:        Hello
res2:        5
res3:        0.3333
firstMatch:  first case
resNull:     null
resDefault:  unknown
resSubtype1: 5.0000
resSubtype2: 0.3333

如果希望结果是 Optional (如果有匹配则有一个值,如果没有匹配则为空)可以相应地调整 case 函数:

private static <R> Optional<R> caseTypeNonNull(Object obj, Function<Object, Optional<R>>... functions) {
        for (Function<Object, Optional<R>> f : functions) {
            Optional<R> res = f.apply(obj);
            if (res.isPresent()) {
                return Optional.of(res.get());
            }
        }
        return Optional.empty(); // Default case (no match)
    }

关于java - 大小写类型(带返回值的开关),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51224109/

相关文章:

java - 开关盒顺序会影响速度吗?

c++ - 在 char* 上切换大小写

java - 使用 BIRT 和嵌入式 Tomcat 报告

java - 如何从 firebase 中检索特定的数据列表?

java - 改造不良请求和 RecyclerView : No adapter attached; skipping layout

c - C 中枚举与 switch-case 的使用

java - 将方 block 添加到动画中

java - 在调用 Future.get() 之前中断线程

javascript - 使用 if 语句并有多个成功案例

java - 开关声明(价格以 5 美分为增量)