linefeed(cqh变量数据类型)

心急吃不了热豆腐。4. 变量 内容导视:数据类型类型转换 使用如下方式使用某值,也不是不可以,但是你不怕一个个复制粘贴不小心漏了吗? System.out.println(327501510); System.out.println(...

心急吃不了热豆腐。

4. 变量

内容导视:

数据类型类型转换

使用如下方式使用某值,也不是不可以,但是你不怕一个个复制粘贴不小心漏了吗?

System.out.println(327501510); System.out.println(327501510 + 6); System.out.println("我们的花园真漂亮"); System.out.println("我们的花园真漂亮");

为了使值得到重复利用,下面使用变量保存这些值。

变量声明

每个变量都需要先声明(定义)自己将要保存的数据的类型,后再给变量赋值。

例:想要保存整数类型的值,需要先声明整数类型的变量,假如取名为 i:

int i;

再给变量赋一个整数值。

// 使用等号(赋值运算符)把等号右边的字面量赋给左边的变量 i = 327501510;

可以访问这个变量保存的值。

System.out.println(i);// 此时 i 为 327501510

也可以重新给 i 变量赋值,把之前保存的值覆盖。

i = 6;// 把 6 赋给 i System.out.println(i);// 此时 i 为 6

两者结合,在声明的同时赋值。

int i = 327501510;

那么就可以把开头的例子转变了:

int num1 = 327501510; int num2 = 6; String str = "我们的花园真漂亮"; System.out.println(num1); System.out.println(num1 + num2); System.out.println(str); System.out.println(str);

num1、num2、str 是变量名,作为标识符,我们有权力命名,只要符合命名规则就行。

很明显通过以上例子看到变量有三个要素:

变量的数据类型,如 int;变量名,如 num1;变量值,如 327501510。

数据类型 变量名 = 值;

如果不考虑类型转换,那么变量的数据类型必须与字面量类型一致。

比如整数型的 int 类型不能保存浮点型的字面量,int i = 3.23; 是错误的写法。

变量含义

变量是内存中存储数据的最基本的单元,任何变量都有数据类型,不同的数据类型在内存中分配的空间大小不同。

如 int a = 3; 在内存里分配 4 个字节空间,空间存放着 3,a 就代表这个空间。

变量相当于内存中的一小块数据存储空间,通过变量名可以访问到这个区域。可以把 a 理解成你家的门牌号,通过门牌号定位你家。

cqh-变量、数据类型

int 类型会被分配 4 个字节大小的空间,1 个字节(byte)= 8 个比特位(bit)

1 TB = 1024 GB 1 GB = 1024 MB 1 MB = 1024 KB 1 KB = 1024 Byte 1 Byte = 8 Bit 1 Bit = 0 或 1

利用 0 和 1 的不同的组合代表各式各样的数据。

变量按声明位置分类

分为成员变量与局部变量。之间说过类名 Hello 后跟的 {} 是类体,方法名 main 后跟的 {} 是方法体。

public class Hello { // 方法体外、类体中声明的变量是成员变量 int a = 2; public static void main(String[] args) { // 方法体中声明的变量是局部变量 int b = 4; System.out.println(b);// 4 }}

值得注意的地方

1)局部变量必须赋值(显式初始化)后才能访问,错误示范:

public static void main(String[] args) { int i; System.out.println(i);}

你得先给 i 赋值,比如 int i = 10; 后再访问。

2)同一个域中,局部变量不能重复声明。

域:{} 包起来的范围。

// 错误示范public static void main(String[] args) { int i = 3; int i = 6;}

你得换个名字,以免冲突。比如把后面改成 int j = 6;

3)变量需要先声明,后访问,错误示范:

public static void main(String[] args) { System.out.println(i); int i = 3;}

你应该把它俩的顺序换过来,毕竟 java 语句是自上而下逐行执行的。

4.1 数据类型

内容导视:

字面量整数类型

Java 是一种静态类型语言,每个变量和表达式在编译时就有明确的类型;[1]

Java 是一种强类型语言,变量的类型限制了变量可以保存的值。

// int 类型的变量只能保存整数int i1 = 5;// 以下不能通过编译i1 = 1.23;i1 = "字符串";

Java 支持的数据类型有两种,基本类型与引用类型。

