5

我正在为 SCJP 考试而学习,但遇到了一个我无法真正解决的问题。

这本书说你不能先加宽然后装箱,但你可以装箱然后加宽。无法装箱的示例是期望 Long 的方法和使用字节调用的方法。

他们的解释是:

想一想……如果它首先尝试装箱,则该字节将被转换为字节。现在我们回到尝试将 Byte 扩展为 Long,当然,IS-A 测试失败了。

但这听起来像盒子然后加宽而不是加宽然后盒子给我。

任何人都可以为我澄清整个盒子并加宽与加宽和盒子,因为就目前而言,这本书在这个问题上并不完全清楚。

编辑:澄清一下:我说的是 SCJP sun 认证的 Java 6 程序员的第 252 页和第 253 页。 http://books.google.be/books?id=Eh5NcvegzMkC&pg=PA252#v=onepage&q&f=false

4

5 回答 5

4

语言混乱。

基本上你不能采用这种方式:
byte -> Byte -> Long
因为 Byte 和 Long 不共享 is-a 关系。
因此,它尝试这样做:
字节 -> 长 -> 长
但它也不能这样做(显然是由于编译器的限制)。因此,它失败并引发错误。

但是,另一方面,您可以这样做:
字节 -> 字节 -> 对象
,因为字节是一个对象。

考虑 2 个函数和一个字节变量:

toLong (Long x)
toObject(Object x)
byte b = 5;

那么这个语句就是非法的:
toLong(b);
// 因为 b -> new Byte(b) -> new Long(new Byte(b)) 是非法的。
由于编译器的限制,AND byte -> long -> Long 无法完成。

但是这个语句是合法的:
toObject(b);
// 因为 b -> new Byte(b) -> new Object(new Byte(b)) 是合法的。

于 2010-10-31T17:22:07.540 回答
4

之所以不允许“加宽然后装箱”可能是因为以下原因(SCJP 书的第 249 页):

Java 5 的设计者决定最重要的规则应该是预先存在的代码应该按照以前的方式运行,因此由于扩展功能已经存在,通过扩展调用的方法不应该输给依赖于装箱的新创建的方法

于 2012-11-10T09:08:31.693 回答
3

基本上,这意味着扩展仅适用于原始类型,而不适用于包装器。如果你先装箱,你会得到一个包装器(byte-> Byte)。但是包装器 - 、 、 、 和Byte没有Double任何Float继承Integer关系(IS-A)。一个参数不能接受一个例子。LongShortLongByte

所以你必须先加宽(byte-> long),然后是框(long-> Long)。

于 2010-09-15T19:33:35.417 回答
1

本质上,规则是你可以先装箱然后加宽,但不能先加宽然后装箱。但是,如果装箱然后加宽,那么被加宽的类必须与您要加宽到的类位于同一继承树中。

虽然显示的示例试图先装箱然后加宽,但它无效的原因是因为 Byte 不是 Long,即它们不在同一个继承树中。但是,如果该示例使用 Byte 和 Numeric,那么您可以将 Box byte 转换为 Byte,然后将 Byte 扩展为 Numeric,因为 Byte IS-A Numeric(它们位于同一继承树中)

于 2011-01-28T08:07:05.947 回答
1

这不是扩大,因为 Byte 不适合 Long。这就是为什么它不起作用。

您可以框成一个字节,然后扩大成一个Object或一个Number

正如你的书所说:

我们又开始尝试将 Byte 扩大到 Long


在您的情况下,我想代码如下所示:

byte b = 1;
Long l = b;

b 更改为 a Byte(首先装箱)但不能更改为 aLong因为 Byte 不是Long.

在更多步骤中:

byte b = 1;
Byte byteB = b; //works
Long l = byteB; //doesn't work
于 2010-09-15T19:09:37.267 回答