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