类型转换与文字赋值
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
文字赋值给 byte
和 int
类型变量赋值给 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。类型系统设计中没有任何暗示这种行为的东西——它基本上是处理最常见情况的一种方法,在这种情况下,缺乏适当的字节类型支持会造成很大的麻烦。
考虑以下因素:
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
文字赋值给 byte
和 int
类型变量赋值给 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。类型系统设计中没有任何暗示这种行为的东西——它基本上是处理最常见情况的一种方法,在这种情况下,缺乏适当的字节类型支持会造成很大的麻烦。