大小写超过类型(带返回值的开关)

时间:2018-07-07 14:24:57

标签: java switch-statement

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

现在,我想以一种在多种功能语言中使用的方式来声明case

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

也就是说,我要打开类型,还要将switch语句视为一个表达式(即它应该有一个结果)。

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

对于上述使用Java 8功能特性的问题,其格式可能为this answer

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

1 个答案:

答案 0 :(得分:3)

类似于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(如果有匹配项则为值,如果没有匹配项则为空),则可以相应地调整大小写功能:

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)
    }