同时也存在有原始值(Primitive Values)和引用值(Reference Values)两种类型的数值可用于变量赋值、参数传递、方法返回和运算操作。

// 将值 3 赋给 int 类型的变量int i = 3;// 将某个对象的引用值赋给 Object 类型的变量Object obj = new Object();

基本类型

基本类型也被称为原始类型(Primitive Types)、简单类型,包括数值类型(Numeric Types)与布尔类型(Boolean Type)。

数值类型包括整数类型(Integral Types)与浮点类型(Floating-Point Types)。

整数类型分为:byte、short、int、long、char;

浮点类型分为:float、double;

布尔类型分为:boolean。

引用类型

引用类型(Reference Types)分为以下三种:

1)类(class)包括枚举

JDK 自带类库,如 java.lang.String、集合、包装类...用户自定义的类型,如我们之前写的 class Hello...第三方类库

2)接口(interface)包括注解

3)数组(array)

[1] 动态类型语言的关键特征是它的类型检查的主体过程是在运行期而不是编译期进行的。像 Java 这种静态类型的语言,如下代码通不过编译:

class Father { String name; int age; public Father(String name, int age) { this.name = name; this.age = age; } public void getAge() { System.out.println(this.name + "的年龄:" + this.age); }}class Son { String name; int age; public Son(String name, int age) { this.name = name; this.age = age; } public void getAge() { System.out.println(this.name + "的年龄:" + this.age); }}class DynamicallyTypedLanguage { public static void main(String[] args) { // 就算 Son 类型有 getAge 方法,编译也不通过 var son = new Son("大头", 3); getAge(son); } // father 的实际类型必须是 Father 或其子类,否则编译不通过 public static void getAge(Father father) { father.getAge(); }}

而动态类型的语言 JavaScript 变量本身没有类型,值才有类型,无论参数是何种类型,只要这种类型的确有 getAge 方法,即可通过编译。

var v1 = 1;v1 = "字符串";v1 = 1.23;class Father { constructor(name, age) { this.name = name; this.age = age; } getAge() { document.write(this.name + "的年龄:" + this.age); }}class Son { constructor(name, age) { this.name = name; this.age = age; } getAge() { document.write(this.name + "的年龄:" + this.age); }}// 运行时,只要 Son 类型的确有 getAge 方法就行getAge(new Son("大头", 3));// father 类型任意,编译时不会检查,也没有办法检查是哪种类型,且有没有 getAge 方法function getAge(father) { father.getAge();}4.1.1 字面量

字面量(Literal)也称字面常量,字面量是基本类型、String 类型、空类型的值在源文件中的表示。

1)整数字面量:如 1、2、5... 这些整数,可以使用十进制、八进制、十六进制表示:

long n1 = 800;// 十进制long n2 = 0400;// 八进制long n3 = 0xFA;// 十六进制

可以加下划线作为分隔符,不影响语义:

long n4 = -1;// -1 的补码的二进制形式、十六进制形式long n5 = 0b1111_1111_1111_1111_1111_1111_1111_1111;long n6 = 0xffffffff;System.out.println(n4);//-1System.out.println(n5);//-1System.out.println(n6);//-1

整数型字面量默认被当作 int 类型处理,可加后缀 L 表示是 long 类型。

// 错误: 不兼容的类型: 从long转换到int可能会有损失int i = 5L;

2)浮点数字面量:如 1.2、5.3、2.11... 这些小数,小数默认被当作 double 类型处理,可加后缀 f 表明是 float 类型。

float f1 = 0.5f;double d1 = 0.5;double d2 = 0.5d;double d3 = 0.25;// 0 可以省略不写,但最好不要这么做double d4 = .25;// 科学计数法double d5 = 2.5E-1;double d6 = 0x0.4P0;

3)布尔字面量:只有两个值,true、false 分别代表真和假。

4)字符字面量:'a'、'b'、'c'... 用英文单引号括起来的单个字符。

5)字符串字面量:"abc"、"b"、"北京欢迎你"... 用英文双引号括起来的是字符串,用于给 String 类型的变量赋值。

6)空字面量:null,给引用类型的变量赋值,表明该变量没有指向任何对象。

4.1.2 整数类型

整数类型的变量可以存储整数字面量、字符字面量。

下面是不同类型的取值范围:

