Java泛型:运算符“ *”不能应用于T,T。我很难理解通用

时间:2019-09-23 05:52:55

标签: java generics

我在大学里有一些工作,我们必须按照给定的模块实现通用代码。

因此,我正在制作一个仅包含IntegerLongDoubleString的课程

我观看了一些有关通用视频的YouTube视频,并且也相当了解,但是我的代码存在一个问题,我无法在任何地方找到解决方案。

这是我的课程:

    public Kubus(T tinggi, T panjang,T lebar ) {

        this.tinggi = tinggi;
        this.panjang = panjang;
        this.lebar = lebar;

    }

    public T getTinggi() {
        return tinggi;
    }

    public T getPanjang() {
        return panjang;
    }

    public T getLebar() {
        return lebar;
    }

    @Override
    public String toString() {
        return "tinggi: " + getTinggi() +
                "  - panjang: " + getPanjang() +
                " - lebar: " + getLebar();
    }

    public T getResultAsLong(){
        T = getPanjang() * getLebar();
    }
}

在getResultAslong方法中,它应该采用Long数据类型,但是我有一个问题,即*操作数不能使用。有什么问题吗?

3 个答案:

答案 0 :(得分:4)

我要指出的第一件事是,您不能直接定义仅 接受特定类型列表的类。例如,您只能将T绑定为1个类型(或类型的交集)的子类。

对于问题中列出的类型,它们的唯一常见超类型是SerializableObject。您可以将类型变量声明为:

class Kubus<T extends Serializable> { // or Kubus<T>, equivalent to T extends Object

,但是您可以使用此范围内的任何T实例化,例如Kubus<ArrayList<Frobnicator>>,因为ArrayList实现了Serializable。 ({Serializable也是一种毫无用处的类型,除非您实际上想要使用内置的序列化序列化Kubus。释义Josh Bloch在 Effective Java 中的建议:“不要”)。

如果只希望 接受这些类型,则可以做的就是限制该类的构造方式,方法是将构造函数设为私有,然后为您的类型提供静态工厂方法想要

private Kubus(T tinggi, T panjang,T lebar ) { ... }

public static Kubus<Integer> ofInteger(Integer tinggi, Integer panjang, Integer lebar ) {
  return new Kubus<>(tinggi, panjang, lebar);
}

public static Kubus<Long> ofLong(Long tinggi, Long panjang, Long lebar ) {
  return new Kubus<>(tinggi, panjang, lebar);
}

// etc for other specific types.

然后您可以使用创建

Kubus<Integer> first = Kubus.ofInteger(1, 2, 3);
Kubus<Long> second = Kubus.ofLong(1L, 2L, 3L);

编写 type Kubus<ArrayList<Frobnicator>>(或任何任意类型)仍然有效,但是您无法创建它的实例。

Kubus<ArrayList<Frobnicator>> whatever = null;

这实际上使您有机会解决您询问的特定问题(*)。

问题是您不能将任意事物相乘。在这里,您需要一些方法将“事物”转换为long,以便使其倍增。强制转换为Long是不安全的选择,因为不能将IntegerString强制转换为Long

由于您只想将T限制为某些类型,因此还可以提供一个转换器来安全地进行转换类型。

可以使用ToLongFuntion<T>对这种转换器进行建模:这需要一个T,并返回一个long。因此,更改构造函数以采用另一个参数:

private Kubus(T tinggi, T panjang,T lebar, ToLongFunction<T> converter ) { ... }

public static Kubus<Integer> ofInteger(Integer tinggi, Integer panjang, Integer lebar ) {
  return new Kubus<>(tinggi, panjang, lebar, i -> i.intValue());
}

public static Kubus<Long> ofLong(Long tinggi, Long panjang, Long lebar ) {
  return new Kubus<>(tinggi, panjang, lebar, lng -> lng.longValue());
}

// etc for other specific types.

converter分配给构造函数中的一个字段,然后在您的乘法方法中应用以获取长整型值,该值可以相乘:

return converter.applyAsLong(getTinggi())
    * converter.applyAsLong(getPanjang())
    * converter.applyAsLong(getLebar());

(*)我无意暗示您只能将converter方法与private构造函数一起使用:您当然可以使构造函数成为非私有的,并直接使用实例化构造函数。我只是怀疑您会很快对书面重复感到厌倦:

Kubus<Integer> first = new Kubus<>(1, 2, 3, Integer::longValue);
Kubus<Integer> second = new Kubus<>(1, 2, 3, Integer::longValue);
Kubus<Integer> third = new Kubus<>(1, 2, 3, Integer::longValue);
// ...

答案 1 :(得分:0)

如果要执行乘法运算(*),则首先需要将getPanjang()和getLebar()的值强制转换为任何数字格式,然后执行乘法运算。

答案 2 :(得分:0)

如果您的T类型需要为数字,则可以使用<T extends Number>进行定义,以确保您可以在任何Number.longValue上调用T。不幸的是,您特别声明它可能是String(想将其转换为long中的getResultAsLong)。

您有几种选择:

  1. 不要使用泛型。使用interface方法定义abstract classlongValue,然后将其扩展为您要支持的各种类型。

  2. 使用long通过String转换为Long.valueOf(getLabar().toString())。本质上,在转换为long之前,将所有内容转换为字符串。不优雅。

  3. 使用instanceof Numberinstanceof String决定如何将它们隐藏到long