为什么需要Generic类型然后键入reasure虽然我们可以使用Object Pojo

时间:2017-07-18 12:06:58

标签: java generics

我有这样的代码:

public class Crate<T> {
    private T contents;

    public T emptyCrate() {
        return contents;
    }

    public void packCrate(T contents)
    {
        this.contents = contents;
    }
}

现在我们知道 - 最后它将被“转换”为以下代码:

public class Crate {
    private Object contents;

    public Object emptyCrate() {
        return contents;
    }

    public void packCrate(Object contents) 
    {
        this.contents = contents;
    }
}

那么为什么我们需要创建一个泛型,如果我已经可以创建一个类似Object的类?

5 个答案:

答案 0 :(得分:2)

你看,java代码被翻译成字节码。那你为什么不用字节码编写你的程序呢?无论如何他们会被翻译?或者,确切地说:JIT编译器会在某些时候将大多数字节码转换为机器码。那么为什么你坚持编写java源代码而不是二进制机器代码?!

我猜上述问题清楚地说明了这一点:泛型允许您表达人类读者的意图。它们允许您编写更好的源代码;并且它们使编译器能够对您的输入进行某些类型的检查 - 正如安迪·特纳在另一个答案中所总结的那样。

这就是编程语言为您提供的任何抽象的全部要点:它们帮助程序员创建表达“需要做什么”的源代码以简洁的方式使人类读者更容易了解正在发生的事情,以及为什么

答案 1 :(得分:2)

当人们谈论类型擦除时,他们通常会关注泛型类本身。但是泛型有另一个重要的地方:呼叫网站。

例如,如果你有这个代码:

ServiceConfigurationError

然后,当它被编译时,它实际上变成:

Crate<Integer> intCrate = new Crate<>();
intCrate.packCrate(0);
Integer contents = intCrate.emptyCrate();

即。有自动插入的强制转换。另外,隐含地,检查Crate intCrate = new Crate(); intCrate.packCrate(0); Integer contents = (Integer) intCrate.emptyCrate(); // ^ Important! This cast. 的参数是否与packCrate兼容,因此您无法写:

Integer

现在,您可以在没有泛型的情况下执行此操作,自己进行这些转换,但编译器无法帮助您了解放入intCrate.packCrate("hello"); 的内容。你可以这样写:

Crate

这会在运行时失败,因为包中包含Crate crate = new Crate(); crate.packCrate(0); String contents = (String) crate.emptyCrate(); ,而不是Integer

泛型只是帮助您不必记住您可以传递给实例的内容,以及您将从中获得的内容。

答案 2 :(得分:1)

它将变成什么并不重要。

相反,编译阶段很重要。泛型保证编译类型类型安全(修复编译时错误比运行时错误容易得多)。

它还消除了强制转换,并且能够实现通用算法

答案 3 :(得分:0)

Java中的所有集合都是泛型。这是使用泛型的最好例子。例如,您创建类List。它会包含哪些类型的物体?当您创建List类时,您不知道它将保留哪些类型,因此您使用泛型。当您使用List课程时,您说要放Integersnew List<Integer)。

答案 4 :(得分:0)

泛型中的模板参数用于编译时安全性。如果你写的话,编译器会窒息:

Crate<Integer> cr;
Object o;

cr.packCrate(o);  // compilation error here

它还可以声明用作参数的任何类都将实现一些方法:

Interface I {
    void myMethod();
}

class Crate<T extends I> {
    private T contents;
    ...
    public void applyMethod() {
        contents.myMethod();      // T shall implement myMethod
    }
}

事实上,一切都可以通过显式转换来完成,但是你只能获得运行时错误,而泛型允许编译时检测到错误。