原始types“短” – 在Java中投射

我有一个关于Java中的shorttypes的问题。 我正在使用JDK 1.6。

如果我有以下情况:

 short a = 2; short b = 3; short c = a + b; 

编译器不想编译 – 它说“它不能从int转换为short”,并build议我把一个expression式转换为short ,所以这个:

 short c = (short) (a + b); 

真的有用。 但我的问题是为什么我需要施放? a和b的值在short的范围内 – 短值的范围是{-32,768,32767}。 当我想要执行操作时,我也需要投射 – ,*,/(我没有检查过其他人)。

如果我对原始typesint做同样的操作,我不需要将aa + bb转换为int 。 以下工作正常:

 int aa = 2; int bb = 3; int cc = aa +bb; 

我在devise一个需要添加两个shorttypesvariables的类时发现了这个问题,编译器希望我做一个类。 如果我用inttypes的两个variables做这个,我不需要投。

非常感谢你提前。

小小的一句话:原始typesbyte也会发生同样的情况。 所以,这工作:

 byte a = 2; byte b = 3; byte c = (byte) (a + b); 

但是这不是:

 byte a = 2; byte b = 3; byte c = a + b; 

对于longfloatdoubleint ,不需要投射。 只用于shortbyte值。

正如C#所说的(也适用于其他语言编译器,比如Java)

从short到int,long,float,double或decimal有一个预定义的隐式转换。

您不能隐式地将较大存储大小的非文字数字types转换为较短(请参阅积分types的存储大小的“积分types表”)。 例如,考虑以下两个短variablesx和y:

 short x = 5, y = 12; 

下面的赋值语句会产生编译错误, 因为赋值运算符右侧的算术expression式默认情况下为int。

 short z = x + y; // Error: no conversion from int to short 

要解决这个问题,请使用cast:

 short z = (short)(x + y); // OK: explicit conversion 

可以使用以下语句,其中目标variables具有相同的存储大小或更大的存储大小:

 int m = x + y; long n = x + y; 

一个好的后续问题是:

“赋值运算符右侧的算术expression式为什么默认值为int”?

第一个答案可以在下面find:

整数常量折叠的分类与forms化validation

Java语言规范确切地定义了如何表示整数值以及如何评估整数算术expression式 。 这是Java的一个重要特性,因为这种编程语言被devise用于Internet上的分布式应用程序。 Java程序需要产生相同的结果,而不依赖于目标机器执行它

相比之下,C(以及大多数广泛使用的命令式和面向对象的编程语言)更为</s> and,并留下了许多重要的特性。 这个不准确的语言规范背后的意图是明确的。 通过用目标处理器内置的算术运算实例化源程序的整数运算,相同的C程序应该在16位,32位甚至64位体系结构上运行。 这导致更高效的代码,因为它可以直接使用可用的机器操作。 只要整数计算只处理“足够小”的数字,就不会出现不一致。

从这个意义上讲,C整数算术是一个占位符,它不是由编程语言规范完全定义的,而只是通过确定目标机器来完成实例化的。

Java精确地定义了如何表示整数以及如何计算整数算术。

  Java Integers -------------------------- Signed | Unsigned -------------------------- long (64-bit) | int (32-bit) | short (16-bit) | char (16-bit) byte (8-bit) | 

Char是唯一的无符号整数types。 它的值表示Unicode字符,从\u0000\uffff ,即从0到2 16 -1。

如果整型运算符的操作数types为long,那么另一个操作数也转换为longtypes。 否则,操作在inttypes的操作数上执行,如果需要,则将较短的操作数转换为int 。 转换规则是完全指定的。

[来自理论计算机科学82(2)(2003)
Blesner-Blech-COCV 2003: Sabine GLESNER ,Jan Olaf BLECH,
FakultätfürInformatik,
卡尔斯鲁厄大学
德国卡尔斯鲁厄]

编辑:好的,现在我们知道它是Java …

Java语言规范第4.2.2节规定:

Java编程语言提供了许多对整型值起作用的运算符:

