Java 在不使用泛型的类中的方法中,泛型的用途是什么?
我在很多API中看到过这种代码方法,ant总是想知道它的真正目的是什么。 如果我们有一个带有简单签名的类,我们可以这样说:Java 在不使用泛型的类中的方法中,泛型的用途是什么?,java,generics,Java,Generics,我在很多API中看到过这种代码方法,ant总是想知道它的真正目的是什么。 如果我们有一个带有简单签名的类,我们可以这样说: public class MyClass {...} 在这个类中,我们有一个Object类型的变量,这个变量有一个getter和一个setter。 区别在于getter方法使用泛型。所以我们班看起来是这样的: public class MyClass { private Object myVariable; public void setMyVariab
public class MyClass {...}
在这个类中,我们有一个Object类型的变量,这个变量有一个getter和一个setter。
区别在于getter方法使用泛型。所以我们班看起来是这样的:
public class MyClass {
private Object myVariable;
public void setMyVariable(Object myVariable) {
this.myVariable = myVariable;
}
public <T> T getMyVariable() {
return (T)myVariable;
}
}
myClassInstance.setMyVariable(new Vehicle());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
myClassInstance.setMyVariable(new Airplane());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
因此,当我们调用getter方法时,我们可以这样做:
public class MyClass {
private Object myVariable;
public void setMyVariable(Object myVariable) {
this.myVariable = myVariable;
}
public <T> T getMyVariable() {
return (T)myVariable;
}
}
myClassInstance.setMyVariable(new Vehicle());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
myClassInstance.setMyVariable(new Airplane());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
这确实很好,因为在设置变量时,我们创建了一个相同类型的实例。
但我们也可以这样做:
public class MyClass {
private Object myVariable;
public void setMyVariable(Object myVariable) {
this.myVariable = myVariable;
}
public <T> T getMyVariable() {
return (T)myVariable;
}
}
myClassInstance.setMyVariable(new Vehicle());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
myClassInstance.setMyVariable(new Airplane());
Vehicle v = myClassInstance.<Vehicle>getMyVariable();
现在我们将看到在执行应用程序时出现错误,因为飞机不能被转换为车辆
因此,在这个方法中使用泛型似乎使使用类强制转换更容易。
但这是这种方法的唯一功能吗?或者还有另一个优点?这是非常不安全的,只是为了让客户的生活更容易编辑:顺便说一句,您的编译器/IDE还应该添加一个警告。由于向后兼容性的原因,这不是一个错误。您甚至不需要myClassInstance.getMyVariable,只要将myClassInstance.getMyVariable存储到Vehicle类型的变量中或从返回Vehicle的方法返回它,就可以了。在这两种情况下,都会推断类型
一种更安全的方法是将类型参数拉入类中,这样可以确保任何MyClass在编译时只保存车辆。这是非常不安全的,只是为了让客户端的生活更容易编辑:顺便说一句,您的编译器/IDE还应该添加一个警告。由于向后兼容性的原因,这不是一个错误。您甚至不需要myClassInstance.getMyVariable,只要将myClassInstance.getMyVariable存储到Vehicle类型的变量中或从返回Vehicle的方法返回它,就可以了。在这两种情况下,都会推断类型
更安全的方法是将类型参数拉入类中,这样可以确保任何MyClass在编译时只保存车辆。这样做的好处是允许用户执行强制转换,而无需编写强制转换。在大多数情况下,调用方法时不需要限定类型。以下内容相当:
Foo myValue = myClassInstance.getMyVariable();
Foo myValue = myClassInstance.<Foo>getMyVariable();
然而,在编译类时,Java会发出一个未经检查的强制转换警告,这表明您正在做一些危险或错误的事情。你可能是
您的类允许用户执行不正确的强制转换,可能会在其代码中创建各种奇怪的bug,而在编译自己的代码时不会收到任何警告。例如,以下代码在编译时不会显示警告,在运行时也不会显示运行时错误
List<Integer> myIntList = new ArrayList<Integer>();
myClassInstance.setMyVariable(myList);
List<String> myStringList = myClassInstance.getMyVariable();
myIntList.add(3);
myStringList.add("hi");
然而,当后面的代码假定您知道此列表中项目的类型时,会发生什么情况?如果显式执行了强制转换,则会出现编译时错误:
List<String> myStringList = (List<Integer>) myIntList; // error: inconvertible types
因此,它的第二个优点是,您可以使用它来编写、编译和运行比Java编译器通常允许您编写、编译和运行的Java代码更破碎、更容易出错。这样做的优点是允许用户执行强制转换,而无需编写强制转换。在大多数情况下,调用方法时不需要限定类型。以下内容相当:
Foo myValue = myClassInstance.getMyVariable();
Foo myValue = myClassInstance.<Foo>getMyVariable();
然而,在编译类时,Java会发出一个未经检查的强制转换警告,这表明您正在做一些危险或错误的事情。你可能是
您的类允许用户执行不正确的强制转换,可能会在其代码中创建各种奇怪的bug,而在编译自己的代码时不会收到任何警告。例如,以下代码在编译时不会显示警告,在运行时也不会显示运行时错误
List<Integer> myIntList = new ArrayList<Integer>();
myClassInstance.setMyVariable(myList);
List<String> myStringList = myClassInstance.getMyVariable();
myIntList.add(3);
myStringList.add("hi");
然而,当后面的代码假定您知道此列表中项目的类型时,会发生什么情况?如果显式执行了强制转换,则会出现编译时错误:
List<String> myStringList = (List<Integer>) myIntList; // error: inconvertible types
因此,它的第二个优点是,您可以使用它来编写、编译和运行Java代码,这些代码比Java编译器通常允许您编写、编译和运行的Java代码更破碎、更容易出错。这让我觉得,这本身就是不安全的,我很乐意这样做
AnyClass thing = myClassInstance.getMyVariable();
由于完全没有类型检查和客户端代码中没有警告,myClassInstance代码中会出现警告,从而在运行时引发ClassCastException
我认为最好将类参数化
public class MyClass<T> {
private T myVariable;
public void setMyVariable(T myVariable) {
this.myVariable = myVariable;
}
public T getMyVariable() {
return myVariable;
}
}
Java类型推断系统现在应该强制执行类型安全,并防止任何运行时异常。这让我觉得本质上是不安全的,我很乐意这样做
AnyClass thing = myClassInstance.getMyVariable();
由于完全没有类型检查和客户端代码中没有警告,myClassInstance代码中会出现警告,从而在运行时引发ClassCastException
我认为最好将类参数化
public class MyClass<T> {
private T myVariable;
public void setMyVariable(T myVariable) {
this.myVariable = myVariable;
}
public T getMyVariable() {
return myVariable;
}
}
Java类型推断系统现在应该强制执行类型安全,并防止任何运行时异常
选项。您也可以简单地使用Vehicle v=myClassInstance.getMyVariable;无需指定所需的类型。您也可以简单地使用Vehicle v=myClassInstance.getMyVariable;无需指定所需的类型。