使用参数化(通用)Java类与普通类

时间:2011-05-29 16:21:52

标签: java generics

如果我需要编写一个处理'Comparable'类型数据的类,我可以用两种方式来做:

1)

public class MyClass<T extends Comparable>
{

    private T value;

    MyClass(T value)
    {
        this.value = value;    
    }

    other code...
}

2)

public class MyClass
{

    private Comparable value;

    MyClass(Comparable value)
    {
        this.value = value;    
    }

    other code...
}

这两种方法中的哪一种更好,为什么?一般来说,如果能够在不使用Geneics的情况下实现同样的事情,那么使用Generics会更好吗?

6 个答案:

答案 0 :(得分:6)

这取决于你班上的其他人。例如,如果您有一个方法getValue,那么通用方法会更好,因为您可以这样做:

public class MyClass<T extends Comparable>
{

    private T value;

    MyClass(T value)
    {
        this.value = value;    
    }

    T getValue() {
        return this.value;
    }

    other code...
}

如果没有泛型,某些类型信息会丢失,因为您只能返回Comparable

答案 1 :(得分:4)

一般来说,事实并非如此。只有在想要添加原本不存在的类型安全时,才应使用泛型。对于你的示例类是否就是这种情况,我们实在说不出来;如果您的班级集体处理了多个Comparable个对象,那么可以使用泛型来确保它们Comparable<T>T的相同值;但如果没有,可能没有理由在这里使用泛型。

答案 2 :(得分:2)

泛型提供更高的编译时类型安全性。由于type erasure,它们对运行时性能没有(直接)影响。

那就是说,你的例子可能会因使用泛型而受益。就目前而言,它应该产生关于使用原始类型的编译器投诉。它必须修改为这样的东西:

public class MyClass<T extends Comparable<? extends SomeBaseClass>>
{

    private T value;

    MyClass(T value)
    {
        this.value = value;    
    }

    // other code...
}

然后编译器可以检查所涉及的对象类型,以确保它们彼此可以

答案 3 :(得分:1)

使用泛型时,可以返回对象,因为它将被声明为编译时。如果不使用泛型,则必须在需要时将其强制转换为正确的类型。 e.g。

//Generic class 
class CGeneric<T extends Comparable>
{
    private T obj;
    public T getObj() { return obj; }
    public void setObj(T value) { obj = value;: }
}

//Non-generic class
class CNormal
{
  private Comparable obj;
  public Comparable getObj() { return obj; }
  public void setObj(Comparable value) {obj = value;}
}

在CGeneric实例上调用getObj时,可以将该对象用作MyComparable(如果要使用在此处声明的特殊方法)。如果你在CNormal上调用getObj,你会得到一个Comparable(在编译时),你必须将它强制转换为MyComparable才能使用你可能拥有的特殊方法。

因此泛型为您提供编译时类型检查,您将不会遇到CastException。

答案 4 :(得分:0)

泛型的主要原因是只能使用一种类型(类型安全)。除非你做到,否则任何东西都可以使用。我个人会选择第1步。

答案 5 :(得分:0)

仿制药最显着的缺点很简单:它们非常复杂,无法完全正确。 T扩展可比?那将是有效的,但这是仿制药和非仿制药的混合物。所以第一个可能尝试的是T extends Comparable&lt; T&GT;哪个会工作正常,但遗憾的是限制太多,因为假设一个类:

class Foo实现Comparable&lt;对象&gt;

实际上,实现应该是T extends Comparable&lt; ?超级T&gt;。很好,而不是那么复杂。但后来我们得到像Enum&lt; E延伸Enum&lt; E - 代替;&GT;而且,真的,在不混淆他的情况下向他解释 - 祝你好运。

因此,泛型对于使用非常有用且简单,但是很难正确编写(并且不要让我开始编写现有库的正确二进制向后兼容版本 - 请参阅JDK中的集合库)。幸运的是,只有少数图书馆作者必须让其他人从中获利才能获利