简体   繁体   English

Java类型转换,对象类型和重载问题

[英]Java Type Cast, Object Type and overloading Issue

Please have a look on following Class, I need to check if there is valid value in the variable. 请看下面的类,我需要检查变量中是否有有效值。 All works fine if there is a proper value in variable instead of null , When it comes null the behaviour is not what I expect (Although it might make sense if Integer a = null; when checked as a instanceof Integer , 如果变量中有一个适当的值而不是null ,那么一切都可以正常工作,当它为null ,行为不是我期望的(尽管Integer a = null;可能是有意义的Integer a = null;当作为a instanceof Integer进行检查时,

Can some one guide me how to achieve correct result from following class? 有人可以指导我如何从上课后获得正确的结果吗?

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);
    }
}

Why I need exact type checking is, I thave to throw erros like "Not valid Integer", "No valid Long" etc. 为什么需要精确的类型检查,我必须抛出诸如“无效的整数”,“无效的长整数”等错误信息。

The output of above class is as follows. 上一类的输出如下。

/-----------------------(Output 1)----------------------------/
a is not Integer
/-----------------------(Output 2)----------------------------/
Object
Object
Object
Object
/------------------------(Output 3)---------------------------/
Integer
Long
String
Object

Output 1: a is not integer (checked by instanceof) can not recognize it but when passed to a overloaded function goes to the right function (Output 3) 输出1:a不是整数(由instanceof检查)不能识别它,但是当传递给重载函数时转到正确的函数(输出3)

Output 2: How to achieve checkAll with multiple/dynamic param checkAll(varInt, varLong, varString, varObject) 输出2:如何实现checkAll具有多个/动态PARAM checkAll(varInt,varLong,varString,varObject)

The behaviour for Output 1 is caused by the fact that method overloads are bound at compile time. 输出1的行为是由于在编译绑定了方法重载这一事实引起的 So the specific overload to pick is bound before the program even runs. 因此,要选择的特定重载在程序甚至运行之前就已绑定。 instanceof , on the other hand, is a runtime check. 另一方面, instanceof是运行时检查。

Thus, at runtime a instanceof Integer is effectively null instanceof Integer , which is obviously false . 因此,在运行时, a instanceof Integer实际上是null instanceof Integer ,这显然是false

But for each of those individual method calls, the proper method is called because the compiler bound the specific overload of the method at compile time, based on the reference type of the variable. 但是对于每个单独的方法调用,都将调用适当的方法,因为编译器根据变量的引用类型在编译时绑定了方法的特定重载。 Thus: 从而:

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)

So regardless of the actual object that a , b , x , and y reference, you'll always get the right output on your console for the respective object. 因此,无论abxy引用的是哪个实际对象,您都将始终在控制台上为各个对象获得正确的输出。


Output 2: How to achieve checkAll with multiple/dynamic param checkAll(varInt, varLong, varString, varObject) 输出2:如何使用多个/动态参数checkAll(varInt,varLong,varString,varObject)实现checkAll

Well, if you're going to pass null , you can't really. 好吧,如果您要传递null ,那么您就不能做到。 null is null at runtime, and doesn't have any type information associated with it. null在运行时为null ,并且没有任何与之关联的类型信息。 The JVM can't tell that one null is a " String null " or an " Object null ". JVM不能说一个null是“ String null ”或“ Object null ”。 It's just null . 它只是null So you can't really implement the multiple check you want to for null inputs -- null instanceof ______ will always return false , so you'll always end up with your default case. 因此,您不能真正实现对null输入想要的多重检查null instanceof ______总是返回false ,因此您总是会遇到默认情况。

If you pass actual objects, though, that method should work properly. 但是,如果传递实际对象,则该方法应该可以正常工作。

problem: 问题:

    Integer a = null;
    Long b =  null;
    String x = null;
    Object y = null;

You cant use instanceof on null values, it expect the objects to be instantiated thus giving you wrong result. 您不能对空值使用instanceof ,它期望对象被实例化,从而给您错误的结果。

solution: 解:

instantaite the object first before you check for instance. 在检查实例之前,先实例化对象。

The problem here is that when you check instanceof in your loop, you are checking null . 这里的问题是,当您在循环中检查instanceof时,您正在检查null null is not an instance of anything, it is the absence of an instance. null不是任何实例,它是没有实例。

If you want to achieve something like this, you're going to have to change your API for checkAll(Object ...) to something that tells the function what types to expect: 如果要实现这样的目标,则必须将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}
        );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM