我有点生疏,陷入了一些基本问题。我希望我的方法printBinary
能够接受Long
或Integer
。并根据我想要调用相应对象的toBinaryString()
方法的输入类型。
现在我知道有一些替代方法,比如方法重载,我可以创建两个方法,调用printBinary
,但一个方法需要Long
,另一个需要Integer
。但如果我想用一种方法做到这一点我怎么能实现呢?
public static <T extends Object> void print(T arg){
System.out.println(arg);
}
public static <T extends Number> void printBinary(T arg){
if(arg instanceof Long){
print(Long.toBinaryString(arg)); //this throws an error incompatible types: Number cannot be converted to long
}else{
print(Integer.toBinaryString(arg)); //this throws an error incompatible types: Number cannot be converted to int
}
}
答案 0 :(得分:4)
你的写作
public static <T extends Number> void printBinary(T arg)
所以你声明T
是扩展Number
的东西。非常重要,请注意关于T
的更多信息。所以你只能安全地假设它是Number
,但仅此而已(没有检查,例如使用instanceof
)。
接下来就是你写
// requires long
print(Long.toBinaryString(arg));
// requires int
print(Integer.toBinaryString(arg));
但这两种方法都不需要Number
,它们需要long
和int
。请查看他们的文档(Long,Integer)。
即使我们考虑装箱,Java也只能将Long
转换为long
和Integer
转换为int
(反之亦然)。但不是Number
到Long
或Number
到Integer
。 Number
不一定是Long
或Integer
。例如,它也可以是Double
。而且你不知道T
是什么,你只知道它至少是Number
类型。
因此,您需要做的是明确将arg
转换为long
和int
。因此,您可以使用Number
提供的实用程序方法,即Number#longValue和Number#intValue:
print(Long.toBinaryString(arg.longValue()));
print(Integer.toBinaryString(arg.intValue()));
instanceof
另一个可能是施放他们。如果您使用instanceof
检查T
确实属于Long
类型或Integer
,则可以安全地投放它:
print(Long.toBinaryString((Long) arg));
print(Integer.toBinaryString((Integer) arg));
投射后,Java会自动将Long
转换为long
,将Integer
转换为int
,这称为取消装箱。或者为了使其更明确,请自行调用取消装箱方法:
print(Long.toBinaryString(((Long) arg).longValue()));
print(Integer.toBinaryString(((Integer) arg).intValue()));
准确地说,使用您当前的代码,取消选中 <{1}}。您还需要检查Integer
,因此更安全:
arg instanceof Integer
答案 1 :(得分:2)
如果你想要你的方法
public static <T extends Number> void printBinary(T arg){
if(arg instanceof Long){
print(Long.toBinaryString(arg)); //this throws an error incompatible types: Number cannot be converted to long
}else{
print(Integer.toBinaryString(arg)); //this throws an error incompatible types: Number cannot be converted to int
}
}
要工作,你需要在调用toBinaryString(art)方法时使用强制转换,例如像这样
public static <T extends Number> void printBinary(T arg){
if(arg instanceof Long){
print(Long.toBinaryString((Long) arg)); //this throws an error incompatible types: Number cannot be converted to long
}else{
print(Integer.toBinaryString((Integer) arg)); //this throws an error incompatible types: Number cannot be converted to int
}
}
但是,您发布的代码仍存在一个问题。正如@Jacob H所说,像<T extends Number>
这样的声明意味着该方法将接受扩展Number类的任何类的参数。因此,如果参数的类型为Integer或Long,它将起作用,但是例如Float值将被传递时将失败。
很遗憾toBinaryString方法不是由Number类实现的,而是由Integer和Long之类的子类提供的方法。
因此,对于您的情况,实现两个采用不同类型参数的分离方法可能更好 - Long和Integer。
如果你真的想使用这种通用符号,但不处理除Integer和Long之外的其他类型的输入,你可能需要生成某种参数类型验证。但是,仍然,定义采用Number类型参数并且不处理它的某些子类的方法,有些确实可能会让人感到困惑并且看起来像是一个糟糕的设计。
答案 2 :(得分:0)
您只想使用<Number>
,<T extends Number>
表示“某些类型T扩展数字”,因此它需要Long或Integer,但不能同时使用。 <Number>
表示“数字或任何扩展数字的类型”
答案 3 :(得分:0)
最好的解决方案是使用方法过载。使用Number
,该方法也将接受双打。
如果您真的想使用Number
,则不需要泛型。重写像这样的方法
public static void print(Object arg)
public static void printBinary(Number arg)