Java Consumer示例理解困难

3

我不理解一个关于Java Consumer接口的例子中方法声明的意思。我在在线书籍(清单11.7)中找到了这个例子。

class Consumers {

    public static <T> Consumer<T> measuringConsumer( Consumer<T> block){
        return t -> {
            long start = System.nanoTime();
            block.accept( t );
            long duration = System.nanoTime() - start;
            Logger.getAnonymousLogger().info("Execution time (ns): " + duration);
        };
    }
}

在这个声明中,<T> Consumer<T>代表什么?难道不应该只有Consumer<T>而没有第一个<T>吗?

5
如果您移除第一个 <T>,会发生什么? - Oliver Charlesworth
我相信你可以移除第一个<T>。Consumer<T>是对Consumer类型T的定义,它必须与accept()方法和measuringConsumer()方法中作为输入的类型相同。 - Dina Bogdan
2
@DinaBogdan 嗯,不行,你不能移除<T> - 我的意思是,从技术上讲,你可以移除它,但那样就无法编译。 - luk2302
measuringConsumer 是一个通用方法,如果您对此不熟悉,请阅读以下内容:https://docs.oracle.com/javase/tutorial/extra/generics/methods.html。 - Oleg
2个回答

4

第一个 <T> 用于定义 Consumer 将接受的对象类型的边界。

在这种特定情况下,该方法似乎接受从 java.lang.Object 派生的任何内容,但您可以通过执行以下操作进一步约束可接受的类型:

public static <T extends Foo> Consumer<T> measuringConsumer(Consumer<T> block) { ... }

请参考文档了解更多示例。

2
第一个<T>是一个通用类型变量。它表示measuringConsumer方法是通用的,即它接受和/或返回通用类型。
在这种情况下,该方法接受一个类型为Consumer<T>(一个通用类型)的参数,并返回一个类型为Consumer<T>的值,该值也是通用的。最重要的是,返回值的通用类型与参数的通用类型相同。这意味着,如果您将Consumer<Integer>作为参数传递,此方法将返回一个Consumer<Integer>而不是Consumer<String>,因为T类型变量对于参数和返回值都是相同的。
请注意,类型变量T没有边界。这意味着T可以是任何东西,例如,您可以将任何东西的Consumer作为参数传递,例如Consumer<Integer>Consumer<Double>Consumer<String>Consumer<YourOwnClass>等。
如果T被限制,即<T extends Number>,那么Consumer<T>只能是Consumer<Integer>Consumer<Long>Consumer<BigDecimal>Consumer<Double>等,实际上是任何Number的后代的Consumer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接