我们看下面的代码,你就明白为什么了吗?
class IntegerConsumer implements Consumer<Integer>, IntConsumer {
...
}
任何类都可以实现多接口,其中之一是Consumer<Integer>
也许实现另一个是IntConsumer
。有时当我们想要适应时就会发生IntConsumer
to Consumer<Integer>
并保存其原始类型(IntConsumer
),那么代码如下所示:
class IntConsumerAdapter implements Consumer<Integer>, IntConsumer {
@Override
public void accept(Integer value) {
accept(value.intValue());
}
@Override
public void accept(int value) {
// todo
}
}
Note: 这是使用类适配器设计模式 https://stackoverflow.com/questions/9978477/difference-between-object-adapter-pattern-and-class-adapter-pattern.
THEN您可以使用IntConsumerAdapter
两者都作为Consumer<Integer>
and IntConsumer
, 例如:
Consumer<? extends Integer> consumer1 = new IntConsumerAdapter();
IntConsumer consumer2 = new IntConsumerAdapter();
Sink.OfInt
是一个具体用法类适配器设计模式 https://stackoverflow.com/questions/9978477/difference-between-object-adapter-pattern-and-class-adapter-pattern在jdk-8中。的缺点Sink.OfInt#accept(Integer)
显然 JVM 会抛出一个NullPointerException
当它接受一个null
值,所以这就是为什么Sink
is package可见的。
189 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#189 interface OfInt extends Sink http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#Sink<Integer http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Integer.java#Integer>, IntConsumer http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/function/IntConsumer.java#IntConsumer {
190 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#190 @Override http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Override.java#Override
191 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#191 void accept(int value);
193 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#193 @Override http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Override.java#Override
194 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#194 default void accept(Integer http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Integer.java#Integer i) {
195 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#195 if (Tripwire.ENABLED)
196 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#196 Tripwire.trip http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Tripwire.java#Tripwire.trip%28java.lang.Class%2Cjava.lang.String%29(getClass http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Object.java#Object.getClass%28%29(), "{0} calling Sink.OfInt.accept(Integer)");
197 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#197 accept http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#Sink.OfInt.accept%28int%29(i.intValue http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/lang/Integer.java#Integer.intValue%28%29());
198 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#198 }
199 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/stream/Sink.java#199 }
我发现为什么需要投射Consumer<Integer>
to an IntConsumer
如果通过像这样的消费者IntConsumerAdapter
?
原因之一是当我们使用Consumer
接受一个int
编译器需要将其自动装箱到Integer
。并且在方法中accept(Integer)
你需要拆箱Integer
to an int
手动。
换句话说,每个accept(Integer)
执行 2 个额外的装箱/拆箱操作。它需要提高性能,所以在算法库中做了一些特殊的检查。
另一个原因是重用一段代码。的身体OfInt#forEachRemaining(消费者) https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.OfInt.html#forEachRemaining-java.util.function.Consumer-是一个很好的应用例子适配器设计模式 https://stackoverflow.com/questions/9978477/difference-between-object-adapter-pattern-and-class-adapter-pattern用于重复使用OfInt#forEachRenaming(IntConsumer) http://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.OfInt.html#forEachRemaining-java.util.function.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);
}
}