[…]

  • 数值运算符,其结果是int或longtypes的值:
  • […]
  • 加法运算符+和 – (§15.18)
  • 换句话说,就像C# – 加法运算符(当应用于整型时)只会导致intlong ,这就是为什么你需要强制转换为一个shortvariables。

    原始答案(C#)

    在C#(你没有指定的语言,所以我猜),原始types的唯一的加法运算符是:

     int operator +(int x, int y); uint operator +(uint x, uint y); long operator +(long x, long y); ulong operator +(ulong x, ulong y); float operator +(float x, float y); double operator +(double x, double y); 

    这些都在C#3.0规范7.7.4节中。 另外,小数加法被定义为:

     decimal operator +(decimal x, decimal y); 

    (枚举添加,string连接和委托组合也在那里定义。)

    正如你所看到的,没有short operator +(short x, short y)操作符 – 所以两个操作数都隐式转换为int,并使用intforms。 这意味着结果是一个“int”types的expression式,因此需要强制转换。

    在C#和Java中,赋值右边的算术expression式默认为int。 这就是为什么你需要退回到一个简短的,因为没有隐式转换forms诠释为空,原因显而易见。

    鉴于“为什么int默认情况下”的问题还没有得到解答…

    首先,“违约”并不是真正的正确的条件(尽pipe足够接近)。 正如VonC所指出的,一个由ints和longs组成的expression式会有很长的结果。 而且由ints / logs和double组成的操作会有双重结果。 编译器将expression式的条件推广到任何types,从而在结果中提供更大的范围和/或精度(浮点types被认为具有比积分更大的范围和精度,尽pipe你失去了将大的long转换为double的精度)。

    一个警告是,这种促销只发生在需要它的条款。 所以在下面的例子中,子expression式5/4只使用整数值,并且使用整数math来执行,即使整个expression式涉及到一个double。 结果不是你所期望的…

     (5/4) * 1000.0 

    好的,为什么byte和short会被提升为int? 没有任何引用来支持我,这是由于实用性:字节码数量有限。

    顾名思义,“字节码”使用一个字节来指定一个操作。 例如iadd ,它增加了两个整数。 目前, 定义了205个操作码 ,每种types的整数运算需要18个 (即整数和长整数之间的总和),不包括转换运算符。

    如果short和byte每个都有自己的一组操作码,那么你将会在241,限制JVM扩展的能力。 正如我所说,没有任何提及支持我,但我怀疑高斯林等人说:“人们实际上用短裤的频率是多less? 另一方面,将字节提升为int会导致这种不太好的效果(预期的答案是96,实际是-16):

     byte x = (byte)0xC0; System.out.println(x >> 2); 

    你使用什么语言?

    许多基于C的语言都有一个规则,即任何mathexpression式的大小都是int或更大。 因此,一旦添加两条短裤,结果就是inttypes。 这导致需要演员。

    Java总是使用至less32位值进行计算。 这是由于Java引入时的1995年常见的32位架构造成的。 CPU中的寄存器大小为32位,算术逻辑单元接受了2个cpu寄存器长度的数字。 所以这个cpus已经被优化了。

    这就是为什么所有支持算术运算并且小于32位的数据types一旦用于计算就会被转换为int(32位)的原因。

    所以总结起来主要是由于性能问题,现在为了兼容性而保留下来。

    在Java中,每个数字expression式如下所示:

     anyPrimitive zas = 1; anyPrimitive bar = 3; ?? x = zas + bar 

    x总是至less是一个整数,或者如果其中一个元素是一个长整型的话。

    但是有一些怪癖困难

     byte a = 1; // 1 is an int, but it won't compile if you use a variable a += 2; // the shortcut works even when 2 is an int a++; // the post and pre increment operator work 

    任何数据types女巫都低于“int”(布尔除外)隐式转换为“int”。

    在你的情况下:

     short a = 2; short b = 3; short c = a + b; 

    (a + b)的结果隐式转换为int。 现在你把它分配给“short”。所以你得到了错误。

    短,字节,字符 – 所有这些,我们将得到同样的错误。

    AFAIS,没有人提到final用法。 如果修改了最后一个例子,并将variablesa和b定义为finalvariables,那么编译器会确保它们的总和值5可以分配给bytetypes的variables,而不会损失任何精度。 在这种情况下,编译器可以将a和b的和分配给c。 这是修改的代码:

     final byte a = 2; final byte b = 3; byte c = a + b; 

    我想添加一些未被指出的东西。 Java不考虑你赋予variables(2和3)的值…

    短a = 2; 短b = 3; 短c = a + b;

    所以据Java知道,你可以做到这一点…

    短a = 32767; 短b = 32767; 短c = a + b;

    这将超出范围之外,它会自动将结果自动复制到一个int,因为它是“可能的”,结果将超过一个简短但不超过一个整数。 Int被选为“违约”,因为基本上大多数人不会是硬编码值超过2,147,483,647或低于-2,147,483,648