引用数据类型、自动类型提升、自动类型转换、强制类型转换
10.7.2 引用数据类型
/*
* 1、与 基本数据类型 对应的是 引用类型
* 2、在基本数据类型的变量中存储的就是相应类型的数值
* 3、在引用类型的变量中存储的是一个内存地址(通过这个地址可以找到真正的数据)
*/
public class Snake {
public static void main( String[] args ) {
int first = 100 ; // int 类型的变量 first 中直接存储了数值 100
System.out.println( first );
// 对于 main 方法的参数 args 来说就是一个 引用类型 的变量 (引用变量)
System.out.println( args ); // 所有引用变量中都存储了一个内存地址
// 通过这个内存地址可以找到真正的数据所在的位置
int n = args.length ; // 获取数组长度
for( int i = 0 ; i < n ; i++ ) {
System.out.println( args[ i ] ) ;
}
}
}
10.7.3 自动类型提升
/**
* 1、表示数字的基本数据类型的【自动类型提升】
* 2、按照能够表示的数字范围从小到大排列依次是 byte 、 short 、int 、long 、float 、double
* 3、将 数字范围较小的类型的变量的值 赋值给 数字范围较大的类型的变量 时,会发生【自动类型提升】
*/
public class Chicken {
public static void main( String[] args ) {
// 8bit 16bit 32bit 64bit 32bit 64bit
// byte --> short --> int --> long ---> float ---> double
// 声明一个 byte 类型的、名称为 first 的 变量并为其赋值
byte first = 100 ; // 100 对应的二进制形式刚好是用 8 个二进制位所能表示的
System.out.println( first );
short second = first ; // 本来是 byte 类型的 first 变量中存储的数值 会提升为 short 类型
System.out.println( second );
// int third = second ; // 本来是 short 类型的 second 变量中存储的数值 会提升为 int 类型
int third = first ; // 本来是 byte 类型的 first 变量中存储的数值 会提升为 int 类型
System.out.println( third );
long fourth = first ; // 本来是 byte 类型的 first 变量中存储的数值 会提升为 long 类型
System.out.println( fourth );
float fifth = first ; // 本来是 byte 类型的 first 变量中存储的数值 会提升为 float 类型
System.out.println( fifth );
double sixth = first ; // 本来是 byte 类型的 first 变量中存储的数值 会提升为 double 类型
System.out.println( sixth );
}
}
/**
* 1、在 Java 语言中,如果遇到 范围比 int 小的类型发生运算时,首先需要提升为 int 类型后再运算
* 2、在 Java 语言中,两个 float 类型的变量相加后仍然是 float 类型 ( Java 8 和 Java 11 测试通过 )
* 3、在 Java 语言中,一个 float 类型的数值 与 一个 double 类型的数值 发生运算时,float 数值首先提升为 double 类型后再运算
*/
public class Pig {
public static void main( String[] args ) {
byte first = 100 ;
byte second = 50 ;
// byte third = first + second ; // 【编译失败】错误: 不兼容的类型: 从int转换到byte可能会有损失
// 两个 byte 类型的 变量 相加时,会首先自动类型提升为 int 类型,再运算
int third = first + second ;
System.out.println( third );
short fourth = 100 ;
short fifth = 200 ;
// short sixth = fourth + fifth ; // 【编译失败】错误: 不兼容的类型: 从int转换到short可能会有损失
// 两个 short 类型的 变量 相加时,会首先自动类型提升为 int 类型,再运算
int sixth = fourth + fifth ;
System.out.println( sixth );
// byte result = first + fourth ; // ???
// short result = first + fourth ; // ???
// int result = first + fourth ; // ???
// long result = first + fourth ; // ???
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
float one = 3.14F ;
float two = 3.14F ;
float three = one + two ; // 注意: 这里至少在 Java 8 中测试是通过的
System.out.println( three );
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
double four = 3.1415926 ;
// float five = one + four ; // 【编译失败】错误: 不兼容的类型: 从double转换到float可能会有损失
double five = one + four ;
System.out.println( five );
}
}
10.7.4 自动类型转换
/**
* 1、short 和 char 之间不能实现【自动类型转换】
* 2、short 和 char 都可以【自动类型提升】为 数字范围较大 的类型 ( int 、long 、float 、double )
*/
public class Dog {
public static void main( String[] args ) {
// short : 16bit
short first = 97 ;
System.out.println( first );
// char second = first ; // 【编译失败】错误: 不兼容的类型: 从short转换到char可能会有损失
int second = first ; // 本来是 short 类型的 first 变量中存储的数值会自动提升为 int 类型后再赋值给 second 变量
System.out.println( second );
// char : 16bit
char third = 'a' ;
System.out.println( third );
// short fourth = third ; // 【编译失败】错误: 不兼容的类型: 从short转换到char可能会有损失
int fourth = third ; // 本来是 char 类型的 third 变量中存储的数值会自动提升为 int 类型后再赋值给 fourth 变量
System.out.println( fourth );
}
}
10.7.5 强制类型转换
public class NarrowingPrimitive {
public static void main(String[] args) {
// 【 1 】In the first step,
// the floating-point number is converted either to a long , if T is long, or to an int, if T is byte, short, char, or int, as follows:
// 【 1.1 】If the floating-point number is NaN ( Not a Number ), the result of the first step of the conversion is an int or long 0 .
double nan = Double.NaN ; // NaN 是 Double 类中声明的一个常量
System.out.println( nan );
System.out.println( "byte : " + (byte) nan + " , short : " + (short) nan + " , int : " + (int) nan + " , long : " + (long) nan );
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 【 1.2 】Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V,
// rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
// 【 1.2.1 】If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V
double lv = 0xFFFFFFFFL + 0.625; // 假设 double 变量中存储的数值的整数部分恰好是 long 类型可以表示的整数
System.out.println( lv );
System.out.println( "long : " + (long) lv );
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 【 1.2.2 】Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
double iv = 0xFFFFFF + 0.625; // 假设 double 变量中存储的数值的整数部分恰好是 int 类型可以表示的整数
System.out.println( iv );
System.out.println( "int : " + (int) iv );
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 【 1.3 】Otherwise, one of the following two cases must be true:
// 【 1.3.1 】The value must be too small ( a negative value of large magnitude or negative infinity ),
// and the result of the first step is the smallest representable value of type int or long.
// double negative = Double.NEGATIVE_INFINITY ; // NEGATIVE_INFINITY 是 Double 类中定义的常量,表示负无穷大
double negative = 0x8000_0000_0000_0000L - 10000.0 ; // 一定要让 long 类型的值 减去 double 类型的数值
System.out.println( negative );
System.out.println( "int : " + (int) negative + " , long : " + (long) negative );
// int min value : 0x8000_0000 ( 0b1000_0000_0000_0000_0000_0000_0000_0000 )
// long min value : 0x8000_0000_0000_0000L
System.out.println( "~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~" );
// 【 1.3.2 】The value must be too large ( a positive value of large magnitude or positive infinity ),
// and the result of the first step is the largest representable value of type int or long.
// double positive = Double.POSITIVE_INFINITY ; // POSITIVE_INFINITY 是 Double 类中定义的常量,表示正无穷大
double positive = 0x7FFF_FFFF_FFFF_FFFFL + 10000.0 ; // 一定要让 long 类型的值 加上 double 类型的数值
System.out.println( positive );
System.out.println( "int : " + (int) positive + " , long : " + (long) positive );
// int max value : 0x7FFF_FFFF ( 0b0111_1111_1111_1111_1111_1111_1111_1111 )
// long max value : 0x7FFF_FFFF_FFFF_FFFFL
double x = 0xFFFF + 0.1415926 ;
//【 2 】In the second step:
//【 2.1 】 If T is int or long, the result of the conversion is the result of the first step.
System.out.println( "int : " + (int) x + " , long : " + (long) x );