类型

占用字节

字面量取值范围

byte(字节)

1 byte

[-128 ~ 127] 即 [-27 ~ 27 - 1]

short(短整型)

2 byte

[-32768 ~ 32767] 即 [-215 ~ 215 - 1]

int(整型)

4 byte

[-2147483648 ~ 2147483647] 即 [-231 ~ 231 - 1]

long(长整型)

8 byte

[-9223372036854775808 ~ 9223372036854775807] 即 [-263 ~ 263 - 1]

char(字符型)

2 byte

[0 ~ 65535] 即 [0 ~ 216 - 1]

byte、short、int、long 类型用来保存整数字面量,对应的值在内存中的表示是整数的补码形式,有符号位。

char 类型用来保存单个字符,值在内存中的表示是字符的 UTF-16 编码,范围在 '\u0000' ~ '\uFFFF',如 '马' 的序号是 U+9A6C,转成二进制是 0b1001 1010 0110 1100,没有符号位,直接存储此段二进制;

// 如下都是 '马'char c1 = '马';char c2 = '\u9A6C';char c3 = 39532;char c4 = 0b1001_1010_0110_1100;// c1 自动转换成 int 类型:39532int i1 = c1;// 得到 i1 对应的十六进制补码System.out.println(Integer.toHexString(i1));// 9a6c

例子:

int i = 3;byte b = 45;b = 34;System.out.println(i);

定义了 int 类型的变量,变量名为 i,保存的值为 3。

定义了 byte 类型的变量,变量名为 b,保存的值为 45。

cqh-变量、数据类型

把 34 赋给 b 变量,原来保存的 45 被修改了。

cqh-变量、数据类型

System.out.println(i);表示把 i 保存的值输出到控制台(目前是 DOS 窗口)上。

有人可能会问超过了整数类型的取值范围会怎么样?

byte b = 128;Hello.java:4: 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失 byte b = 128;

这下就更疑惑了,什么叫 int 转成 byte 会有损失?难道这个 128 也就是整数型字面量默认被当作 int 类型处理吗?

让我们试一试:

long num1 = 2147483648;

推测:就算 long 类型可以保存这么大的数,但如果后面的 2147483648 真的被当作 int 类型处理的话,那肯定由于超过 int 的范围,会报错。

Hello.java:4: 错误: 过大的整数: 2147483648 long num1 = 2147483648;

好的,大概明白了。得出结论:

整数型字面量默认被当作 int 类型处理。当字面量的值没超过整数类型的范围时,可以直接赋值。如 byte b = 1;

有人就问了,超出 int 范围的值?那能不能让整数型字面量被当作 long 类型处理?

答:在声明整数型字面量时在其后加 l 或 L,作为标识。

long num1 = 2147483648L;long num2 = 2147483648l;

但是你也看见了,由于小写的 l 感觉就像 1,为了避免混淆,统一使用大写表示。

long a1 = 1000_0000_0000L; 为了易读,可以加下划线。规则:不能出现在开头或结尾;不允许出现在标识前后。

这里插一条概念:

值传递:把变量保存的值重新复制一份,传递给另一个变量;而另一个变量修改自己保存的值,不会影响原来变量保存的值。

值传递也称值拷贝

int i1 = 100;// 把 i1 保存的值 100 复制一份,传给 i2,此时 i2 保存的值为 100int i2 = i1;// 修改 i2 保存的值,不会对 i1 有影响i2 = 55;System.out.println("i1 = " + i1);// i1 = 100System.out.println("i2 = " + i2);// i2 = 55cqh-变量、数据类型

好,有了这个概念,让我们试着互换两个变量保存的值。

大家想一想,如果现在有两个杯子 a、b,都装满了水,该如何互换?

cqh-变量、数据类型

是不是要准备第 3 个杯子 c,先把 a 倒进 c 中,然后把 b 倒进 a 中,最后把 c 倒进 b 中。

int a = 22;int b = 433;int c = a;// c = 22a = b;// a = 433b = c;// b = 22

可以不借助第三个变量 c 吗?

有聪明的小伙伴想到了:让 a 保存两值之和(a + b),让 b = 两值之和 - b = a;

int a = 22;int b = 433;a = a + b;// a = 22 + 433b = a - b;// b = (22 + 433) - 433 = 22a = a - b;// a = (22 + 433) - 22 = 433

