在java中制作类Generic

时间:2015-08-20 22:33:24

标签: java collections

 public class ClassGenericParameterized<T> {

    public void add(T t1, T t2){
        //System.out.println(t1+t2);
        System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString()));          
    }

    public void multiply(T t1, T t2){
        System.out.println(Integer.parseInt(t1.toString()) * Integer.parseInt(t2.toString()));          
    }

    public void subtract(T t1, T t2){
        System.out.println(Integer.parseInt(t1.toString()) - Integer.parseInt(t2.toString()));          
    }

    public void division(T t1, T t2){
        System.out.println(Integer.parseInt(t1.toString()) / Integer.parseInt(t2.toString()));          
    }

    public static void main(String[] args) {

        ClassGenericParameterized<Integer> ob = new ClassGenericParameterized<Integer>();
        ob.add(1,2);
        ob.multiply(2, 4);
        ob.subtract(15, 6);
        ob.division(6, 3);

    }
}

在java中制作Generic类的逻辑和需求是什么? 何时替换声明

 ClassGenericParameterized<Integer> ob = new ClassGenericParameterized<Integer>()

通过

ClassGenericParameterized<Double> ob = new ClassGenericParameterized<Double>()

给出

Error(The method add(Double, Double) in the type ClassGenericParameterized<Double> is not applicable for the arguments (int, int))

正如我的想法那样,因为在add方法中编写的语句为Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString())

所以再次尝试替换语句

System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString()));

通过

System.out.println(t1+t2)

给出了

Error(The operator + is undefined for the argument type(s) T, T). 

那怎样才能真正意义上的通用呢?有人可以解释它为什么会发生以及如何纠正这个错误来实现我的功能吗?

2 个答案:

答案 0 :(得分:1)

在这种情况下,泛型不太适合。原因是:

  • 您不能简单地声明任何能够进行加法,减法,乘法或除法的类型。 T的上限为Object

  • 如果您将绑定设置为<T extends Number>,这仍然无效,因为您无法保证您可以将该参数中您想要的任何内容自动放映到类型T阶级被束缚了。

最终,您将要使用Number作为参数。由于Number是包括BigIntegerBigDecimal在内的所有数字包装器的父类,因此您可以利用它。

public class NumberOperations {

    public void add(Number t1, Number t2){
        //System.out.println(t1+t2);
        System.out.println(Integer.parseInt(t1.toString()) + Integer.parseInt(t2.toString()));
    }

    public void multiply(Number t1, Number t2){
        System.out.println(Integer.parseInt(t1.toString()) * Integer.parseInt(t2.toString()));
    }

    public void subtract(Number t1, Number t2){
        System.out.println(Integer.parseInt(t1.toString()) - Integer.parseInt(t2.toString()));
    }

    public void division(Number t1, Number t2){
        System.out.println(Integer.parseInt(t1.toString()) / Integer.parseInt(t2.toString()));
    }

    public static void main(String[] args) {

        NumberOperations ob = new NumberOperations();
        ob.add(1, 2);
        ob.multiply(2, 4);
        ob.subtract(15, 6);
        ob.division(6, 3);

    }
}

答案 1 :(得分:0)

首先是一点理论:

Java(和其他语言)中的泛型是一种语言技术,它使用相同的程序来处理完全不相交的类型。

最常见的例子是Collection容器:Any Collection存储&#34; any&#34;的对象。参数类型,在编译时未知但在运行时始终相同。例如:

public class MyClass<T>
{
    private T[] array;
    public void set(T t) {...}
    public T get() {...}
    public T[] get2() {...}
    public Set<T> get3() {...}
}

在编写本课程时,我们不知道将会是什么。但是有了这个客户端程序:

MyClass<String> obj=new MyClass<String>();

......我们将有一个MyClass的对象,该对象将始终与String绑定:T的每一次出现都将填充String

如果要确保泛型类中的某些层次结构约束,可以要求参数类型具有这样的最小超类:

public class MyClass<T extends SomeOtherClass>

现在,让我们来解决实际问题:

  • 您的抽象设计合理但使用错误:在main方法中,您提供int值。对Integer类型参数没问题,但要小心:如果更改为Double类型参数,您必须也更改作为输入参数提供的值方法

  • Altough设计得很好,没有正确实现:将T值转换为整数的方式很差:一个客户端程序可以声明:

    ClassGenericParameterized<String> s=new ClassGenericParameterized<String>(); s.add("hello", "world");

...并且编译器会将其传递给OK,但在运行时,您将获得NumberFormatException不希望您想要

想一想:如果你想编写一个仅面向数值的抽象代码,你应该依靠编译器检查只有数字类型作为类型参数提供:Make T extend Number:< / p>

public class MyClass<T extends Number>

...以这种方式,您可以利用intValue()方法将它们转换为整数。而且,最重要的是,您不需要使用不安全的解析*方法,这些方法可能会在运行时抛出不可预测的异常。