Java中的隐式转换如何工作? [英] How does implicit conversion work in Java?

查看:50
本文介绍了Java中的隐式转换如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在Java中,整数默认是 int ,所以如果我写这样的话

I know that in Java Integer literals are int by default,so if I write something like this

byte byteValue = 2;

Java自动将文字值 2 (默认为int)转换为字节.如果我写同样的东西

Java auto converts the literal value 2(which is an int by default) to byte. And the same thing works if I write

byte byteValue = 4/2;

RHS被评估为一个整数,并隐式转换为字节.

The RHS is evaluated as an int and implicitly converted to a byte.

但是在以下两种情况下为什么不进行隐式转换?

int n1 = 4;
byte value = n1/2;

在此

byte n1 = 4;
byte value = n1/2;

我知道这两个示例的RHS都被评估为 int .但是为什么Java不会像前两种情况那样将其隐式转换为字节呢?是否只有在有文字的情况下才会隐式转换为较小的数据类型?

I know that the RHS of both these examples are evaluated as an int. But why doesn't Java convert it to a byte implicitly like it did in the first two cases.Does implicit conversion to smaller data type happen only if there are literals?

推荐答案

说明

让我们看一下您的代码和一些修改后的示例:

Explanation

Lets take a look at your code and some modified examples:

// Example 1
byte byteValue = 2;

// Example 2
byte byteValue = 4/2;

// Example 3
byte byteValue = 2000;

// Example 4
byte byteValue = 500/2;

// Example 5
int n1 = 4;
byte byteValue = n1/2;


无损转换

对于示例3 示例4 示例5 ,您将得到提到的编译时错误.


Non-lossy conversion

You will get the mentioned compile-time error for Example 3, Example 4 and Example 5.

首先,在编译时执行示例1至4的简单数学运算.因此,Java将在编译时计算 500/2 并将代码替换为基本上 byte byteValue = 250; .

First of all, the simple math you have for Example 1 to 4 is executed at compile-time. So Java will compute 500 / 2 at compile-time and replace the code with basically byte byteValue = 250;.

Java中字节的有效值为 -128 127 .因此,超出该范围的任何值都不能仅视为 byte ,而需要进行显式转换.因此,示例1 示例2 通过.

Valid values for bytes in Java are -128 to 127. So any value outside of that range can not just be taken as a byte but requires explicit conversion. Because of that, Example 1 and Example 2 pass.

要了解其余部分失败的原因,我们必须研究Java语言规范(JLS),尤其是 5.2.分配上下文.

To understand why the rest fails, we have to study the Java Language Specification (JLS), more specifically chapter 5.1.3. Narrowing Primitive Conversion and 5.2. Assignment Contexts.

它表示从 int byte 的转换(如果超出了 byte 的范围)是缩小的原始转换,并且可能会丢失信息(出于明显的原因).继续说明转换是如何完成的:

It says that a conversion from int to byte (if it is outside of the range of byte) is a narrowing primitive conversion and that it may lose information (for obvious reasons). It continues by explaining how the conversion is done:

有符号整数到整数类型T的缩小转换会简单地丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位的数量.除了可能丢失有关T的大小的信息外,数字值,这可能导致结果值的符号与输入值的符号不同.

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

从第二章开始,如果值是恒定表达式,则允许分配进行窄转换.

From the second chapter, assignments with narrow conversions are allowed if the value is a constant expression.

此外,如果表达式是 byte ,short,char或int类型的常量表达式(第15.29节):

In addition, if the expression is a constant expression (§15.29) of type byte, short, char, or int:

如果变量的类型为 byte ,short或char,并且常量表达式的值可以表示为变量的类型,则可以使用缩窄基元转换.

A narrowing primitive conversion may be used if the variable is of type byte, short, or char, and the value of the constant expression is representable in the type of the variable.

长话短说,必须向Java明确声明可能会丢失信息(因为该值超出范围)的缩小转换.Java不仅会强迫您执行它,还会为您完成它.这是通过演员阵容完成的.

Long story short, a narrowing conversion that may lose information (because the value exceeds the range) has to explicitly be announced to Java. Java will not just do it for you without you forcing it. That is done by a cast.

例如

byte byteValue = (byte) (500 / 2);

得出值 -6 .

您的最后一个示例非常有趣:

Your last example is very interesting:

int n1 = 4;
byte byteValue = n1/2;

尽管这没有超出范围,但Java仍将其视为有损缩小转换.为什么会这样呢?

Although this does not exceed the range, Java still treats it as lossy narrowing conversion. Why is that the case?

好吧,Java无法确保在执行 n1/2 之前最后一秒未更改 n1 .因此,它必须考虑所有代码,以查看是否有人偷偷地访问了 n1 并对其进行了更改.Java在编译时不会进行这种分析.

Well, Java can not ensure 100% that n1 is not changed last second before n1/2 is executed. Therefore, it would have to consider all of your code to see if maybe someone accesses n1 sneaky and changes it. Java does not do this kind of analysis at compile-time.

因此,如果您可以告诉Java n1 保持 4 并且实际上永远都不会改变,那么它将可以编译.在这种特定情况下,将其设置为 final 就足够了.因此,

So if you can tell Java that n1 stays 4 and can actually never change, then this will actually compile. In this specific case, it would be enough to make it final. So with

final int n1 = 4;
byte byteValue = n1/2;

它实际上会编译,因为Java知道 n1 保持 4 并且不能再更改了.因此,它可以在编译时将 n1/2 计算为 2 ,并使用基本上为 byte byteValue = 2; 的代码替换该代码,该范围在范围内

it will actually compile because Java knows that n1 stays 4 and can not change anymore. Hence it can compute n1/2 at compile-time to 2 and replace the code with basically byte byteValue = 2;, which is in range.

因此,如先前在您可以在

You can check the details what it needs to have a constant expression in 15.29. Constant Expressions. Basically everything simple that can easily be computed in place without any method invocations or other fancy stuff.

这篇关于Java中的隐式转换如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