转义字符

你们可能会在其他地方遇到如 char c = '\n';,这叫转义字符;

一般使用 \ 开头,代表着将某某转义得到单个字符。注意,\xxx 会先转义,哪怕是在字符串中。

cqh-变量、数据类型

在 Unicode 字符表中查到 A 对应的 16 进制为 0x0041,' 对应的 16 进制为 0x0027," 对应的为 0x0022,+ 对应 0x002b。

System.out.println("\u0041\u0022\u002b\u0022\u0041");// " A " + " A "

所以结果不是 \u0041\u0022\u002b\u0022\u0041,而是 "A"+"A",字符串之间会拼接,输出 AA。

下面是常见的转义字符:

\n:换行 \t:制表符 tab \r:回车 \u:把十六进制数转成对应的字符

1)\n:

什么叫换行?

System.out.println("你好\n我好\n大家好\n");char c = '\n';System.out.println(c);System.out.println(2);

这里不得不提一下 ln:

System.out.print(2);System.out.print(1);System.out.println();// 代表换行System.out.print(7);217

ln(换行) 表示当前行结束输出,如果要继续输出,就要移到下行。

回过头来,"你好"换行,"我好"换行,"大家好"换行,ln 代表换行。 System.out.println(c);,c 是 '\n',代表换行,ln 代表换行。 结果如下:

你好我好大家好2

2)\t:

System.out.println("狗\t猫\t鱼");狗 猫 鱼

可以看到狗与猫、鱼之间隔了一个制表符的距离。

3)\r:

System.out.println("我是什么\r人呢");

回车:回到行首,输出文本。由此产生分歧,有人认为一个 \n 足以表示回车加换行,两个字符太浪费了,而 Windows 系统中还保留原来概念,Enter 键(我们通常叫回车键),实际用两个字符表示:\r\n;对应的 ASCII 码用十进制表示分别为 13、10。

Windows 系统换行 Carriage return and line feed(CRLF):回车加换行

Linux 系统换行 Line feed(LF):换行

回到这里,如果回车但不换行,\r 后的 “人呢” 还在同行首个位置上输出,把 “我是” 覆盖,最后结果:"人呢什么"。

4)\u:

System.out.println("\u5929");天

16 进制的 5929 对应的字符为天,有兴趣请在扩充内容中的字符编码了解。

这个 \ 作用不止如此。

问想要使用 char 类型保存单个字符:英文单引号 ' 怎么做?

char c = ''';这样?

Hello.java:4: 错误: 未结束的字符文字 char c = ''';

像这类具有特殊含义的字符,需要使用 \ 转成普通的字符,使其不再被认为是代表字符开始的单引号。

char c = '\'';

同理,打印 \、" 等特殊符号,都需要在字符前加上 \:

System.out.println("\"");System.out.println("\\");

输出结果:

"\4.1.3 浮点类型

浮点类型的变量可以接收一个小数,如 6.2、32.2。

由于使用指数的形式表示值,表示的数比相同字节下的整数类型更大,但是精度有限,结果可能有误差,无法精确表示。

现在看看浮点类型的取值范围,的确比整数类型的取值范围大多了:

类型

占用空间

范围

float

4 个字节

[1.4E-45 ~ 3.4028235E38] 即 [2-149 ~ 2128 - 2104]

double

8 个字节

[4.9E-324 ~ 1.7976931348623157E308] 即 [2-1074 ~ 21024 - 2971]

回过头来,小数类型的字面量又被当作什么类型处理?

做个实验:

float f = 3.14;Hello.java:8: 错误: 不兼容的类型: 从double转换到float可能会有损失 float f = 3.14;

看来默认被当作 double 类型处理。同样想要指定字面量被当作 float 处理,需要在字面量后加上 f 或 F。

float f = 3.14F;

同理,指定字面量被当作 double 类型处理。(其实 D、d 去掉也可以,在基本类型的转换中有讲)

double d1 = 5D;double d2 = 3d;

有时候你会看见这种写法:double d = .12; 不要疑惑,这等同于 double d = 0.12 ,这个 0 可以省略不写,但一般不要这么做,否则其他人可能会疑惑。

精度

