我在大学里有一些工作,我们必须按照给定的模块实现通用代码。
因此,我正在制作一个仅包含Integer
,Long
,Double
和String
的课程
我观看了一些有关通用视频的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数据类型,但是我有一个问题,即*操作数不能使用。有什么问题吗?
答案 0 :(得分:4)
我要指出的第一件事是,您不能直接定义仅 接受特定类型列表的类。例如,您只能将T绑定为1个类型(或类型的交集)的子类。
对于问题中列出的类型,它们的唯一常见超类型是Serializable
和Object
。您可以将类型变量声明为:
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
是不安全的选择,因为不能将Integer
或String
强制转换为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
)。
您有几种选择:
不要使用泛型。使用interface
方法定义abstract class
或longValue
,然后将其扩展为您要支持的各种类型。
使用long
通过String
转换为Long.valueOf(getLabar().toString())
。本质上,在转换为long之前,将所有内容转换为字符串。不优雅。
使用instanceof Number
和instanceof String
决定如何将它们隐藏到long
。