为什么不能在方法名称后面放置类型参数?

时间:2014-11-19 17:29:52

标签: java generics

如果确实如此,问题是:

如果可以在方法名称后放置类型参数,可能会出现什么问题?


E.g:

import com.google.common.base.Predicate;
static import com.google.common.base.Predicates.alwaysTrue;

Predicate<SomeType> p = alwaysTrue<SomeType>();

更新

我知道你可以用这种方式传递类型参数:

Predicate<SomeType> p = Predicates.<SomeType>alwaysTrue();

2 个答案:

答案 0 :(得分:1)

如果问题是Java设计师为什么设计这样的语法:我最好的猜测是因为方法名称有自己的命名空间与变量/字段名称分开,这意味着它是合法的使方法名称与变量或字段具有相同的名称,并且上下文确定正在使用哪个名称。因此:

x = myName;

查找名为myName的变量或字段,而

x = myName(arg);

查找名为myName的方法。左(是告诉编译器查找方法而不是变量的东西。这样,即使myName具有作为变量和方法的合法含义,编译器也可以接受这两个语句。

如果语法是类型参数在方法名称之后:

x = myName<T>(arg);

编译器会非常困惑。此表达式是变量myName,后跟<(小于)运算符,后跟一个名为T的变量,后跟一个>运算符,后跟一个在括号中表达?或者是带有类型参数的方法调用?可能是因为没有两种可能的解释(因为<>在Java中的boolean参数上不合法),但是设计师认为它是合理的会对编译器造成太大的负担,或者在所有情况下正确设计语言规则的负担太大。

P.S。只是为了让您了解可能导致什么样的头痛:第一项任务在Java中是合法的:

// instance members
int name1, name2, name3;
public <T> boolean name2(int argument) { ... }

// some statement later on in some method
boolean x = name1<name2>>(name3);        // legal
boolean x = name1<name2<name4>>(name3);  // would be legal syntax if type parameters appeared
                                         // after method names

请注意,解释>>的规则很特殊 - 它在类型上下文中被视为两个单独的>个字符(因此您可以ArrayList<ArrayList<Integer>> ),但作为换班操作员。我不想成为编写编译器代码或语言规则的人,以确保两者都得到正确处理。

答案 1 :(得分:1)

我在这里看到两个不同的问题:

为什么需要参数化方法的类或对象?

public class Test {
    private static <T> void staticMethod() {}
    private <T> void method() {}
    public Test() {
        method();                // Works!
        <Integer>method();       // Doesn't work!
        this.<Integer>method();  // Works again!
    }

    public static void main(String[] args) {
        staticMethod();                // Works!
        <Integer>staticMethod();      // Doesn't work
        Test.<Integer>staticMethod(); // Works again!
    }
}

不幸的是我无法给出答案......

第二个问题:为什么方法类型参数放在方法之前(而不是类参数,类之后)?

这里我确实有预感 - 其中一个问题是通用构造函数。通用构造函数可以像任何其他方法一样具有类型参数,并且这些参数可以独立于类类型参数:

public class Class<T> {
    public <V>Class(V arg) {

    }
    public static void main(String[] args) {
        new <Number>Class<Object>(0);
    }
}

这是有效的语法,第一个类型参数是方法参数,第二个是类型参数。

需要有一种区分这些机制的机制,并且记住 - 由于向后兼容性,开发人员可能会忽略这两种机制!

我想不出任何其他方法,而不是将它们放在构造函数调用的不同方面。

想象有一个类似的边缘情况模糊不清,参数化的方法在没有对象或类的情况下调用,但我现在无法想到。