基元类型“short” - Java 中的强制转换

2022-08-31 12:45:10

我有一个关于Java中基元类型的问题。我使用的是 JDK 1.6。short

如果我有以下情况:

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

编译器不想编译 - 它说它“不能从int转换为短”,并建议我进行强制转换,所以这样:short

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

真的有效。但我的问题是,为什么我需要施法?a 和 b 的值在 - 短值的范围是 {-32,768, 32767} 的范围内。当我想执行操作时,我还需要强制转换 -, *, / (我还没有检查其他人)。short

如果我对基元类型做同样的事情,我不需要将aa + bb转换为。以下工作正常:intint

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

我在设计一个类时发现了这一点,我需要添加两个 short 类型的变量,编译器希望我进行强制转换。如果我用两个类型的变量来做这件事,我不需要强制转换。int

一个小问题:基元类型也发生了同样的事情。所以,这有效:byte

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

但这不是:

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

对于 、 、 和 ,不需要强制转换。仅 for 和 值。longfloatdoubleintshortbyte


答案 1

正如C#中所解释的那样(也适用于其他语言编译器,如Java)

有一个预定义的隐式转换,从短整型到整型、长整型、浮点型、双精度型或十进制数。

不能将存储大小较大的非文字数值类型隐式转换为 short(有关整数类型的存储大小,请参见整数类型表)。例如,考虑以下两个短变量 x 和 y:

short x = 5, y = 12;

下面的赋值语句将产生编译错误,因为赋值运算符右侧的算术表达式的计算结果默认为 int。

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

要解决此问题,请使用强制转换:

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

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

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

一个好的后续问题是:

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

第一个答案可以在以下位置找到:

分类和正式验证整数常数折叠

Java 语言规范精确定义了整数的表示方式以及如何计算整数算术表达式。这是Java的一个重要属性,因为这种编程语言被设计为用于Internet上的分布式应用程序。Java 程序需要独立于执行它的目标机器生成相同的结果

相比之下,C(以及大多数广泛使用的命令式和面向对象的编程语言)更加草率,并留下了许多重要的特征。这种不准确的语言规范背后的意图是显而易见的。相同的 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 是唯一的无符号整数类型。其值表示 Unicode 字符,从 到 ,即从 0 到 216−1。\u0000\uffff

如果整数运算符的操作数为 long 类型,则另一个操作数也将转换为 long 类型。否则,将在 int 类型的操作数上执行操作,如有必要,将较短的操作数转换为 int。转换规则已精确指定。

[摘自《理论计算机科学电子笔记》第82期(2003年)
Blesner-Blech-COCV 2003:Sabine GLESNER,Jan Olaf BLECH,
Fakultät für Informatik,
Karlsruhe Karlsruhe
大学,德国]


答案 2

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

Java 语言规范的第 4.2.2 节规定:

Java 编程语言提供了许多作用于整数值的运算符:

[...]

  • 数值运算符,用于生成 int 或 long 类型的值:
  • [...]
  • 加法运算符 + 和 - (§15.18)
  • 换句话说,它就像C#一样 - 加法运算符(当应用于整数类型时)只产生或,这就是为什么你需要强制转换为分配给变量的原因。intlongshort

    原始答案 (C#)

    在 C# 中(您尚未指定语言,因此我猜),基元类型上唯一的加法运算符是:

    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);
    

    (枚举加法、字符串串联和委托组合也在此处定义。

    如您所见,没有运算符 - 因此两个操作数都隐式转换为 int,并使用 int 形式。这意味着结果是类型“int”的表达式,因此需要强制转换。short operator +(short x, short y)