我写了一种方法,“典型化” String
,并试图推断其中保存的数据类型。 (this gist的略微修改版本)。该方法在Map.Entry<Class, String>
中返回推断的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
的{{1}}自变量的键与大decodeTypify()
树中的任何选项都不匹配,则if-else
返回{{1} }。这是在Java 11.0.1中的jshell中运行的方法:
decodeTypify()
我为本地类型推断变量分配了一个null
值! isn't supposed to be possible。这种副作用(看来)是,我实际上可以告诉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
我有事吗?如果没有,有人可以解释这是怎么回事吗?
答案 0 :(得分:2)
您还没有打破任何东西。您不能直接分配null,但是可以通过方法调用间接分配null。
这样做的原因是,仅分配null
即可使编译器没有信息来知道所需的类型。可以进行的唯一推断是针对可用的最通用类型Object
,如果这是正确的推断,则只需将其明确声明为即可!还有3个额外的字符。
当编译器具有要使用的方法调用时,它可以使用方法的返回类型进行类型推断。
public static String foo() {
return null;
}
public static <T> T bar() {
return null;
}
public static <T> T baz(Class<T> clazz) {
return null;
}
public static void main(String[] args) {
var a = null; // compile error
var b = foo(); // fine
var c = bar(); // fine
var d = baz(String.class); //fine
}
答案 1 :(得分:0)
您可以将null值分配给类型推断的局部变量。 您只是不能使用null初始值设定项来实例化此类变量。
我检查了您引用的要点,很明显,如果您在输入中给方法“ null”(值,而不是String),那么它将把对象设置为Object类型。 您正在初始化一个空对象,'var'可以处理。至少,编译器知道您正在使用Object类。此外,方法将具有返回类型,因此var也可以使用该返回类型。
关于类型分配切换副作用的东西... 广播null始终有效,因此,泛型能够很好地处理它并不奇怪:No Exception while type casting with a null in java