Приведение типов Java, проблема с типом объекта и перегрузкой

#java #casting #overloading

#java #Кастинг #перегрузка

Вопрос:

Пожалуйста, посмотрите на следующий класс, мне нужно проверить, есть ли в переменной допустимое значение. Все работает нормально, если в переменной есть правильное значение вместо 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 amp;amp; value.intValue() > 0);
    }
    public static boolean empty(Long value) {
        System.out.println("Long");
        return (value != null amp;amp; value.longValue() > 0);
    }
    public static boolean empty(String value) {
        System.out.println("String");
        return (value != null amp;amp; 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)

Комментарии:

1. Я думаю, вам следует вызвать общую ошибку нулевого указателя, что-то вроде «поле не может быть нулевым», и если есть какие-либо данные, затем проверьте конкретный формат (в этом случае вам даже не нужен экземпляр). Это также позволит избежать склеивания кода (скопируйте и вставьте, если xxx!= null). Дайте мне знать, соответствует ли это вашим потребностям.

Ответ №1:

Поведение для вывода 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: Как добиться проверки с помощью проверки нескольких / динамических параметров (varInt, varLong, varString, varObject)

Ну, если вы собираетесь пройти null , вы действительно не можете. null находится null во время выполнения и не имеет никакой информации о типе, связанной с ним. JVM не может определить, что один null является « String null » или « Object null «. Это просто null . Таким образом, вы не можете реализовать многократную проверку, которую вы хотите выполнить для null входных данных — null instanceof ______ всегда будет возвращаться false , поэтому вы всегда будете иметь свой случай по умолчанию.

Однако, если вы передаете реальные объекты, этот метод должен работать правильно.

Комментарии:

1. @NetSurgeon Спасибо! Забавный факт: если вы замените любой из empty(_) них на empty(null) , вы получите ошибку компилятора, потому что компилятор не может определить, какой метод привязать. Не могу себе представить, что это слишком полезно.

2. О да, если null передается напрямую, это ошибка компилятора. спасибо.

Ответ №2:

проблема:

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

Вы не можете использовать instanceof значения null, он ожидает, что объекты будут созданы, что даст вам неверный результат.

решение:

сначала создайте объект, прежде чем проверять, например.

Комментарии:

1. Правильно, это то, что я понял из приведенного выше опыта. но если вы видите 3-й вывод, перегруженные функции распознают тип этих нулевых переменных. Мне нужно знать, как они это делают?

2. Это был не я (the -ve)

3. @NetSurgeon ммм, потому что вы печатаете его перед проверкой.

Ответ №3:

Проблема здесь в том, что когда вы проверяете instanceof в своем цикле, вы проверяете null . null это не экземпляр чего-либо, это отсутствие экземпляра.

Если вы хотите достичь чего-то подобного, вам придется изменить свой API на checkAll(Object ...) что-то, что сообщает функции, какие типы ожидать:

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