在Java中,如果我写:
function Cat(name)
{
this.Name = name || "Cat";
}
var x = new Cat("kitty");
function PetTheCat(cat)
{
/// <param name='cat' type='Cat' />
console.log(cat.Name + " is purring!");
}
,我得System.out.println((String) null);
。
这看起来很奇怪。有谁知道为什么设计师选择这种方法?在我看来,这是一个“无中生有”的案例。我读过JLS entry on cast operators,并说:
强制转换表达式的类型是将捕获转换(第5.1.10节)应用于其名称出现在括号内的类型的结果。
即使操作数表达式的结果是变量,转换表达式的结果也不是变量,而是值。
跳转到entry on capture conversion,我看到为泛型类型定义的捕获转换,但该条目添加:
除参数化类型(第4.5节)以外的任何类型的捕获转换都充当身份转换(第5.1.1节)。
好!在entry on identity conversion上,就是这个:
任何类型都允许从类型转换为相同类型。
在这种情况下,类型为"null"
,但要转换的内容为String
,这让我感到困惑。但是,事实证明Java实际上正在为null
使用字符串转换。 JLS entry on String conversion说:
任何类型都可以通过字符串转换转换为String类型...
如果引用为null,则将其转换为字符串“null”(四个ASCII字符n,u,l,l)。
这引起的一个问题是:
(String) null
该程序打印HashMap map = new HashMap();
System.out.println((String)map.get("something"));
。我如何知道是否因为条目"null"
而不是HashMap中的字符串值为“null”(四个ASCII字符'n','u','l','l')?现在我知道有人会说Java不鼓励使用raw types,并且类型null
应该参数化但是解决方案是什么?
答案 0 :(得分:-1)
你正在思考这个问题。 Java没有将(值)null
转换为(字符串)"null"
。正确的答案是,这只是PrintStream.println(String)
方法的明确行为:
打印字符串然后终止该行。此方法的行为就像调用
print(String)
然后调用println()
。
接下来,我们会咨询PrintStream.print(String)
所说的内容:
打印一个字符串。如果参数为
null
,则打印字符串"null"
。否则,字符串的字符将根据平台的默认字符编码转换为字节,并且这些字节的编写方式与write(int)
方法完全相同。
(请注意,System.out
的类型为PrintStream
。)
答案 1 :(得分:-1)
HashMap map = new HashMap(); System.out.println((String)map.get("something"));
该程序打印
"null"
。我怎么知道是不是因为 entry为null
,而HashMap中的String值为&#34; null&#34; (四个ASCII字符&#39; n&#39;,&#39; u&#39;,&#39; l&#39;,&#39; l&#39;)?
null
和"null"
之间仍然存在差异,当您使用System.out.println
打印出来时,您无法看到它们。他们的价值观不同,他们的确有不同的比较:
HashMap map = new HashMap();
map.put("foo", "null");
String something = (String) map.get("something");
String foo = (String) map.get("foo");
System.out.println(something == null); // true
System.out.println(foo == null); // false
System.out.println("null".equals(something)); // false
System.out.println("null".equals(foo)); // true
答案 2 :(得分:-1)
它与转换无关,但与打印无关:如果将null
转换为String,它仍然是null
:
String s=(String)null;
if (s==null)
{
System.out.println("It is still a null");
}
else
{
throw new RuntimeException("This won't happen");
}
因此,检查Map,Collection或任何API返回的值是否为空,您应该没有任何困难,只需按程序执行直接比较。
另一方面,永远不要相信PrintStream
(作为System.out)直接打印到标准输出的结果。请参阅PrintStream.print(String)的文档。
此外:打印数字或布尔值时会出现同样的歧义:如果在标准输出“123”上看到,它是数字值还是字符串值?我坚持认为:要检查值,永远不要相信打印到PrintStream的字符串的外观。