Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在不使用泛型的类中的方法中,泛型的用途是什么?_Java_Generics - Fatal编程技术网

Java 在不使用泛型的类中的方法中,泛型的用途是什么?

Java 在不使用泛型的类中的方法中,泛型的用途是什么?,java,generics,Java,Generics,我在很多API中看到过这种代码方法,ant总是想知道它的真正目的是什么。 如果我们有一个带有简单签名的类,我们可以这样说: public class MyClass {...} 在这个类中,我们有一个Object类型的变量,这个变量有一个getter和一个setter。 区别在于getter方法使用泛型。所以我们班看起来是这样的: public class MyClass { private Object myVariable; public void setMyVariab

我在很多API中看到过这种代码方法,ant总是想知道它的真正目的是什么。 如果我们有一个带有简单签名的类,我们可以这样说:

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;无需指定所需的类型。