提问人:Honza Brabec 提问时间:1/3/2012 最后编辑:cellepoHonza Brabec 更新时间:7/5/2023 访问量:316417
为什么 Java 的 +=、-=、*=、/= 复合赋值运算符不需要将 long 转换为 int?
Why don't Java's +=, -=, *=, /= compound assignment operators require casting long to int?
问:
直到今天,我还以为:
i += j;
只是以下方面的捷径:
i = i + j;
但是,如果我们尝试这样做:
int i = 5;
long j = 8;
然后不会编译,但会编译得很好。i = i + j;
i += j;
这是否意味着实际上这是这样的事情的捷径?i += j;
i = (type of i) (i + j)
答:
与这些问题一样,JLS拥有答案。在本例中为 §15.26.2 复合赋值运算符。摘录:
形式的复合赋值表达式等价于 ,其中 是 的类型,只不过只计算一次。
E1 op= E2
E1 = (T)((E1) op (E2))
T
E1
E1
引自 §15.26.2 的示例
[...]以下代码正确:
short x = 3; x += 4.6;
并导致 x 的值为 7,因为它等价于:
short x = 3; x = (short)(x + 4.6);
换句话说,你的假设是正确的。
评论
i+=j
i += j
i = i + j
)
您需要从 to 强制转换,以防万一,它将编译并给出正确的输出。喜欢long
int
explicitly
i = i + l
i = i + (int)l;
或
i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.
但是,在这种情况下,它工作正常,因为运算符隐式地执行从右变量类型到左变量类型的类型转换,因此不需要显式转换。+=
评论
int
+
long
int
很好的问题。Java 语言规范证实了您的建议。
例如,以下代码是正确的:
short x = 3; x += 4.6;
并导致 x 的值为 7,因为它等价于:
short x = 3; x = (short)(x + 4.6);
评论
double->float
float
double
double
float
float->double
是的
基本上当我们写
i += l;
编译器将其转换为
i = (int) (i + l);
我刚刚检查了文件代码。.class
知道真的是一件好事。
评论
这种强制转换的一个很好的例子是使用 *= 或 /=
byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57
或
byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40
或
char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'
或
char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'
评论
A
;)
ch += 32
这里的问题涉及类型转换。
当您添加 int 和 long 时,
- int 对象被强制转换为 long 并且两者都被添加,你会得到一个 long 对象。
- 但是 long 对象不能隐式转换为 int。所以,你必须明确地这样做。
但是以这样一种方式进行编码,即它进行类型转换。+=
i = (int) (i + m)
在 Java 中,当赋值操作右侧的表达式类型可以安全地提升为赋值左侧的变量类型时,会自动执行类型转换。因此,我们可以安全地分配:
byte -> short -> int -> long -> float -> double.
反之亦然。例如,我们不能自动将 long 转换为 int,因为第一个比第二个需要更多的存储空间,因此信息可能会丢失。为了强制这样的转换,我们必须进行明确的转换。
类型 - 转换
评论
long
float
float
int
double
long
double d=33333333+1.0f;
float
int
有时,这样的问题可以在面试中被问到。
例如,当您编写:
int a = 2;
long b = 3;
a = a + b;
没有自动排版。在 C++ 中,编译上述代码不会有任何错误,但在 Java 中,您将得到类似 .Incompatible type exception
因此,为了避免这种情况,您必须像这样编写代码:
int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
评论
op
主要区别在于,没有进行类型转换,因此编译器会因为没有类型转换而对你生气。但是,它真正要做的是将类型转换为与 兼容的类型。所以如果你这样做a = a + b
a += b
b
a
int a = 5;
long b = 10;
a += b;
System.out.println(a);
你真正在做的是:
int a = 5;
long b = 10;
a = a + (int) b;
System.out.println(a);
评论
微妙的一点在这里......
when 是 double 并且是 int 有一个隐式类型转换。
Java 总是在整数之间进行运算时将整数转换为双精度值。i+j
j
i
为了澄清其中是整数,是双精度,可以描述为i+=j
i
j
i = <int>(<double>i + j)
请参阅:隐式强制转换的此说明
为清楚起见,在这种情况下,您可能希望键入 to。j
(int)
评论
int someInt = 16777217; float someFloat = 0.0f; someInt += someFloat;
someInt
someInt
float
Java 语言规范将 E1 op= E2 定义为等价于 E1 = (T) ((E1) op (E2)),
其中 T
是 E1 的一种类型,并且 E1
被计算一次。
这是一个技术性的答案,但你可能想知道为什么会这样。好吧,让我们考虑以下程序。
public class PlusEquals {
public static void main(String[] args) {
byte a = 1;
byte b = 2;
a = a + b;
System.out.println(a);
}
}
这个程序打印什么?
你猜到3了吗?太糟糕了,这个程序无法编译。为什么?好吧,碰巧在 Java 中定义了字节的添加以返回一个 int
。我相信这是因为 Java 虚拟机没有定义字节操作来节省字节码(毕竟字节码的数量有限),而是使用整数操作是语言中公开的实现细节。
但是,如果不起作用,则意味着如果将其定义为 ,则永远不会对字节起作用。正如前面的例子所表明的,情况确实如此。作为使 operator 为 bytes 和 short 工作的 hack,涉及隐式转换。这并不是一个伟大的黑客,但在 Java 1.0 工作期间,重点是让语言从一开始就发布。现在,由于向后兼容性,Java 1.0 中引入的这个 hack 无法删除。a = a + b
a += b
E1 += E2
E1 = E1 + E2
+=
与这些问题一样,JLS拥有答案。在本例中为 §15.26.2 复合赋值运算符。摘录:
E1 op= E2 形式的复合赋值表达式等价于 E1 = (T)((E1) op (E2)),其中 T 是 E1 的类型,只是 E1 只计算一次。
引自 §15.26.2 的示例
[...]以下代码正确:
short x = 3;
x += 4.6;
并导致 x 的值为 7,因为它等价于:
short x = 3;
x = (short)(x + 4.6);
换句话说,你的假设是正确的。
评论
i+=(long)j;
i += (int) f;
(int) i += f;