浮点数存放形式:浮点数 = 符号位 + 指数位 + 尾数位,尾数部分很可能会丢失,造成精度损失。(小数都是近似值)(有兴趣去之前的内容 “浮点数表示法" 了解,这里不赘述)

System.out.println(0.11111111111111111111111111111F);System.out.println(0.11111111111111111111111111111D);0.111111110.1111111111111111

大概可以这么理解:

float 的精度是保留 7 ~ 8 位有效数字。

double 的精度是保留 15 ~ 16 位有效数字。通常使用 double 类型。

有效数字是一个数从左边第一个不为 0 的数字起,直到末尾止的数字称为有效数字,如 0.009210,有效数字 4 位:9、2、1、0。

保留两位有效数字:0.0092。

由于浮点数运算得到的结果可能有误差,所以如下就成了错误做法:

double d1 = 9.9 / 3;double d2 = 3.3;if (d1 == d2) { System.out.println("它们相等"); }

上面的意思是:如果 d1 等于 d2,就输出 “它们相等”。

但试着运行,控制台什么都没有输出...

此时再试下访问 d1 的值:

System.out.println(d1);// 3.3000000000000003

看到没有?9.9 / 3 不等于 3.3,而是十分接近 3.3 的小数。

当对运算结果是小数的进行相等判断时,应该以两个数的差值的绝对值,在某个精度范围类判断。这个精度由自己决定,如人民币数值比较,人民币最低面额 1 分 = 0.01 元,只要两数差值小于 0.01,就认为它们相等。

现在该改一下了:

double d1 = 9.9 / 3;double d2 = 3.3;if (Math.abs(d1 - d2) < 1.0E-2) { System.out.println("它们相等"); }

还记得如何查 API 文档吗?当导入 java.lang 包下的类时,可以不用 import。哦,对了,你们还不懂,这节在面向对象的包机制中。

那我直接说含义,Math.abs(a):求 a 的绝对值。当 d1 - d2 的绝对值小于 0.01 时,我们姑且认为它们相等。

我还是说说怎么找吧:

打开 JDK API 文档,如果知道 Math 在哪个包下,比如 Math 在 java.lang 包下,点击 java.lang;

cqh-变量、数据类型

如果不知道,点击索引找 M 开头的类:

cqh-变量、数据类型

找到后点击 Math,看看 abs 方法的介绍。

特殊的浮点数值

之前大家可能试过了整数类型的除 0:System.out.println(5 / 0); 报了 ArithmeticException 算术异常。

double d1 = 5.0 / 0;double d2 = -2.0 / 0;double d3 = 0.0 / 0;System.out.println(d1);// InfinitySystem.out.println(d2);// -InfinitySystem.out.println(d3);// NaNSystem.out.println(d3 == d3);// falseSystem.out.println(d3 != d3);// true

一个正数或负数除以 0.0 是无限大 Infinity,对负数求平方根或 0.0 / 0.0 结果不是个数字(is not a numer)

需要注意的是任意两个 NaN 都不相等(包括自己),所以在 Double 类中的 isNaN 方法,使用了自己与自己比较,只有为 NaN 时,自己才不等于自己。

public static boolean isNaN(double v) { return (v != v);}

true:真,false:假

4.1.4 布尔类型

boolean 类型只有两个值:true 或 false,用于逻辑运算,如:2 < 3 为 true。

一般放在 if 、for 等语句的条件处,控制程序的流程,现在不用深究。

虽然 Java 虚拟机定义了 boolean 这种数据类型,但是只对它提供了非常有限的支持。在 Java 虚拟机中没有任何供 boolean 值专用的字节码指令,在 Java 语言之中涉及到 boolean类型值的运算,在编译之后都使用 Java 虚拟机中的 int 数据类型来代替。boolean 的数组类型的访问与修改共用 byte 类型数组的 baload 和 bastore 指令

从 《Java 虚拟机规范》得知:单个定义时 boolean 类型占用 4 个字节,在 boolean 数组中的每个 boolean 类型的元素占用 1 个字节。

4.2 类型转换

内容导视:

基本数据类型转换基本数据类型与 String 类型的转换4.2.1 基本数据类型转换

缘起

double d = 3; 唉呀,字面量 3 不是被当作 int 类型处理吗?怎么就可以赋给 double 类型的 d?别急,看完以下实验就明白规则了。

boolean 除外,不同类型容量(取值范围)按从小到大排列:

byte -> short -> int -> long -> float -> doublechar -> int -> long -> float -> double

基本数据类型的转换规则

前提:基本数据类型

当所赋值的字面量类型与变量的数据类型不一致时,会发生数据类型转换,从一种数据类型转成另一种数据类型。分为自动类型转换、强制类型转换。除了 boolean 类型不能参与转换,其他基本数据类型可以互相转换。

小容量赋给大容量,会发生自动类型转型,如 int 类型自动转为 long 类型:

// int 类型自动转换为 longlong l = 3;// long 类型自动转为 floatfloat d = 3L;System.out.println(d);// 3.0// char 自动转 intint i = '中';System.out.println(i);// 20013

'中'在 Unicode 字库的序号是 4E2D,使用 UTF-16 编码存储的二进制码为 0100111000101101,即 20013。

大容量赋给小容量,自动转换无法进行,溢出了:

// 错误: 不兼容的类型: 从 double 转换到 int 可能会有损失int i = 3.13;// 错误: 不兼容的类型: 从 long 转换到 int 可能会有损失i = 3L;// 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失byte b = 532;

这时就需要强制转换符 (),但可能会有精度损失,想想如果用 16 位才能表示的数强行赋给只有 8 位的空间,又或者将小数赋给只能保存整数的空间,那么很抱歉,对于 int、long 类型转成小容量的类型只能截去前面多余的部分,float、double 类型转成整数类型,舍去小数部分。

// 强制把 double 类型转成 intint i = (int)3.13;System.out.println(i);// i = 3// 强制把 long 类型转成 inti = (int)3L;System.out.println(i);// i = 3// 强制把 int 类型转成 bytebyte b = (byte)532;System.out.println(b);// b = 20

关于溢出,并不是每次都会有提醒:

int i = 2147483647;// int 类型能够保存的最大的整数System.out.println(i + 1);// -2147483648

如果对结果有兴趣,可以了解下之前的内容 “原码、补码、反码”,下面只举 2 个例子:

byte b = 127;b++;System.out.println(b);

b 的补码为 01111111,加 1 后为:10000000,而 10000000 是 -128 的补码,所以输出 -128。

int num1 = 2147483647;int num2 = 7;System.out.println(num1 + num2);2147483647和 7 的补码如下,两数相加 01111111 11111111 11111111 11111111+ 00000000 00000000 00000000 00000111= 10000000 00000000 00000000 00000110 结果是负数的补码补码:10000000 00000000 00000000 00000110反码:10000000 00000000 00000000 00000101原码:11111111 11111111 11111111 11111010 最前面的是符号位,即 -2147483642

补充细节

1)如果字面量的值没有超出 byte、short、char 的取值范围,可以直接赋值给它们。(除了被当作 long 类型处理的字面量)

