1.概述
本文作为一个用例(或者说是尝试),基于 Java 8 的语法在类和方法的层面实现模式匹配的效果。考虑到对象的创建和频繁入栈和出栈,在计算密集型的代码中请谨慎使用本文中的程序。
2.Java 12 及其他语言的模式匹配
首先看下 Java 12 中 switch 表达式的效果:
int i = 0;
String s = switch (i) {
case 1 -> "1";
case 2 -> {
System.out.println("is 2");
break "2";
}
default -> "3";
};
然后是kotliln的效果:
private fun test(foo: Any): String {
var result = when (foo) {
0 -> "Object equals"
3, 10 -> "Or"
in 11..20 -> "Range contains"
is Date -> "Class instance"
!in 4..30 -> "Range not contain"
else -> "Default"
}
return result
}
再是Scala的效果:
def matchObject(foo: Any): String = {
val result = foo match {
case 0 => "Object equals"
case i if i == 10 || i == 11 => "Expression"
case i: Int => s"Class instance holds $i"
case List(1, 2, _*) => "Match the last element of a list"
case Number(n) => s"Case class holds $n"
case t: {def length: Int} => "Class structure contains method length"
case _ => "Default"
}
result
}
3.本例实现的效果
下面上本例所实现的效果:
/* API1:有返回值的匹配 */
Object o = null;//1;//4;//"ksjdf";
String s1 = Cond.match(o)
.valueOf(1, i -> "is 1")
.valueOf(2, i -> "is 2")
.typeOf(String.class, s -> "is String")
.orElse(t -> "is else");
System.out.println(s1);
/* API1:无返回值的匹配 */
o = "string";//null;//"";//1;//2;
Cond.match(o)
.valueOf(2, i -> {
System.out.println("is 2");
})
.valueOf(null, n -> System.out.println("is null"))
.typeOf(String.class, s -> System.out.println("is String"))
.orElse(t -> System.out.println("is else"));
/* 没有匹配项的情况 */
System.out.println(Cond.match(8).orElse(i -> 9999).toString());
Cond.match(8).orElse((Consumer<Integer>) System.out::println);
/* API2:无返回值的匹配 */
Cond.match(8,
typeOf(String.class, t -> {
System.out.println("is string : " + t);
}),
valueOf(null, (Object obj) -> System.out.println("is null : " + obj)),
valueOf(4, (Integer t) -> System.out.println("is number " + t)),
orElse((Object i) -> System.out.println("or else" + i)));
/* API2:有返回值的匹配 */
String s2 = match(null,
typeOf(String.class, s -> "is String"),
valueOf(null, j -> "is null"),
valueOf(1, i -> "is number " + i),
orElse(obj -> "is else : " + obj))
.orElse("opt else");
System.out.println("------- " + s2);
4.代码
实现代码如下(注意,本类中包含两套API,根据喜好自行删减; 之前加了注释,发现写得可能会误导,于是就删掉了; 另外省去空指针判断,匹配的值支持null,对应操作不支持):
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class Cond {
public static <T> BaseCond<T> match(T t) {
return new BaseCond<>(t);
}
@SafeVarargs
public static <T> void match(T t, ProcCondition<T>... conditions) {
for (ProcCondition<T> condition : conditions) {
if (condition.predicate.test(t)) {
condition.consumer.accept(t);
return;
}
}
}
@SafeVarargs
public static <T, R> Optional<R> match(T t, FunCondition<T, R>... conditions) {
for (FunCondition<? super T, ? extends R> condition : conditions) {
if (condition.predicate.test(t)) {
return Optional.ofNullable(condition.function.apply(t));
}
}
return Optional.empty();
}
public static class ProcCondition<T> {
final Predicate<? super T> predicate;
final Consumer<? super T> consumer;
ProcCondition(Predicate<? super T> predicate, Consumer<? super T> consumer) {
this.predicate = predicate;
this.consumer = consumer;
}
}
public static class FunCondition<T, R> {
final Predicate<? super T> predicate;
final Function<? super T, ? extends R> function;
FunCondition(Predicate<? super T> predicate, Function<? super T, ? extends R> function) {
this.predicate = predicate;
this.function = function;
}
}
public static <T, K> ProcCondition<T> typeOf(Class<K> tClass, Consumer<? super K> consumer) {
return new ProcCondition<>(tClass::isInstance, t -> consumer.accept((K) t));
}
public static <T, K> ProcCondition<T> valueOf(K value, Consumer<? super K> consumer) {
return new ProcCondition<>(t -> Objects.equals(t, value), t -> consumer.accept((K) t));
}
public static <T, K> ProcCondition<T> orElse(Consumer<? super K> consumer) {
return new ProcCondition<>(t -> true, t -> consumer.accept((K) t));
}
public static <T, K, R> FunCondition<T, R> typeOf(Class<K> tClass, Function<? super K, ? extends R> function) {
return new FunCondition<>(tClass::isInstance, t -> function.apply((K) t));
}
public static <T, R, K> FunCondition<T, R> valueOf(K value, Function<? super K, ? extends R> function) {
return new FunCondition<>(t -> Objects.equals(t, value), t -> function.apply((K) t));
}
public static <T, K, R> FunCondition<T, R> orElse(Function<? super K, ? extends R> function) {
return new FunCondition<>(t -> true, t -> function.apply((K) t));
}
public interface ReturnCond<T, R> {
<K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f);
<K> ReturnCond<T, R> valueOf(K value, Function<? super K, R> f);
R orElse(Function<? super T, R> f);
}
public interface VoidCond<T> {
<K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f);
<K> VoidCond<T> valueOf(K value, Consumer<? super K> f);
void orElse(Consumer<? super T> f);
}
private static class EmptyReturnCond<T, R> implements ReturnCond<T, R> {
private final R object;
EmptyReturnCond(R object) {
this.object = object;
}
@Override
public <K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
return this;
}
@Override
public <K> ReturnCond<T, R> valueOf(K value, Function<? super K, R> f) {
return this;
}
@Override
public R orElse(Function<? super T, R> f) {
return object;
}
}
private static class ReturnCondImpl<T, R> implements ReturnCond<T, R> {
private final T object;
ReturnCondImpl(T object) {
this.object = object;
}
@Override
public <K> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
return kClass.isInstance(object)
? new EmptyReturnCond<>(f.apply((K) object))
: this;
}
@Override
public <K> ReturnCond<T, R> valueOf(K value, Function<? super K, R> f) {
return Objects.equals(value, object)
? new EmptyReturnCond<>(f.apply((K) object))
: this;
}
@Override
public R orElse(Function<? super T, R> f) {
return f.apply(object);
}
}
private static class EmptyVoidCond<T> implements VoidCond<T> {
@Override
public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
return this;
}
@Override
public <K> VoidCond<T> valueOf(K value, Consumer<? super K> f) {
return this;
}
@Override
public void orElse(Consumer<? super T> f) {
}
}
private static class VoidCondImpl<T> implements VoidCond<T> {
private final T object;
public VoidCondImpl(T object) {
this.object = object;
}
@Override
public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
if (kClass.isInstance(object)) {
f.accept((K) object);
return new EmptyVoidCond<>();
} else {
return this;
}
}
@Override
public <K> VoidCond<T> valueOf(K value, Consumer<? super K> f) {
if (Objects.equals(value, object)) {
f.accept((K) object);
return new EmptyVoidCond<>();
} else {
return this;
}
}
@Override
public void orElse(Consumer<? super T> f) {
f.accept(object);
}
}
public static class BaseCond<T> {
private final T object;
BaseCond(T object) {
this.object = object;
}
public <K, R> ReturnCond<T, R> typeOf(Class<K> kClass, Function<? super K, R> f) {
return kClass.isInstance(object)
? new EmptyReturnCond<>(f.apply((K) object))
: new ReturnCondImpl<>(object);
}
public <K> VoidCond<T> typeOf(Class<K> kClass, Consumer<? super K> f) {
if (kClass.isInstance(object)) {
f.accept((K) object);
return new EmptyVoidCond<>();
} else {
return new VoidCondImpl<>(object);
}
}
public <K, R> ReturnCond<T, R> valueOf(K value, Function<? super K, R> f) {
return Objects.equals(value, object)
? new EmptyReturnCond<>(f.apply((K) object))
: new ReturnCondImpl<>(object);
}
public <K> VoidCond<T> valueOf(K value, Consumer<? super K> f) {
if (Objects.equals(value, object)) {
f.accept((K) object);
return new EmptyVoidCond<>();
} else {
return new VoidCondImpl<>(object);
}
}
public void orElse(Consumer<? super T> f) {
f.accept(object);
}
public <R> R orElse(Function<? super T, R> f) {
return f.apply(object);
}
}
}
5.总结
示例的 API1 中到达匹配条件后,后续的调用都是无效调用,匹配条件越多无效调用也越多,但是 API1 的代码更美观且使用起来更顺畅。
Android 开发中如果需要使用,則需要复制 Java 8 的个别函数式接口(Consumer,Function,Predicate),自己实现 Java 7 的 Objects 的 equals 方法,重新实现 Java 8 的 Optional 类并去掉个别 Android API 26 才能用的接口方法。