免责声明
在继续之前,我必须指出,当我们对Java进行编程时,本文中描述的技术没有实际目的。 这就像填字游戏或拼图。 它主要训练您的大脑进行逻辑思维,可能发展您的Java语言知识甚至您的思维能力。 这就像魔术师执行的把戏。 最后,您意识到什么都不是样子。 切勿在现实生活的编程中做任何花招,以解决此难题。
问题
我最近阅读了一篇文章 ,其中描述了以下情况下的调试情况:
if(trouble != null && !trouble.isEmpty()) {
System.out.println(“fine here: ” + trouble);
}else{
System.out.println(“not so fine here: ” + trouble);
}
正在打印:
fine here: null
实际的错误是字符串包含“ null”,也就是字符“ n”,“ u”,“ l”和“ l”。 在现实生活中可能会发生,特别是当您在不检查变量的空值的情况下连接字符串时。
然后,我开始考虑其他类似的奇怪代码和调试情况。 我能否做到这一点,以使变量不仅是带有这些字符的“空”字符串,而且实际上是空的? 好像疯了吗? 看一下代码:
package com.javax0.blog.nullisnotnull;
public class NullIsNotNull {
public static void troubled(){
String trouble = new String("hallo");
Object z = trouble != null && !trouble.toString().isEmpty() ?
trouble.toString() : "";
if (z == null) {
System.out.println("z is really " + z + "?");
}
}
}
它会打印出:
z is really null?
题。 事实是,您可以创建一个包含public static void main()
的Java类,以便在main()
调用troubled()
的方法troubled()
时打印该句子作为Java应用程序。 换句话说:我确实调用了troubled()
方法,解决方案不是main()
打印该句子。
在这种情况下,变量z
不仅被打印为“ null”,而且实际上为null。
提示
解决方案不应涉及
- 反射
- 字节码操作
- 打电话给JNI
- 特种装载机
- Java代理
- 注释处理器
这些工具太重了。 您不需要这种军械库。
提示#1
如果我更改代码,使变量z
为String
它甚至不会编译:
如果它使您更加困惑,那就对不起。 继续阅读!
提示2
在Java语言中, String
是标识符而不是关键字。 Java语言规范 3.9节可能会提供有关此重要性的更多信息。
提示#3
类Object
中的toString()
方法具有返回类型java.lang.String
。 您可能需要阅读我的文章 ,其中涉及类的名称,简单名称和规范名称之间的区别。 这可能会有所启发,并增加文章的点击数。
提示#4
要使用在同一程序包中声明的类,无需导入该程序包。
解
解决方案是在同一包中创建一个名为String
的类。 在这种情况下,编译器将使用此类而不是java.lang.String
。 代码中的三元运算符是简单的魔术师技巧。 从重点出发,有些事情会引起您的注意。 要点是,上述代码中的String不是java.lang.String
。 如果仍然找不到如何创建把戏类的方法,请单击折叠的源代码块以全面了解它:
package com.javax0.blog.nullisnotnull;
class String {
private java.lang.String jString;
private boolean first = true;
public String(java.lang.String s) {
jString = s;
}
public boolean isEmpty() {
return jString.isEmpty();
}
@Override
public java.lang.String toString() {
if( first ){
first = false;
return jString;
}
return null;
}
public static void main(java.lang.String[] args) {
NullIsNotNull.troubled();
}
}
翻译自: https://www.javacodegeeks.com/2014/11/when-null-checking-miserably-fails.html