byte b = 3;char c = 33;byte b1 = 'a';// 'a' 表示 97// 超出 byte 的取值范围,从 char 转换到 byte 可能会有损失byte b2 = '中';// '中' 表示 20013

需要注意,我指的是以字面量形式赋值,而不是值传递,自己试试报什么错?

int i1 = 3;int i2 = 33;char letter = 'a';byte b = i1;char c = i2;byte b1 = letter;

之前有人问你怎么知道 'a' 代表的整数,我又不想了解 ASCII 码,有什么简单的方法吗?这就是第 2 点,请看:

2)byte、short、char 类型的变量混算时,会自动升级到 int 类型。

怎么得出的这个结论?

byte b1 = 2;byte b2 = 5;byte b3 = b1 + b2;Hello.java:6: 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失byte b3 = b1 + b2;

是吧,两个 byte 类型的变量相加,竟然升级了。那我可以利用这一点,让 char 类型的变量升级成 int 变量,自然就知道该字符对应的整数了。

char c = '中';short s = 0;System.out.println(c + s);// 20013System.out.println('1' - 0);// 49

3)多种类型混算时,先把字面量转成容量大的那种数据类型,再进行计算。

如果你不知道这点,以后计算很容易吃亏。比如 10 / 4,你本来想得到 2.5,但是这参与运算的数,容量最大的也只是 int 类型,而 int 类型只能保存整数,所以 2.5 被削去了小数。

