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

发布于 2022-09-06 10:35:38 字数 374 浏览 16 评论 0

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()就成了死循环了啊,是我理解的不对吗?正确的转换是什么,请大家多多指教

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

久伴你 2022-09-13 10:35:38

首先给出我认为的正确写法吧(我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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文