【问题标题】:What does the dot operator `.` (before the generic parameter) mean?点运算符 `.`(在泛型参数之前)是什么意思?
【发布时间】:2015-01-25 19:28:39
【问题描述】:

我今天看到了这段代码:

    ImmutableMap<Class<? extends ClientCommand>, CommandProcessorInterface> immutableMap =
            ImmutableMap.<Class<? extends  ClientCommand>, CommandProcessorInterface>of(...

这个语法是什么意思?

ImmutableMap.&lt;Class ..

我知道泛型就在类名之后。没有?

有什么区别:

ImmutableMap&lt;Class.. 和 ImmutableMap.&lt;Class..

【问题讨论】:

  • 它是静态方法of的泛型参数,而不是类本身。

标签: java generics syntax guava


【解决方案1】:

这意味着您正在调用一个通用静态方法,在 ImmutableMap 类中称为 of。

这与您调用 static 方法几乎相同,嵌套在某个类中:

SomeClass.staticMethod();

对于您的方法定义了类型参数的情况,您可以显式提供泛型类型,方法如下:

SomeClass.<Type>genericStaticMethod();

回答你最后一个问题:

ImmutableMap&lt;Class...&gt; 和 ImmutableMap.&lt;Class... 有什么区别?

第一个通常在创建泛型类的实例时使用。它用于在类级别定义泛型类型,而第二个用于调用嵌套在某个类中的泛型静态方法。

【讨论】:

  • 您通常不需要提供它。请参阅docs。 fromArrayToCollection(sa, cs); // T inferred to be String
  • 它可能是从返回类型转换(或赋值)推导出来的,但并不总是可能的。我只是说“你需要提供泛型类型”它并不总是正确的
  • @user270349 我什至会说“你需要”这句话是完全错误的。
【解决方案2】:

它涉及一个静态方法ImmutableMap.of。这有自己的泛型类型参数。

class Test {

static <T> T f() { return null; }

void t() {
    String s = Test.f();                 // Inferred from LHS.
    String t = Test.<String>f();         // Not needed.
    int n = Test.<String>f().length();   // Needed.
}

在你的情况下,它似乎并不真正需要,但我如履薄冰,因为泛型类型推断在 Java 8 中变得更强大了。

【讨论】:

    【解决方案3】:

    泛型方法是使用任何泛型类型参数声明的方法。 请参阅文档here。方法的泛型类型不必与声明类的任何泛型类型参数相关。该类可能是通用的,也可能不是通用的。

    在调用泛型方法(静态或非静态)时,您可以指定泛型类型,但您通常不会看到它,因为它通常是自动检测的。您找到的语法就是指定它的语法。

    如果有这样声明的方法:

    <T> void fromArrayToCollection(T[] a, Collection<T> c) { ...
    

    你可以这样称呼它:

    Integer[] a = ...
    ArrayList<Integer> l = ...
    x.fromArrayToCollection(a, l);
    

    但如果你有这样的:

    <T> Collection<T> myMethod(int c) {
      return new ArrayList<T>(c);
    }
    

    那么您有两种方法可以向编译器阐明类型。您可以通过两种方式为其提供足够的信息。

    一个是在调用中指定类型:

    Object c = x.<Integer>myMethod(5);
    

    另一个是类型转换(通过分配给变量显式或隐式):

    Collection<Integer> c = x.myMethod(5);
    

    【讨论】:

    • Object c = & 显式/隐式是我的答案中缺少的。点赞
    【解决方案4】:

    泛型方法的完整调用类型是(如Generic Methods所说):

    // use Collections#emptyList as an example
    List<String> a = Collections.<String>emptyList();
    

    可以简化为:

    // use Collections#emptyList as an example
    List<String> a = Collections.emptyList();
    

    还有一个例子:

    List<String> a = ...;
    String s = a.<String>get(0);
    

    字母类型参数也可以简化为:

    String s = a.get(0);
    

    这叫Type Inference。

    查看 Guava ImmutableMap 的几个示例:

    // type parameter can be omitted
    ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>of("a", 1);
    

    可以简化为:

    ImmutableMap<String, Integer> map = ImmutableMap.of("a", 1);
    

    这是由目标类型推断的。

    但是对于这个:

    // type parameter can not be omitted
    ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder().build();
    

    这令人困惑。事实上,完整的格式是:

    // the latter type parameter can be omitted
    ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder().<String, Integer>build();
    

    有两个连续的泛型方法:builder & build。对于后一种方法,由于目标类型推断,可以省略类型参数。对于前一种方法,情况并非如此。它没有可以推断的目标类型,所以类型参数必须写在这里:

    ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder()...
    

    如果你真的想省略 builder 和 build 的类型参数,它们必须都有目标类型来推断:

    ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
    ImmutableMap<String, Integer> immutableMap = builder.build();
    

    【讨论】:

      猜你喜欢
      • 2012-04-19
      • 2012-06-07
      • 2012-07-15
      • 1970-01-01
      • 2013-05-07
      • 2015-04-05
      • 2015-09-18
      • 2017-03-29
      相关资源
      最近更新 更多