int i = 10 / 4;System.out.println(i);// i = 2

这时就需要浮点类型的参与,改一下:

double i = 10.0 / 4;System.out.println(i);// i = 2.5

思考如下语句可以通过编译吗?

byte b = 10;b = b * 2;

b 保存的 10 对应 byte 类型,2 对应 int 类型,这就是混算;让 10 升级到 int 类型,与 2 相乘,结果还是 int 类型,再赋给 byte 类型的变量,报错:从 int 转换到 byte 可能会有损失。

思考输出什么?

double d = 1 / 4 * 4.0;System.out.println(d);

有人说这不就是 1 吗?有什么难的?当然也有其他人看出来了:1 / 4 是两个 int 类型的字面量参与运算,结果为 0;(你难道忘了 int 类型只能保存整数吗?)接着算,0 * 4.0 = 0.0;

所以结果为 0.0。(忘记带小数,哪怕只是 .0,结果就完全不同)

你的原意可能是这:double d = 1.0 / 4 * 4.0;

4)NaN 转成整数为 0;

byte b = (byte)(0.0 / 0.0);System.out.println(b);

5)Infinity、-Infinity 转成 long、int 类型为此类型能够表示的最大值、最小值;

int i = (int)(1.0 / 0.0);System.out.println(i);// 2147483647long l = (long)(-1.0 / 0.0);System.out.println(l);// -9223372036854775808

如果转成 byte、short、char 类型,会先将无穷大值转成 int 类型,再强转为 byte、short、char 类型。

byte b = (byte)(1.0 / 0.0);System.out.println(b);

先将 Infinity 转为 int 类型的最大值 2147483647,对应的补码为 0111_1111 1111_1111 1111_1111 1111_1111,4 个字节转成 1 个字节,将前面 3 个字节截去得到 1111_1111,这是 -1 的补码,所以 b = -1。

4.2.2 基本数据类型与 String 类型的转换

"+" 号除了能计算两数之和外,还能拼接字符串。

String str1 = "我";String str2 = "和";String str3 = "你";String str4 = str1 + str2 + str3;System.out.println(str4);// 我和你

思考输出什么?

System.out.println(4 + 3 * 2 + "2" + 5 * 5);

4 + 6 = 10;10 + "2" = "102";"102" + 25 = "10225";

没看晕吧?从左至右,乘号优先;字符串加谁,谁就被拼接在一起。那么就利用这个 "+",将基本数据类型转成字符串吧。

基本数据类型转成字符串

"" 代表空字符串。输出字符串时,是不会输出双引号的,这你应该早就知道了。

long l = 3L;int i = 3;char c = '中';double d = 3.243;String str1 = l + "";String str2 = i + "";String str3 = c + "";String str4 = d + "";System.out.println(str1);// 3System.out.println(str2);// 3System.out.println(str3);// 中System.out.println(str4);// 3.243

String类型 = String.valueOf(基本数据类型); String类型 = 包装类型.toString(基本数据类型);

字符串转成基本数据类型

别看,等到包装类时就懂了。(或者你会查 API 文档,它们在 java.lang 包下)

String str = "123";byte num1 = Byte.parseByte(str);short num2 = Short.parseShort(str);int num3 = Integer.parseInt(str);long num4 = Long.parseLong(str);float num5 = Float.parseFloat(str);double num6 = Double.parseDouble(str);/* 取下标为 0 的字符(得到 str 的第一个字符) 下标是从 0 开始,以 1 递增,并不是从 1 开始哦*/ char num7 = str.charAt(0);// 如果解析不是"true"的字符串,那么返回结果是 falseboolean num8 = Boolean.parseBoolean("true");System.out.println(num1);// 123System.out.println(num2);// 123System.out.println(num3);// 123System.out.println(num4);// 123System.out.println(num5);// 123.0System.out.println(num6);// 123.0System.out.println(num7);// 1System.out.println(num8);// true

注意不要想着把字符串 "abc" 转成整数,编译虽然可以通过,但运行时会报 java.lang.NumberFormatException 异常(数字格式化异常),程序会在抛出异常的位置终止执行。(异常中有讲)

编译时只是检查语法,并不会解析 "abc" 是否能够转成整数。

