java 易错题_Java五道输出易错题解析(进来挑战下)

收集了几个易错的或好玩的Java输出题,分享给大家,以后在编程学习中略微注意下就OK了。

1. 看不见的空格?

以下的输出会正常吗?package basic;

public class IntegerTest {

public static void main(String[] args) {

System.out.println(Integer.parseInt("1"));

System.out.println(Integer.parseInt("2"));

}

}

解析:将上面代码复制下(不要自己手敲)在自己的环境里执行看看,是不是输出以下错误来了:1

Exception in thread "main" java.lang.NumberFormatException: For input string: "2"

at java.lang.NumberFormatException.forInputString(Unknown Source)

at java.lang.Integer.parseInt(Unknown Source)

at java.lang.Integer.parseInt(Unknown Source)

at basic.IntegerTest.main(IntegerTest.java:7)

居然说第二条语句有问题,表面上全然看不出来不论什么问题是不是!

实际上这里的错误原因涉及到一个概念 — 零宽度空格,可能有人接触过,但相信很多其它的人甚至都没听过,什么是零宽度空格?它实际上是一个Unicode字符,是一个空格。关键是它没有宽度,因此我们一般肉眼看不到。

但能够在vim下看到,上面的第二条语句中的2前面就有一个零宽度空格。放到vim中打开后你会发现是以下这种语句:System.out.println(Integer.parseInt("2"));

Unicode规范中定义,每个文件的最前面分别增加一个表示编码顺序的字符,这个字符的名字叫做”零宽度非换行空格“(ZEROWIDTHNO-BREAKSPACE),用FEFF表示。

这正好是两个字节,并且FF比FE大1。因此以下的语句会输出65279。刚好是FEFF。System.out.println((int)"2".charAt(0));

2. 类静态成员初始化

以下的程序能编译通过么?假设通过,说结果并解释,不能编译,说错误原因。class A

{

public static int X;

static { X = B.Y + 1;}

}

public class B

{

public static int Y = A.X + 1;

static {}

public static void main(String[] args) {

System.out.println("X = "+A.X+", Y = "+B.Y);

}

}

解析:这个程序能正确执行,类的执行步骤例如以下:首先载入主类B,初始化静态成员Y。发现须要类A的信息,于是载入类A。初始化静态成员X,也用到B类信息,因为此时B类的Y还未成功载入因此这里是默认值0。从而得到A类的X为1,然后返回到B类,得到Y为2。

3. 装箱拆箱的实际过程

关于自己主动装箱,相信大部分人都明确是怎么一回事,但真的全然明确了嘛?

先看以下的代码:Short s1 = 1;

Short s2 = s1;

System.out.println(s1 == s2);

谁都知道当然打印true了。如今加一句试试:Short s1 = 1;

Short s2 = s1;

s1++;

System.out.println(s1 == s2);

还是true吗?No。这次输出成了false。

WHY?难道s1和s2引用的不是同一个对象吗?有这些疑问的说明你对自己主动装箱拆箱的过程还不是非常清楚。实际上上面的代码能够翻译为以下的代码(实际执行过程,要掌握):Short s1 = new Short((short)1);

Short s2 = s1;

short tempS1 = s1.shortValue();

tempS1++;

s1 = new Short(tempS1);

System.out.println(s1 == s2);

哦,原来如此,这下明确了。因此我们在使用自己主动装箱的时候小心点为妙。

4. 你自以为是的异常

先来两句代码:NullTest myNullTest = null;

System.out.println(myNullTest.getInt());

相信非常多人看到这段代码时。都会自以为是的说:NullPointerException。果真如此吗?你还没看到NullTest 这个类是怎样定义的呢。

如今看看这个类的定义:class NullTest {

public static int getInt() {

return 1;

}

}

因为getInt()是静态方法,他只和类相关,和详细的对象无关,类完毕载入时,就可以通过类名.getInt()进行调用。因此这里就算对象实例为NULL也会正常输出1.

记住:类变量和类方法的使用,只依赖引用的类型。即使引用为null,仍然能够调用。从良好实践的角度来看,明智的做法是使用NullTest.getInt()来取代myNullTest.getInt(),但谁不不能保证不会碰到这种代码。因此还是小心为妙。

5. 变长參数和数组,怎样变通?

变长參数特性带来了一个强大的概念,能够帮助开发人员简化代码。

只是变长參数的背后是什么呢?Basically,就是一个数组。public void calc(int... myInts) {}

calc(1, 2, 3);

编译器会将前面的代码翻译成相似这样:int[] ints = {1, 2, 3};

calc(ints);

只是这里有两点须要注意:当心空调用语句,这相当于传递了一个null作为參数。

calc();

等价于

int[] ints = null;

calc(ints);

当然,以下的代码会导致编译错误,因为两条语句是等价的:

public void m1(int[] myInts) { ... }

public void m1(int... myInts) { ... }

參考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值