【问题标题】:Making class Generic in java在java中制作类泛型
【发布时间】:2015-08-21 08:04:19
【问题描述】:
 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). 

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

【问题讨论】:

  • 问题是int不能自动装箱到Double。
  • 而且您完全误解了泛型,因为 T 的实际类型在您的方法中没有任何意义。
  • 是的,我已经猜到了,有什么方法可以纠正它? @sotirios
  • 自动装箱在你的情况下不起作用,试试这个:ob.add((double)1,(double)2);
  • 你想做什么?没有 generic 方法可以像那样做 add()。

标签: java collections


【解决方案1】:

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

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

  • 1234563 .

最终,您将希望使用Number 作为您的参数。由于Number 是所有数字包装器(包括BigInteger 和BigDecimal)的父类,因此您可以利用它。

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);

    }
}

【讨论】:

    【解决方案2】:

    先说一点理论:

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

    最常见的例子是Collection 容器:Any Collection 存储“任何”参数类型的对象,这些对象在编译时是未知的,但在运行时总是相同的。例如:

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

    在编译这个类时,我们不知道 T 会是什么。但是有了这个客户端程序:

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

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

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

    public class MyClass<T extends SomeOtherClass>
    

    现在,让我们进入实际问题:

    • 您的抽象设计得很好但使用错误:在main 方法中,您提供了int 值。 Integer 类型参数没问题,但请注意:如果您更改为 Double 类型参数,您必须还更改作为方法输入参数提供的值。

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

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

    ...编译器会通过它作为 OK,但在运行时你会得到一个 NumberFormatException,这不是你想要的。

    想一想:如果你想编写一个只面向数值的抽象,你应该依靠编译器来检查只提供数值类型作为类型参数:Make T extend Number:

    public class MyClass<T extends Number>
    

    ...通过这种方式,您可以利用intValue() 方法将它们转换为整数。而且,最重要的是,您无需使用可能在运行时引发不可预测异常的不安全 parse* 方法。

    【讨论】:

    • 谢谢@Little Santi,很好的解释...... tnx 很多
    • 但最后我需要 t1.intValue(),它再次不适用于 double 等,这会破坏我的类的通用性
    • 不,一点也不:您可以合法地在 Number 的任何子类上调用 intValue:Integer、Double、Long、Float 等。它可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    相关资源
    最近更新 更多