4.x 总结回顾

变量

数据类型 变量名 = 值; 先声明后访问。

数据类型

分为基本类型(byte、short、int、long、float、double、char、boolean)与引用类型(类、接口、数组)。

不能直接以双等号判断两个浮点类型的值。应该让两数相减得到差值,如果差值在设定的精度范围内就认为它们相等。

强制转换时注意精度的损失。

4.y 课后习题

4.1 下面语句能够通过编译吗?

1)

byte b = 2;b = b * 2 + 10L;

2)

int i = 3;float f = i + 2.22;

3)

int i = 21;long l = 231;double d = 3.23;long l2 = i + l + d;

4)

int x = (int)3.14 * 3 + 6.2 * 10;

5)

short s1 = 34;short s2 = s1 - 3;

6)

int i = 3;char c = (char)i;

7)

byte b1 = 4 * 3;byte b2 = b1 + (byte)4;short s = b1 + b2;

8)

double d = 3;float f = (float)d + .234F;

9)

long l = 3L;double d = l + 3.24F;

4.2 下面输出结果?

1)

int x = (int)3.14 * 3 + 6 * 10;System.out.println(x);

2)

int x = (int)(3.14 * 3 + 6.2 * 10);System.out.println(x);

4.3 想在控制台上输出 \,怎么写?

4.4 想在控制台上输出如下,怎么写?

cqh-变量、数据类型

4.5 控制台上输出什么?

1)

byte b = (byte)128;System.out.println(b);

2)

byte b = (byte)0b10000000;int i = 0b10000000;System.out.println(b);System.out.println(i);

3)

byte b = (byte)0b111100101;System.out.println(b);4.z 习题答案

4.1 下面语句能够通过编译吗?

1)

byte b = 2;b = b * 2 + 10L;

不能,从 long 转换到 byte 可能会有损失。

2)

int i = 3;float f = i + 2.22;

不能,从 double 转换到 float 可能会有损失。(2.22 默认被当作 double 处理)

3)

int i = 21;long l = 231;double d = 3.23;long l2 = i + l + d;

不能,从 double 转换到 long 可能会有损失。

4)

int x = (int)3.14 * 3 + 6.2 * 10;

不能,从 double 转换到 int 可能会有损失。(强转符号只针对最近的操作数有效,只是把 3.14 转成了 int 类型,可以使用小括号提升优先级)

5)

short s1 = 34;short s2 = s1 - 3;

不能,从 int 转换到 short 可能会有损失。

6)

int i = 3;char c = (char)i;

可以。

7)

byte b1 = 4 * 3;byte b2 = b1 + (byte)4;short s = b1 + b2;

不能,第 2 行报从 int 转换到 byte 可能会有损失;第 4 行报从 int 转换到 short 可能会有损失。

8)

double d = 3;float f = (float)d + .234F;

可以。

9)

long l = 3L;double d = l + 3.24F;

可以。

4.2 下面输出结果?

1)

int x = (int)3.14 * 3 + 6 * 10;System.out.println(x);// 3 * 3 + 6 * 10 = 69

2)

int x = (int)(3.14 * 3 + 6.2 * 10);System.out.println(x);// 9.42 + 62 = 71.42,小数被舍去,71

4.3 想在控制台上输出 \,怎么写?

System.out.println("\\");

4.4 想在控制台上输出如下,怎么写?

cqh-变量、数据类型

System.out.println("动漫名称\t编剧\t价格\t销量\n微笑超人\t坂本\t1000\t0001");

4.5 控制台上输出什么?

1)

byte b = (byte)128;System.out.println(b);// -128128 的补码:00000000 00000000 00000000 10000000强制成一个字节的 byte,只剩 1000000010000000 是 -128 的补码

2)

byte b = (byte)0b10000000;int i = 0b10000000;System.out.println(b);// -128System.out.println(i);//128

0b10000000 = 128,与上题一样。

3)

byte b = (byte)0b111100101;System.out.println(b);补码:111100101反码:111100100原码:100011011b = -0b00011011 = -(1+2+8+16) = -27

  • 发表于 2022-12-05 20:12:35
  • 阅读 ( 150 )
  • 分类:科技

0 条评论

请先 登录 后评论
小小
小小

329 篇文章

你可能感兴趣的文章

相关问题