当前位置: 首页 > 知识库问答 >
问题:

强制转换Java功能接口

黄君博
2023-03-14

和往常一样,我在浏览JDK8源代码时发现了非常有趣的代码:

@Override
default void forEachRemaining(Consumer<? super Integer> action) {
    if (action instanceof IntConsumer) {
        forEachRemaining((IntConsumer) action);
    } 
}

问题是:如何consumer<?super integer>可能是IntConsumer的实例?因为它们处于不同的层级。

我做了类似的代码片段来测试转换:

public class InterfaceExample {
    public static void main(String[] args) {
        IntConsumer intConsumer = i -> { };
        Consumer<Integer> a = (Consumer<Integer>) intConsumer;

        a.accept(123);
    }
}
Exception in thread "main" 
    java.lang.ClassCastException: 
       com.example.InterfaceExample$$Lambda$1/764977973 
     cannot be cast to 
       java.util.function.Consumer

共有1个答案

佘辰龙
2023-03-14

让我们看看下面的代码,然后你就能明白为什么了?

class IntegerConsumer implements Consumer<Integer>, IntConsumer {
   ...
}

任何类都可以实现多个接口,一个是consumer 可能实现另一个是intconsumer。当我们想要将intconsumer适配到consumer 并保存其原始类型(intconsumer)时,有时会发生这种情况,那么代码如下所示:

class IntConsumerAdapter implements Consumer<Integer>, IntConsumer {

    @Override
    public void accept(Integer value) {
        accept(value.intValue());
    }

    @Override
    public void accept(int value) {
        // todo
    }
}

注意:这是类适配器设计模式的用法。

Consumer<? extends Integer> consumer1 = new IntConsumerAdapter();
IntConsumer consumer2 = new IntConsumerAdapter();
189  interface OfInt extends Sink<Integer>, IntConsumer {
190 @Override
191 void accept(int value);
193 @Override
194 default void accept(Integer i) {
195 if (Tripwire.ENABLED)
196 Tripwire.trip(getClass(), "{0} calling Sink.OfInt.accept(Integer)");
197 accept(i.intValue());
198 }
199 }

我发现为什么需要将使用者 强制转换为intconsumer如果将使用者传递为intconsumer

一个原因是,当我们使用使用者来接受int时,编译器需要将其自动装箱为integer。在accept(Integer)方法中,您需要手动将Integer解箱为int。换句话说,每个accept(Integer)执行2个额外的装箱/取消装箱操作。为了提高算法的性能,在算法库中做了一些特殊的检查。

另一个原因是重用一段代码。OFint#ForeachRefling(Consumer)的主体是应用适配器设计模式重用OFint#ForeachRenaming(IntConsumer)的一个很好的例子。

default void forEachRemaining(Consumer<? super Integer> action) {
    if (action instanceof IntConsumer) {
    //   action's implementation is an example of Class Adapter Design Pattern
    //                                   |
        forEachRemaining((IntConsumer) action);
    }
    else {
    //  method reference expression is an example of Object Adapter Design Pattern
    //                                        |
        forEachRemaining((IntConsumer) action::accept);
    }
}
 类似资料:
  • 问题内容: 很难找到该主题的任何线索。我只能找到有关将一个功能接口转换为另一个功能接口的问题,以及一些有关Java中类型转换的文章。不是我要找的东西。 这个问题是关于转换的,而我想相反地转换为任何功能接口,例如to 。 我发现的方法是围绕该方法创建一个lambda适配器: 但是我想避免写 赞成更简单的事情,例如 ➥因此,有没有办法将旧的Java 1.1反射库映射到较新的Java 8功能接口,还是我

  • copy(文件,文件)只是复制一个文件。 java.lang.ClassCastException:sun.util.ResourceBundleEnumeration不能在java.util.Properties.Store0(未知源)~[?:1.7.0_21]在java.util.Properties.Store(未知源)~[?:1.7.0_21]在Bammerbom.UltimateCore

  • 我希望将一个< code>int数组转换为一个< code>double数组。 所以,当我有 我想使用,比如说把它作为参数传递给一个方法。 最好的方法是什么? 演员阵容 不工作。 我可以迭代通过: 有没有更好的方法来做到这一点? <代码>系统。arraycopy不起作用——不适用于两种不同基元类型的数组。 注意:在Java和其他一些讨论中,我们看到了将对象转换为数组。 蒂亚。

  • 问题内容: 我有。我想使用获得最大结果。这是我的代码: 这是我的: 现在我得到了。怎么了? 问题答案: 您的错误可能在以下行中: 其中query.list()返回BigInteger列表而不是Long列表。尝试将其更改为。

  • 我不是一个设计师,但当我得到这个项目,我不能打开特别的一些屏幕,我认为他们是屏幕,我们只重用一些布局已经创建。不管怎么说谁能帮帮我吗?@override public void onBindViewHolder(@nonnull final ProductsAdapter.ViewHolder holder,final int position){String imageUrl=ProductsL