【问题标题】:Java template with primitivedata types as C++ templates具有原始数据类型的 Java 模板作为 C++ 模板
【发布时间】:2016-12-09 12:21:06
【问题描述】:

我想使用模板/泛型在 Java 中实现一个函数,就像在 C++ 中一样。我尝试在 Java 中使用具有原始值(int、double、...)的泛型,但是对于下面的函数意味着我从编译器得到以下错误:

错误:二元运算符 '+' sum += value 的操作数类型错误;第一的 类型:双秒类型:T 其中 T 是类型变量:T 扩展 在方法mean(T[])中声明的对象

我尝试将 T 替换为不同的值,但找不到答案。正确的做法是什么?

// Java code
private <T> double mean(T[] data) {
    double sum = 0;
    for (T value : data)
        sum += value;

    return sum / data.length;
}

【问题讨论】:

    标签: java templates


    【解决方案1】:

    简单地说:你不能。

    相对于 C++ 模板; Java 泛型适用于 reference 也就是“对象”类型。不,没有办法解决这个问题。

    这里的关键是:Java 泛型与 C++ 模板相同。

    在 C++ 方面,编译器确实从您的模板中创建了特定于类型的代码。对于 java,泛型是(不多于)语法糖,围绕着采用 Object 参数的方法。换句话说:编译器执行所有转换,因此看起来您的 List&lt;String&gt; 真的只适用于字符串。但是List&lt;String&gt;List&lt;Integer&gt; 没有特殊/不同的编译单元。只有一个 List.class 可以在所有地方与 Object 一起使用。

    所以基本的答案是:两个概念在两种不同的编程语言中看起来在语法上相同的事实......并不能使它们在语义上相同。

    并且记录在案:正如另一个答案所暗示的那样,您可以使用&lt;T extends Number&gt; 之类的东西,然后使用另一种语法糖(称为自动装箱或拆箱)。但要注意后果:基本上是自动装箱翻译为:中间 Long、Integer、...对象的创建。换句话说:广泛使用,可能会对性能产生重大影响(例如,在处理具有原始值的非常大的数组时);因为没有什么比创建大量立即变成“垃圾”(从而触发 GC 活动!)的对象更“糟糕”了!

    【讨论】:

      【解决方案2】:

      Java 中不能有带有原始类型参数的泛型函数。

      您可以使用盒装原语(java.lang.Integerjava.lang.Double 等)来近似解决方案,并且所有这些类都实现了java.lang.Number 接口。

      使用数组的解决方案:

      private static <T extends Number> double mean(T[] data) { 
          double sum = 0;
          for (T number : data)
              sum += number.doubleValue();
      
          return sum / data.length;
      } 
      
      public static void main(String[] args) { 
          Double[] data = new Double[] {12.0, 16.0};
          System.out.println(mean(data));
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-16
        • 2011-07-26
        • 1970-01-01
        • 2010-12-22
        • 2010-09-15
        • 1970-01-01
        相关资源
        最近更新 更多