请看下面的Class,我需要检查变量中是否有有效值。如果变量中有适当的值而不是null
,则一切正常。当它变为null时,行为不是我所期望的(尽管如果Integer a = null;
被检查为a instanceof Integer
时可能有意义,
有人可以指导我如何从下面的课程中获得正确的结果吗?
package com.mazhar.hassan;
public class ValueChecker {
public static boolean empty(Integer value) {
System.out.println("Integer");
return (value != null && value.intValue() > 0);
}
public static boolean empty(Long value) {
System.out.println("Long");
return (value != null && value.longValue() > 0);
}
public static boolean empty(String value) {
System.out.println("String");
return (value != null && value.length() > 0);
}
public static boolean empty(Object value) {
System.out.println("Object");
return (value != null);
}
public static void checkAll(Object... args) {
for(Object o: args) {
if (o instanceof Integer) {
empty((Integer)o);
}
else if (o instanceof Long) {
empty((Long)o);
}
else if (o instanceof String) {
empty((String)o);
}
else {
empty(o);
}
}
}
public static void main (String[] args) {
Integer a = null;
Long b = null;
String x = null;
Object y = null;
if (a instanceof Integer) {
System.out.println("a is Integer");
} else {
System.out.println("a is not Integer");
}
System.out.println("/---------------------------------------------------/");
checkAll(a,b,x,y);
System.out.println("/---------------------------------------------------/");
empty(a);
empty(b);
empty(x);
empty(y);
}
}
为什么我需要精确的类型检查,我想抛出像“无效的整数”,“无效长”等错误。
上述类的输出如下。
/-----------------------(Output 1)----------------------------/
a is not Integer
/-----------------------(Output 2)----------------------------/
Object
Object
Object
Object
/------------------------(Output 3)---------------------------/
Integer
Long
String
Object
输出1:a不是整数(由instanceof检查)无法识别它但传递给重载函数时会转到右边的函数(输出3)
输出2:如何使用多个/动态参数checkAll(varInt,varLong,varString,varObject)实现checkAll
答案 0 :(得分:5)
输出1的行为是由于方法重载在 编译时绑定的事实引起的。因此,在程序运行之前绑定的特定重载是绑定的。另一方面,instanceof
是运行时检查。
因此,在运行时a instanceof Integer
实际上是null instanceof Integer
,显然是false
。
但是对于每个单独的方法调用,都会调用正确的方法,因为编译器会根据变量的引用类型在编译时绑定方法的特定重载。因此:
empty(a); // Compiled to a call to empty(Integer value)
empty(b); // Compiled to a call to empty(Long value)
empty(x); // Compiled to a call to empty(String value)
empty(y); // Compiled to a call to empty(Object value)
因此,无论a
,b
,x
和y
引用的实际对象如何,您都可以在控制台上获得正确的输出各自的对象。
输出2:如何使用多个/动态参数checkAll(varInt,varLong,varString,varObject)实现checkAll
好吧,如果你要通过null
,你真的不可能。 null
在运行时为null
,并且没有与之关联的任何类型信息。 JVM无法判断一个空是" String null
"或者" Object null
"。它只是null
。因此,您无法真正实现null
输入所需的多项检查 - null instanceof ______
将始终返回false
,因此您始终会以默认值结束情况下。
但是,如果传递实际对象,那么 方法应该正常工作。
答案 1 :(得分:1)
<强>问题:强>
Integer a = null;
Long b = null;
String x = null;
Object y = null;
你不能在空值上使用instanceof
,它希望对象被实例化,从而给你错误的结果。
<强>溶液强>
在检查实例之前先将对象即时化。
答案 2 :(得分:1)
这里的问题是,当您在循环中检查instanceof时,您正在检查null
。 null
不是任何事物的实例,而是缺少实例。
如果您希望实现这样的目标,那么您必须将checkAll(Object ...)
的API更改为告诉函数预期类型的内容:
public class ValueChecker {
public static boolean checkAll(Object[] args, Class<?>[] types) {
if (args == null || types == null || args.length != types.length)
throw new RuntimeException("programming error");
for (int i = 0; i < args.length; i++) {
if (types[i] == null)
throw new RuntimeException("programming error");
if (args[i] == null || !types[i].isAssignableFrom(args[i].getClass())) {
System.out.println("arg " + (i +1) + " is not " + types[i].getSimpleName());
return false;
}
}
return true;
}
public static void main(String[] args) {
Integer a = null;
Long b = null;
String x = null;
Object y = null;
checkAll(
new Object[] {a, b, x, y},
new Class<?>[] {Integer.class, Long.class, String.class, Object.class}
);
}
}