通过阅读一本名为1Z0-803的书,我正在为Java SE 7程序员I考试(OCA Java SE 7 Programmer I Certification Guide)做准备。尽管作者在Java编程方面有12年的经验,并且尽管有技术校对员,但可能是薪水,但本书中存在大量的缺陷。
但有一件事让我感到不安全。作者在第168页说这句话是正确的:
如果方法的返回类型为
int
,则该方法可以返回一个值 类型为byte
。
我说的不同,需要你的帮助。以这段代码为例:
public static void main(String[] args)
{
// This line won't compile ("possible loss of precision"):
byte line1 = returnByte();
// compiles:
int line2 = returnByte();
// compiles too, we "accept" the risk of precision loss:
byte line3 = (byte) returnByte();
}
public static int returnByte()
{
byte b = 1;
return b;
}
显然,编译器不会在returnByte()
方法签名中抱怨不同的返回类型int,以及我们在方法实现结束时实际返回的内容:一个字节。该字节比int(32)使用更少的位(8),并且将被转换为int而不存在精度损失的风险。但返回值 ,总是整数!还是我错了?你在考试中会得到什么回答?
我不完全确定实际的返回类型是什么,因为书中的这句话被认为是真的。 是否在我们的方法实现结束时发生了强制转换,或者在赋值之前是否在主方法中发生了强制转换?
在现实世界中,只要人们理解隐式演员和失去精确度的风险,这个问题就不重要了。但由于这只是考试中可能出现的问题之一,我很想知道问题的技术上正确答案。
大多数答案似乎都认为我想知道是否可以将byte
投射到int
然后会发生什么。嗯,这不是问题。我问的是返回的类型是什么。换句话说,作者引用的陈述是对还是错?在返回的实际返回的之前或之后是否发生了对int的强制转换?如果这是真正的考试,你会有问题,你会回答什么?
请参阅我的代码段中的第1行。如果作者说的是对的,该行将被编译,因为返回的值将是一个字节。但是它没有编译,类型提升的规则说如果我们试图将int压缩到一个字节中,我们就会冒失去精度的风险。对我来说,这证明了返回的值是一个整数。
答案 0 :(得分:1)
是的,你可以这样做。
byte
表达式的值将在返回之前提升为int
。
实际的返回类型与方法签名中声明的一样 - int
。
IMO,这本书的作者写的或多或少是正确的。当你“返回一个字节”时,他只是在解释有关return
语句中发生的字节到整数提升的内容。
是否在我们的方法实现结束时发生了强制转换,或者在赋值之前是否在主方法中发生了强制转换?
演员(推广)发生在returnByte
方法中。
在现实世界中,只要理解隐式演员和失去精确度的风险,这个问题就不重要了。
将byte
推广到int
并不会有任何精确度。如果类型不同,可能会失去精确度,但(假设)精确度的损失在推广执行的任何地方都是相同的。
处理此问题的JLS部分是JLS 14.17,它表示return
表达式必须可赋值到方法声明的返回类型。它没有明确声明促销是在方法中完成的,但它是隐含的。此外,这是实现这一目标的唯一可行方法。
如果(假设)转换是在调用方法中完成的(例如main
),那么:
return
语句正在做什么。鉴于可以单独编译Java类,这是不可能的。return
语句,其表达式具有不同的类型,则编译器需要知道将执行哪个return
。这是不可能的。如果这是真正的考试,你会有问题,你会回答什么?
我会回答......“这取决于......”并继续进行另类观点。
从技术上讲,该方法返回int
,但return
语句可以使用任何类型可以转换为int
的表达式。
但如果有人对我说这个方法正在返回byte
,我会理解他们的意思。
另外,据我所知,方法/函数使用stack.etc的堆栈,在这些堆栈中,它们存储的返回地址不是它们返回的(类型)。所以,再次出现歧义(至少对我而言)。如果我错了,请纠正我。
是的,从技术上讲,方法不会返回类型。 (即使它返回一个Type
对象也没有。这是一个表示类型的对象,而不是类型本身。)但是每个人和他的狗都乐意说“returnByte方法返回类型INT”。
所以,如果你要迂腐,那么是的,它是模棱两可的。但解决方案是不要迂腐。
答案 1 :(得分:0)
我相当肯定它与执行myInt << 24
相同,获得最后8位,因此如果整数超过255(2 ^ 8),则即将失去精度)。
答案 2 :(得分:0)
是的,该声明是有效的。 byte
将永远适合int
。
byte => int //no precision loss
int => byte //precision loss
但如果你这样做:
byte => int => byte //you won't lose any data
你在做什么。这有帮助吗?