原始类型“短”; - 用 Ja​​va 进行铸造

发布于 2024-07-12 07:15:02 字数 1016 浏览 13 评论 0原文

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

如果我有以下内容:

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

编译器不想编译 - 它说它“无法从 int 转换为 Short”并建议我将其强制转换为 short,所以这:

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

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

如果我对原始类型 int 执行相同的操作,则不需要将 aa+bb 转换为 int。 以下工作正常:

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;

对于 longfloatdoubleint,没有需要施放。 仅适用于 shortbyte 值。

I have a question about the primitive type short in Java. I am using JDK 1.6.

If I have the following:

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

the compiler does not want to compile - it says that it "cannot convert from int to short" and suggests that I make a cast to short, so this:

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

really works. But my question is why do I need to cast? The values of a and b are in the range of short - the range of short values is {-32,768, 32767}.
I also need to cast when I want to perform the operations -, *, / (I haven't checked for others).

If I do the same for primitive type int, I do not need to cast aa+bb to int. The following works fine:

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

I discovered this while designing a class where I needed to add two variables of type short, and the compiler wanted me to make a cast. If I do this with two variables of type int, I don't need to cast.

A small remark: the same thing also happens with the primitive type byte. So, this works:

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

but this not:

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

For long, float, double, and int, there is no need to cast. Only for short and byte values.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

冷情 2024-07-19 07:15:02

short C# 中所述(也适用于其他语言编译器,如 Java)

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

您无法将较大存储大小的非文字数值类型隐式转换为较短存储大小(有关整数类型的存储大小,请参阅整数类型表)。 例如,考虑以下两个短变量 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 字符,从 \u0000\uffff,即从 0 到 216−1。

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

[摘自《理论计算机科学电子笔记》82期第2期(2003)
Blesner-Blech-COCV 2003:Sabine GLESNER,Jan Olaf BLECH ,
信息学院,
卡尔斯鲁厄大学
德国卡尔斯鲁厄]

As explained in short C# (but also for other language compilers as well, like Java)

There is a predefined implicit conversion from short to int, long, float, double, or decimal.

You cannot implicitly convert nonliteral numeric types of larger storage size to short (see Integral Types Table for the storage sizes of integral types). Consider, for example, the following two short variables x and y:

short x = 5, y = 12;

The following assignment statement will produce a compilation error, because the arithmetic expression on the right-hand side of the assignment operator evaluates to int by default.

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

To fix this problem, use a cast:

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

It is possible though to use the following statements, where the destination variable has the same storage size or a larger storage size:

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

A good follow-up question is:

"why arithmetic expression on the right-hand side of the assignment operator evaluates to int by default" ?

A first answer can be found in:

Classifying and Formally Verifying Integer Constant Folding

The Java language specification defines exactly how integer numbers are represented and how integer arithmetic expressions are to be evaluated. This is an important property of Java as this programming language has been designed to be used in distributed applications on the Internet. A Java program is required to produce the same result independently of the target machine executing it.

In contrast, C (and the majority of widely-used imperative and
object-oriented programming languages) is more sloppy and leaves many important characteristics open. The intention behind this inaccurate language
specification is clear. The same C programs are supposed to run on a 16-bit,
32-bit, or even 64-bit architecture by instantiating the integer arithmetics of
the source programs with the arithmetic operations built-in in the target processor. This leads to much more efficient code because it can use the available
machine operations directly. As long as the integer computations deal only
with numbers being “sufficiently small”, no inconsistencies will arise.

In this sense, the C integer arithmetic is a placeholder which is not defined exactly
by the programming language specification but is only completely instantiated by determining the target machine.

Java precisely defines how integers are represented and how integer arithmetic is to be computed.

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

Char is the only unsigned integer type. Its values represent Unicode characters, from \u0000 to \uffff, i.e. from 0 to 216−1.

If an integer operator has an operand of type long, then the other operand is also converted to type long. Otherwise the operation is performed on operands of type int, if necessary shorter operands are converted into int. The conversion rules are exactly specified.

[From Electronic Notes in Theoretical Computer Science 82 No. 2 (2003)
Blesner-Blech-COCV 2003: Sabine GLESNER, Jan Olaf BLECH,
Fakultät für Informatik,
Universität Karlsruhe
Karlsruhe, Germany]

向日葵 2024-07-19 07:15:02

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

Java 语言规范第 4.2.2 节 规定:

Java 编程语言提供
一些操作符
积分值:

[...]

  • 数字运算符,其结果
    int 或 long 类型的值:
  • [...]
  • 加法运算符 + 和
    - (§15.18)

  • 换句话说,它就像 C# - 加法运算符(当应用于整数类型时)只会产生 intlong,这就是为什么您需要强制转换才能分配给一个变量。

    原始答案 (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);
    

    这里还定义了枚举加法、字符串连接和委托组合。)

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

    EDIT: Okay, now we know it's Java...

    Section 4.2.2 of the Java Language Specification states:

    The Java programming language provides
    a number of operators that act on
    integral values:

    [...]

  • The numerical operators, which result
    in a value of type int or long:

  • [...]
  • The additive operators + and
    - (§15.18)

  • In other words, it's like C# - the addition operator (when applied to integral types) only ever results in int or long, which is why you need to cast to assign to a short variable.

    Original answer (C#)

    In C# (you haven't specified the language, so I'm guessing), the only addition operators on primitive types are:

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

    These are in the C# 3.0 spec, section 7.7.4. In addition, decimal addition is defined:

    decimal operator +(decimal x, decimal y);
    

    (Enumeration addition, string concatenation and delegate combination are also defined there.)

    As you can see, there's no short operator +(short x, short y) operator - so both operands are implicitly converted to int, and the int form is used. That means the result is an expression of type "int", hence the need to cast.

    眉目亦如画i 2024-07-19 07:15:02

    在 C# 和 Java 中,赋值右侧的算术表达式默认计算结果为 int。 这就是为什么您需要转换回short,因为出于显而易见的原因,没有从int到short的隐式转换。

    In C# and Java, the arithmatic expression on the right hand side of the assignment evaluates to int by default. That's why you need to cast back to a short, because there is no implicit conversion form int to short, for obvious reasons.

    泼猴你往哪里跑 2024-07-19 07:15:02

    鉴于“为什么默认为 int”问题尚未得到解答......

    首先,“默认”并不是真正正确的术语(尽管足够接近)。 正如 VonC 所指出的,由 int 和 long 组成的表达式将产生 long 结果。 由整数/对数和双精度组成的运算将产生双精度结果。 编译器将表达式的项提升为在结果中提供更大范围和/或精度的任何类型(假定浮点类型比整数具有更大的范围和精度,尽管将大长整型转换为双精度确实会损失精度)。

    需要注意的是,此促销活动仅适用于需要它的条款。 因此,在下面的示例中,子表达式 5/4 仅使用整数值并使用整数数学执行,即使整个表达式涉及双精度数。 结果不是你所期望的......

    (5/4) * 1000.0
    

    好吧,那么为什么 byte 和 Short 被提升为 int 呢? 没有任何参考资料来支持我,这是由于实用性:字节码的数量有限。

    “字节码”,顾名思义,使用单个字节来指定操作。 例如iadd,它将两个整数相加。 目前,定义了 205 个操作码,并且整数对于每种类型(即整数和长整型之间总共 36 个),不包括转换运算符。

    如果 Short 和 byte 都有自己的一组操作码,那么您将处于 241,从而限制了 JVM 扩展的能力。 正如我所说,没有任何参考资料支持我的观点,但我怀疑高斯林等人说过“人们实际上多久穿一次短裤?” 另一方面,将 byte 提升为 int 会导致这种不太好的效果(预期答案是 96,实际是 -16):

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

    Given that the "why int by default" question hasn't been answered ...

    First, "default" is not really the right term (although close enough). As noted by VonC, an expression composed of ints and longs will have a long result. And an operation consisting of ints/logs and doubles will have a double result. The compiler promotes the terms of an expression to whatever type provides a greater range and/or precision in the result (floating point types are presumed to have greater range and precision than integral, although you do lose precision converting large longs to double).

    One caveat is that this promotion happens only for the terms that need it. So in the following example, the subexpression 5/4 uses only integral values and is performed using integer math, even though the overall expression involves a double. The result isn't what you might expect...

    (5/4) * 1000.0
    

    OK, so why are byte and short promoted to int? Without any references to back me up, it's due to practicality: there are a limited number of bytecodes.

    "Bytecode," as its name implies, uses a single byte to specify an operation. For example iadd, which adds two ints. Currently, 205 opcodes are defined, and integer math takes 18 for each type (ie, 36 total between integer and long), not counting conversion operators.

    If short, and byte each got their own set of opcodes, you'd be at 241, limiting the ability of the JVM to expand. As I said, no references to back me up on this, but I suspect that Gosling et al said "how often do people actually use shorts?" On the other hand, promoting byte to int leads to this not-so-wonderful effect (the expected answer is 96, the actual is -16):

    byte x = (byte)0xC0;
    System.out.println(x >> 2);
    
    坚持沉默 2024-07-19 07:15:02

    您使用什么语言?

    许多基于 C 的语言都有一个规则,即任何数学表达式都以 int 或更大的大小执行。 因此,一旦添加两个 Shorts,结果就是 int 类型。 这导致需要演员。

    What language are you using?

    Many C based languages have a rule that any mathematical expression is performed in size int or larger. Because of this, once you add two shorts the result is of type int. This causes the need for a cast.

    静赏你的温柔 2024-07-19 07:15:02

    Java 始终使用至少 32 位值进行计算。 这是由于 1995 年 Java 推出时常见的 32 位架构所致。 CPU中的寄存器大小为32位,算术逻辑单元接受CPU寄存器长度的2个数字。 因此 CPU 针对这些值进行了优化。

    这就是为什么所有支持算术运算且小于 32 位的数据类型在使用它们进行计算时都会立即转换为 int(32 位)。

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

    Java always uses at least 32 bit values for calculations. This is due to the 32-bit architecture which was common 1995 when java was introduced. The register size in the CPU was 32 bit and the arithmetic logic unit accepted 2 numbers of the length of a cpu register. So the cpus were optimized for such values.

    This is the reason why all datatypes which support arithmetic opperations and have less than 32-bits are converted to int (32 bit) as soon as you use them for calculations.

    So to sum up it mainly was due to performance issues and is kept nowadays for compatibility.

    离鸿 2024-07-19 07:15:02

    在 java 中,每个数字表达式(例如:

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

    x)将始终至少是一个 int,或者如果其中一个加法元素是 long,则结果是 long。

    但有一些怪癖很难

    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
    

    In java, every numeric expression like:

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

    x will always result to be at least an int, or a long if one of the addition elements was a long.

    But there's are some quirks tough

    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
    
    半窗疏影 2024-07-19 07:15:02

    AFAIS,没有人提到最终的用法。 如果您修改最后一个示例并将变量 a 和 b 定义为 final
    变量,那么编译器确信它们的总和值 5 可以分配给
    byte 类型的变量,没有任何精度损失。 在这种情况下,编译器是好的
    将 a 和 b 的总和分配给 c 。 这是修改后的代码:

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

    AFAIS, nobody mentions of final usage for that. If you modify your last example and define variables a and b as final
    variables, then the compiler is assured that their sum, value 5 , can be assigned to a
    variable of type byte, without any loss of precision. In this case, the compiler is good
    to assign the sum of a and b to c . Here’s the modified code:

    final byte a = 2;
    final byte b = 3;
    byte c = a + b;
    
    最偏执的依靠 2024-07-19 07:15:02

    任何低于“int”的数据类型(布尔值除外)都会隐式转换为“int”。

    在您的情况下:

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

    (a+b) 的结果被隐式转换为 int 。 现在您将其分配给“short”。这样您就会收到错误。

    Short、byte、char——对于所有这些我们都会得到相同的错误。

    Any data type which is lower than "int" (except Boolean) is implicitly converts to "int".

    In your case:

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

    The result of (a+b) is implicitly converted to an int. And now you are assigning it to "short".So that you are getting the error.

    short,byte,char --for all these we will get same error.

    只有一腔孤勇 2024-07-19 07:15:02

    我想补充一些没有指出的内容。 Java 不考虑您在...

    short a = 2; 中给定变量(2 和 3)的值。
    短b=3;
    短c = a + b;

    据 Java 所知,你可以这样做...

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

    这超出了short的范围,它会将结果自动装箱为int,因为结果“可能”大于short但不大于int。 选择 Int 作为“默认值”是因为基本上大多数人不会对高于 2,147,483,647 或低于 -2,147,483,648 的值进行硬编码

    I'd like to add something that hasn't been pointed out. Java doesn't take into account the values you have given the variables (2 and 3) in...

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

    So as far as Java knows, you could done this...

    short a = 32767;
    short b = 32767;
    short c = a + b;

    Which would be outside the range of short, it autoboxes the result to an int becuase it's "possible" that the result will be more than a short but not more than an int. Int was chosen as a "default" because basically most people wont be hard coding values above 2,147,483,647 or below -2,147,483,648

    隔岸观火 2024-07-19 07:15:02

    如果两个值具有不同的数据类型,那么java会自动将其中一个值提升为两种数据类型中较大的一个。 在您的情况下,较小的数据类型(例如 byte、short 和 char)在与二进制算术运算符一起使用时将被“提升”为 int。 如果两个操作数都不是 int,这仍然成立。

    short x = 10;
    short y = 20;
    short z = x+y // this will be a compiler error. To solve this then casting would be required
    short z = (short)(x+y) // this will return 30
    short z = (short) x+y //this will return a compiler error
    

    请记住,转换是一元运算符,因此通过将较大的值转换为较小的数据类型,您可以有效地告诉编译器忽略默认行为。

    If two values have different data types, then java will automatically promote one of the values to the larger of the two data types. In your case, smaller data types such as byte, short and char will be "promoted" to int anytime they are used with a binary arithmetic operator. This is still true if neither operands are an int.

    short x = 10;
    short y = 20;
    short z = x+y // this will be a compiler error. To solve this then casting would be required
    short z = (short)(x+y) // this will return 30
    short z = (short) x+y //this will return a compiler error
    

    Remember that casting is a unary operator, thus by casting a larger value into a smaller datatype, you are effectively telling the compiler to ignore the default behaviour.

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文