Я написал метод, который "типизирует" String
и пытается определить тип данных, которые в нем хранятся.(Немного измененная версия этой сути ).Метод возвращает логический Class
и исходный String
(возможно, слегка измененный - окружающий пробел, обрезанный и т. Д.) В Map.Entry<Class, String>
.Например, typify("3f")
возвращает <Float, "3.0">
, typify(" c ")
возвращает <Character, "c">
и т. Д.
Мой следующий шаг - написать второй метод, который "декодирует" эти возвращенные Map.Entry
объекты, чтобы они моглибыть непосредственно назначенным объекту предполагаемого типа.Например:
Float f = decodeTypify(typify("3.14f"))
Boolean b = decodeTypify(typify("false"))
... и так далее.Этот код приведен ниже:
@SuppressWarnings("unchecked")
public static <T> T decodeTypify (Entry<Class, String> entry) {
// String
if (entry.getKey() == String.class)
return (T) entry.getValue();
// Boolean
else if (entry.getKey() == Boolean.class)
return (T) (Boolean) Boolean.parseBoolean(entry.getValue());
// Byte
else if (entry.getKey() == Byte.class)
return (T) (Byte) Byte.parseByte(entry.getValue());
// Character
else if (entry.getKey() == Character.class)
return (T) (Character) entry.getValue().charAt(0);
// Short
else if (entry.getKey() == Short.class)
return (T) (Short) Short.parseShort(entry.getValue());
// Integer
else if (entry.getKey() == Integer.class)
return (T) (Integer) Integer.parseInt(entry.getValue());
// Long
else if (entry.getKey() == Long.class)
return (T) (Long) Long.parseLong(entry.getValue());
// Float
else if (entry.getKey() == Float.class)
return (T) (Float) Float.parseFloat(entry.getValue());
// Double
else if (entry.getKey() == Double.class)
return (T) (Double) Double.parseDouble(entry.getValue());
// LocalDateTime
else if (entry.getKey() == LocalDateTime.class)
return (T) (LocalDateTime) stringAsDate(entry.getValue());
else return null;
}
Кажется, это прекрасно работает, особенно в сочетании с новым выводом типа локальной переменной Java:
var f = decodeTypify(typify("literally anything"))
Теперь мне не нужно заботиться оВозвращенный тип вообще, потому что Java заботится о предоставлении f
правильного типа.Но обратите внимание, что если аргумент entry
для decodeTypify()
имеет ключ, который не соответствует ни одному из параметров в большом дереве if-else
, то decodeTypify()
возвращает null
.Вот этот метод, выполняющийся в jshell с Java 11.0.1:
jshell> var x = decodeTypify(typify(null))
x ==> null
Я присвоил значение null
локальной переменной с выводом типа!Это не должно быть возможным .Побочным эффектом этого (кажется) является то, что я действительно могу сказать x
, что вообще должен иметь любой тип, без предупреждений:
jshell> Object x = decodeTypify(typify(null))
x ==> null
jshell> String x = decodeTypify(typify(null))
x ==> null
jshell> Byte x = decodeTypify(typify(null))
x ==> null
Обратите внимание, что это не относится к не- null
возвращает:
jshell> var x = decodeTypify(typify("3"))
x ==> 3.0
jshell> Boolean x = decodeTypify(typify("3"))
| Exception java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.Boolean (java.lang.Double and java.lang.Boolean are in module java.base of loader 'bootstrap')
| at (#21:1)
Я что-то сломал?Если нет, может кто-нибудь объяснить, что здесь происходит?