类型转换与文字赋值

Type cast vs literal assignment

考虑以下因素:

class TypeCast {
    public static void main(String[] args) {
        byte by = 4;   // Compiler casts int literal to byte
        int in = 4;
        byte byt = in; // Compilation Error: compiler can not cast automatically. WHY?
    }
}

我知道编译器可以在文字赋值的情况下进行缩小。但是当赋值涉及变量而不是文字时,它不能做同样的事情。为什么?

编辑:我认为大多数人无法理解我想问的问题。这不是分配 'out-of-range' 值,而是将 'in-range' 值分配给 byte 并让编译器负责缩小范围。很明显 'byte' 将无法处理超出范围的值,并且需要进行显式转换(这不是我想知道的)。

给定值落在 byte 范围内,int 文字赋值给 byteint 类型变量赋值给 byte 有什么区别?

byte by = 4 是特例。没有涉及 "cast",例如只允许恰好在字节范围 -128 到 127 内的整数值...

尝试使用超出此范围的值,您会得到同样的错误

byte small = -128;    // <== OK
byte big = 127;       // <== OK
byte tooSmall = -129; // <== error: Type mismatch: cannot convert from int to byte
byte tooBig = 128;    // <== error: Type mismatch: cannot convert from int to byte

恕我直言,主要原因是这样的代码(实际上无法编译)

  int in = ...   // what if in == 1234?;
  byte byt = in; // then byt == -46. Can you expect this?

危险的 ,因为潜在的 溢出 (int 1234 变成 -46 字节)。然而,

  byte byt = 4; 

安全的因为像

这样的非法(溢出)代码
  byte byt = 1234; // doesn't compile   

会导致编译时错误。你可以坚持,但是:

  // I'm warned about the overflow, but do as I command...
  byte byt = (byte) 1234; // -46

  int in = ...
  byte byt = (byte) in; // I know what I'm doing! Cast it, please 

因为将 int 分配给 byte 通常没有意义;编译器应该在这种语句上失败。

编译器接受将文字整数值分配给字节变量的原因是它可以(并且确实)在编译时验证该分配,因此它是完全安全的,并且实际上不需要任何类型的 "cast" 完全没有。如果赋值无效,编译器将失败:

bash$ qjava 'byte b = 128;'
...\QJava.java:4: error: incompatible types: possible lossy conversion from int to byte
    byte b = 128;
             ^
1 error

因为在您的代码中您可以更改变量的值。这就是为什么不允许将 int 变量分配给字节的原因,但是如果您将 int 变量声明为 final 它将允许尝试这个:

 public class Test {
    public static void main(String[] args) {
       final int i = 10;
       byte by = i;
    }
 }

这意味着10在字节范围内,所以一切都很好,但是如果你写

public class Test {
   public static void main(String[] args) {
      final int i = 10000;
      byte by = i;
   }
 }

会报错,因为10000不在一个字节的范围内

你的字节只能表示-128 <= X <= 127。

一个字节是8位。其中第一位是符号,0(正)或 1(负)。

对于正数,其他七位代表二进制数。

零是00000000。127是01111111。

对于底片,它使用名为 two's complement 的系统。

二进制补码 10000000 表示 -128,没有另一个零。

如果 C# 包含字节文字类型,并定义了布尔运算符 (Byte | Byte)、(Byte ^ Byte)、(Byte & Int64)、(Int64 & Byte)、(Byte & UInt64) 和(UInt64 & Byte) 在给定指定的操作数时产生字节结果,那么该语言可以合理地要求想要将某些内容存储到 Byte 中的代码应该使用类型 Byte 的表达式。然而,该语言的创造者大概认为,为短于 Int32 的类型添加真正支持的好处不足以证明成本是合理的,因此它产生的表达式种类很少小于 Int32 =].

考虑到将文字值赋给短变量非常这一事实,因为 C# 没有其他处理此类事情的明智方法,该语言允许整数常量要隐式转换为 Byte 的范围 0 到 255。类型系统设计中没有任何暗示这种行为的东西——它基本上是处理最常见情况的一种方法,在这种情况下,缺乏适当的字节类型支持会造成很大的麻烦。