我在同一个包test
中创建了类似下面的类。它只是为了测试java是否真的允许它。确实如此,但问题就出现了。
package test;
public class E {
}
package test;
public class T {
}
package test;
import test.E;
import test.T;
public class K<E, T> {
E e;
T t;
public K(E e, T t) {
this.e = e;
this.t = t;
}
public static void main(String[] args) {
K k = new K<E, T>(new E(), new T());
}
}
上面的代码给出了多个编译问题
Multiple markers at this line
- Cannot make a static reference to the non-static type E
- Cannot make a static reference to the non-static type T
- Cannot make a static reference to the non-static type T
- Cannot make a static reference to the non-static type E
- K is a raw type. References to generic type K<E,T> should be
parameterized
它清楚地表明,对于T,编译器在E和E类之间是混淆的。
因此,解决方法是使用包定义它的真实类型。
K k = new K<test.E, test.T>(new test.E(), new test.T());
现在,如果所有这些类都在default package
中,则无法解决此编译问题。
所以问题是java应该允许在default package
?
答案 0 :(得分:3)
它清楚地表明,对于T,编译器在E和E类之间是混淆的。
我认为你错了。我认为,如果您仔细阅读JLS的相关部分(我稍后会查看),您会发现它们清楚地说明E
和T
应该在各种情况下解决的问题。如果编译器得到错误的分辨率,我会非常惊讶;即没有实施JLS。
实际上,编写代码的人心中存在困惑......
这里的问题是关于什么优先于你(和典型的程序员)所期望的东西的规则。但他们就像是有充分理由的那样。
通常情况下这没关系,但是如果你忽略了普通的Java命名约定并为类使用单字母名称,那么你可能会被烧毁。
所以问题是java应该允许在默认包中声明这样的类吗?
或者,“你”是否应该忽略Java类命名约定?
坦率地说,如果程序员忽略了样式指南/建议,那么程序员可以通过很多方式来伤害自己。但是如果你试图过多地保护程序员,你实际上是因为无法实现你需要来推送信封的东西而伤害他/她。最好的政策是(IMO)不要将程序员视为儿童。如果他们真的想和锋利的刀子玩耍......那就让他们吧。
答案 1 :(得分:2)
这是一项非常好的研究。
但是,你仍然可以创建一个名为String
的类,Java从不抱怨使用相同的类名。要区分是否使用String类(或)Java提供的String类,需要附加包(全名)。
正如Matt Ball所说,不应该使用默认包。
向后兼容性可能是通用类型未定义为“保留字”
的另一个原因是否允许相同的类名(或),我认为这是包的用途。只要有办法区分我们指的是哪个类,我认为允许同名是完全没问题的。
答案 2 :(得分:2)
如果你愿意,你可能会感到非常困惑。我不确定编译器是否会阻止您编写令人困惑的代码,但我认为编译器应该尝试清除其错误消息。
public class T<T> {
public T() {
}
public static <T> T T() {
T T = null;
return T; // which T is this?
}
}
答案 3 :(得分:0)
考虑到你可以写
public class String<Object>{}
取消与您命名类型参数的名称相同的类或禁止您将名称类型参数命名为任何现有类的类将是疯狂的(具有冲突名称的类可以来自将来创建的另一个jar,因此任何类型参数的名称都可以是与某个类的名称相同,反之亦然)