原始类型“short” - 在 Java 中进行转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/477750/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 15:08:40  来源:igfitidea点击:

Primitive type 'short' - casting in Java

javacastingprimitiveshort

提问by user42155

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

我有一个关于shortJava 中原始类型的问题。我正在使用 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:

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

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

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

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+bb 转换为int. 以下工作正常:

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.

我在设计一个类时发现了这一点,我需要添加两个类型为 short 的变量,编译器希望我进行强制转换。如果我使用两个 type 变量执行此操作int,则不需要强制转换。

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

一个小小的评论:同样的事情也会发生在原始类型上byte。所以,这有效:

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 shortand bytevalues.

对于long, float, double, 和int,不需要强制转换。只为shortbyte值。

回答by Darron

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.

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

回答by Rik

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.

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

回答by VonC

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

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

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

存在从 short 到 int、long、float、double 或 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 和 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.

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

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" ?

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

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 e?cient 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语言规范定义究竟如何整数来表示,如何整数算术表达式进行评估。这是 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 is the only unsigned integer type. Its values represent Unicode characters, from \u0000to \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.

Char 是唯一的无符号整数类型。它的值代表 Unicode 字符,从\u0000\uffff,即从 0 到 2 16?1。

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

[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]

[来自理论计算机科学中的电子笔记 82 No. 2 (2003)
Blesner-Blech-COCV 2003:Sabine GLESNER, Jan Olaf BLECH,
Fakult?t für Informatik,
Universit?t Karlsruhe
Karlsruhe, Germany]

回答by Jon Skeet

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

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

Section 4.2.2 of the Java Language Specificationstates:

Java 语言规范的第 4.2.2 节指出:

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)

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

    [...]

  • 数值运算符,产生 int 或 long 类型的值:
  • [...]
  • 加法运算符 + 和 -(第 15.18 节)

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

    换句话说,它就像 C# - 加法运算符(当应用于整数类型时)只会导致intor long,这就是您需要强制转换以分配给short变量的原因。

    Original answer (C#)

    原始答案(C#)

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

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

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

    这些在 C# 3.0 规范的第 7.7.4 节中。此外,定义了十进制加法:

    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.

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

    回答by kdgregory

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

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

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

    首先,“默认”并不是真正正确的术语(尽管足够接近)。正如 VonC 所指出的,由 int 和 long 组成的表达式将产生 long 结果。由整数/日志和双精度组成的操作将产生双精度结果。编译器将表达式的项提升为在结果中提供更大范围和/或精度的任何类型(假定浮点类型具有比整数更大的范围和精度,尽管将大 long 转换为 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 仅使用整数值并使用整数数学运算执行,即使整个表达式涉及双精度。结果不是你所期望的......

    (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.

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

    "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 18for each type (ie, 36 total between integer and long), not counting conversion operators.

    “字节码”,顾名思义,使用单个字节来指定操作。例如iadd,它添加了两个整数。目前,定义了 205 个操作码,整数数学计算每种类型需要18 个(即 integer 和 long 之间总共 36 个),不包括转换运算符。

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

    如果简短,并且每个字节都有自己的一组操作码,那么您将达到 241,从而限制了 JVM 的扩展能力。正如我所说,没有提到支持我这一点,但我怀疑 Gosling 等人说“人们实际上多久使用一次短裤?” 另一方面,将 byte 提升为 int 会导致这种不太好的效果(预期答案是 96,实际是 -16):

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

    回答by kdgregory

    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...

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

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

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

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

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

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

    空头 a = 32767; 短 b = 32767; 短 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

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

    回答by Jaime Hablutzel

    In java, every numeric expression like:

    在java中,每个数字表达式都像:

    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.

    如果加法元素之一是 long,则 x 将始终至少是 int 或 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
    

    回答by Rushikesh Garadade

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

    任何低于“int”(布尔值除外)的数据类型都会隐式转换为“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.

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

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

    short,byte,char——对于所有这些我们都会得到同样的错误。

    回答by Andreas Mennel

    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.

    Java 总是使用至少 32 位值进行计算。这是由于 1995 年引入 java 时常见的 32 位体系结构。CPU 中的寄存器大小为 32 位,算术逻辑单元接受 2 个 cpu 寄存器长度的数字。因此,CPU 针对这些值进行了优化。

    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.

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

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

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

    回答by snr

    AFAIS, nobody mentions of finalusage for that. If you modify your last example and define variables a and b as finalvariables, then the compiler is assuredthat 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:

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

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