说我们有以下两种方法:
public static <T> T genericReturn() { /*...*/ }
public static String stringReturn() { /*...*/ }
在调用任何方法时,无论是否有任何要求,您都可以提供类型见证人:
String s;
s = Internet.<String>genericReturn(); //Type witness used in return type, returns a String
s = Internet.<Integer>stringReturn(); //Type witness ignored, returns a String
但是,除非在无法推断出类型的情况下(通常表明存在更大的问题),否则我在Java中根本看不到任何实际用途。另外,当不适当使用它时将其简单忽略的事实似乎违反直觉。那么,在Java中完全有什么意义呢?
从JLS§15.2.12.1开始:
- 如果方法调用包括显式类型参数,并且成员是泛型方法,则类型参数的数量等于方法的类型参数的数量。
此子句暗示非泛型方法可能潜在地适用于提供显式类型参数的调用。确实,这可能是适用的。在这种情况下,类型参数将被简单地忽略。
其次是理由
该规则源于兼容性和可替代性原则。由于接口或超类的生成可以独立于其子类型,因此我们可以用非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型实参的调用。否则,该亚型将无法替代其生成的超型。
按照这一推理,让我们构造一个示例。假设在Java 1.4中,JDK有一个类
public class Foo
{
/** check obj, and return it */
public Object check(Object obj){ ... }
}
一些用户编写了一个专有类,该类扩展Foo
并覆盖了check
方法
public class MyFoo extends Foo
{
public Object check(Object obj){ ... }
}
当Java 1.5引入泛型时,Foo.check
泛化为
public <T> T check(T obj)
雄心勃勃的向后可比性目标要求MyFoo
仍在Java
1.5中进行编译而无需进行修改。并且MyFoo.check[Object->Object]
仍然是压倒性的方法Foo.check[T->T]
。
现在,根据上述理由,由于可以编译:
MyFoo myFoo = new MyFoo();
((Foo)myFoo).<String>check("");
这也必须编译:
myFoo.<String>check("");
即使MyFoo.check
不是通用的。
听起来像是舒展。但是,即使我们支持这种观点,解决方案仍然过于广泛和过分。JLS可能已经向上,以便将其拧紧myFoo.<String,String>check
和obj.<Blah>toString()
是非法的,因为类型参数参数数量不匹配。他们可能没有时间解决问题,所以他们只走了一条简单的路线。
假设我们有如下两种方法: 在调用任何方法时,无论是否有任何要求,都可以提供类型见证: 但是,我没有看到它在Java中有任何实际的用途,除非无法推断类型(这通常表明存在更大的问题)。此外,如果不恰当地使用它,它就会被忽略,这一事实似乎违反了直觉。那么,在Java中使用它有什么意义呢?
问题内容: 这是我的代码,但是我没有得到方法如何接受类型作为返回值。如何运作?谁能解释一下这种方法的工作原理? 提前致谢 :) 问题答案: 好的,所以首先要做的是: 这是一个不断扩大的原始类型转换,因此这是合法的。您可以: 但是您不能: 第二:它返回的根本不是ASCII码。Java执行Unicode。 碰巧的是,当创建Java时,Unicode仅定义了适合16位的代码点。因此,它被创建为2字节的无
问题内容: 为什么在Java 8中允许接口具有方法? 如下面的代码所述,它可以正常工作并正确产生输出。 目前它的行为就像一个类,我已经用main方法执行了。 我们为什么需要这个? 问题答案: 从Java 8开始,接口中允许使用静态方法。 main()是静态方法。 因此,在接口中允许main()。 我们 不需要 它,因为以前不允许这样做,但是我们幸存了下来。但是,根据定义,由于静态方法不是绑定到类的
为什么我们不能降低能见度,但可以提高能见度? 此外,我需要实现模板模式,其中可见的公共方法只能是基类。
我在教条文档中读到了对我来说意义不大的以下内容: 使用选项时,假设实体是私有的,不会被其他实体重用。
问题内容: 使用“抽象方法”有什么意义?抽象类不能实例化,但是抽象方法呢?他们只是在这里说“您必须实现我”,如果我们忘记了它们,编译器会抛出错误? 这还意味着其他吗?我还阅读了有关“我们不必重写相同的代码”的内容,但是在抽象类中,我们仅“声明”了抽象方法,因此我们将不得不在子类中重写代码。 您能帮我多了解一点吗?我检查了有关“抽象类/方法”的其他主题,但没有找到答案。 问题答案: 除了提醒您必须实