java8 Predicate接口中的negate()默认方法用java7如何实现?

negate()源码为:

default Predicate<T> negate() {

    return (t) -> !test(t);

}

我理解的可以转换为:

default Predicate<T> negate() {

    return new Predicate<T>() {

        public boolean test(T t) {

            !test(t);

        }

    };

}

但是这样转化的话test()就成了死循环了啊,是我理解的不对吗?正确的转换是什么,请大家多多指教

阅读 4.7k
1 个回答

首先给出我认为的正确写法吧(我copy了Predicat类,然后改名为PredicateExt进行重写)

default PredicateExt<T> negate() {
        PredicateExt<T> predicate = this;
        PredicateExt<T> otherPredicate = new PredicateExt<T>() {
            @Override
            public boolean test(T t) {
                return !predicate.test(t);
            }
        };
        return otherPredicate;
    }

再来看看Java8中Predicate.negate到底表达的是什么意思

  1. Predicate肯定是一个类,(t) -> !test(t)这种lamdba语法也只是表示Predicate的一个对象而已
  2. default方法就是代表了Predicate对象的某个实例方法

因此结合以上两点,可以直接看出Predicate.negate代表Predicate的某个对象A执行时,根据A的执行结果再次创建了一个新Predicate的对象B
所以,要换种方式来表示Predicate.negate方法,肯定也要体现出A,B两个新旧对象,并且该方法的执行结果是根据A的执行结果体现出来的

再来说说题主为什么会死循环,虽然题主已经明显new了一个Predicate对象,这里体现了A,B两个新旧对象,但是后面的执行结果并没有体现出是根据A的执行结果来产生B的
主要在于里面的在重写B的test方法时,是再调用test方法的,只是前面加了一个!,所以显然这里调用的是B的Predicatetest方法,当然就是循环调用了,可别指望它能调用A的Predicate方法,因为你正在重写这个新Predicate的方法,这里的this指针,肯定是指向B的

鉴于此,既然在B里面重写方法时this指针是指向B的,那就在外面显示的把A的对象指示出来,然后再B中重写时,显示用的A的方法进行执行,这样就可以了,所以才有上面的写法

从运行的debug来看,以前的方式和现在重写的方式,在新的B对象中,都包含了以前的旧对象A的,所以是可行的

clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进