2.1 分隔符、标识符、命名方法、关键字
先说一下,从这章开始大家可以用稍微好一点的编辑器了,记事本毕竟过于单调。可以用notepad++、editplus、ultraedit等编辑器。
2.1.1 分隔符
在Java中,有一些符号具有分割的作用,这些被统称为分隔符。
分隔符有分号、花括号、方括号、空格、圆括号、远点。这里只介绍前两个,因为后面那些现在讲还不能够理解。
- 1、分号 ;
分号一般用于结束一个语句,而非通过换行。所以说Java中支持一行书写多个语句,例如:
- System.out.println("Line 1");System.out.println("Line 2"); //合法
- 2、花括号 {}
花括号一般用于定义一个区间,一个代码块等。在hello, world程序当中,类和方法都有一对花括号来表示区间。
花括号是成对的。如果有一个“{”则必须有“}”。
2.1.2 标识符
类、变量、方法等的名字必须是一个标识符。合法的标识符必须满足以下条件:
- 可以用字母(可以包含中文)、数字、下划线、美元符号组成;
- 不能以数字开头;
- 不能有空格;
- 不能有#、&类似的其他字符;
- 不能是关键字。
注意:Java严格区分大小写。A和a是不同的两个标识符。
2.1.3 命名方法
一般在编程语言当中,除了要取一个有意义的名字之外,还得要有一定的规范。目前来讲有两种命名方法:
- 匈牙利命名法(不推荐)
匈牙利命名法的格式为“属性+类型+描述”。
属性是指这个变量的特征,例如静态、常量、局部等等。
类型则是变量的数据类型,例如整数、布尔等。
由于属性和类型的每一项都有字母去代替,所以说看上去会比较凌乱不堪,所以并不推荐这种命名方法。
- 驼峰命名法(推荐)
驼峰命名法是通过对字母大小写的变换来提高阅读性。整个内容都是描述。
驼峰命名法下面还分两种叫做小驼峰和大驼峰。小驼峰中除了第一个词的首字母和非首字母的字母都小写之外,其他的都是大写。例如:
myName;
myFirstNumber;
大驼峰的区别就在于首字母也要大写:
MyName;
MyFirstNumber;
小驼峰适合变量、引用等的命名;大驼峰适合类、接口的命名。
2.1.4 关键字
关键字即为被Java赋予特殊意义的词。目前来讲,Java中有50个关键字。我们已经接触到了class这个关键字,以下为所有的关键字:
abstract | assert | boolean | break | byte |
case | catch | char | class | const(保留) |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto(保留) | if | implements | import |
instanceof | int | interface | long | native |
new | package | private | protected | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
注意:Java中所有关键字为小写。
我没有让你们背这些关键字,我只是列举出来罢了,每一个关键字我们会以后逐个讲到。
本章小结:
- Java中起分割作用的符号统称分隔符。分号;用于结束语句;大括号{}用于定义区间
- 命名方法主要有匈牙利命名法和骆驼命名法,推荐后者
- 关键字是被Java赋予特定意义的单词;合法的标识符用于取名字
2.2 整数类型、浮点类型以及赋值运算
2.2.1 基本数据类型概述
Java为我们提供的基本数据类型包含数值类、布尔类,以及字符类。分类方法见下:
今天我们来学习一下数值类。数值类下又包含整数类型和浮点类型。
2.2.2 整数类型
Java为我们提供了四种整数类型。每一种类型都有不同的精度。这四种分别为long、int、short、byte。所占空间、精度如下:
整数类型 | 所占空间 | 精度 |
long | 64位 | -2^63~2^63-1 |
int | 32位 | -2^31~2^31-1 |
short | 16位 | -2^15~2^15-1 |
byte | 8位 | -2^7~2^7-1 |
学生提问:为什么一个类型的精度的幂数总是所占空间-1?例如int类型占32为,为什么精度的幂数是31?
答:二进制中的原码需要使用最高的一位作为符号位,如果为0则为正、1为负。32位中有一位被用作符号位,剩余的31位便是绝对值。
那么我们如何声明一个变量呢?Java语言中,通过如下格式声明变量:
- 数据类型 变量名;
Java是强类型语言,所以说一个变量的类型是固定的。
以上格式是通用的,浮点类型、布尔类型和字符型也是这样的格式。
- class IntegerDemo{
- public static void main(String[] args){
- int myInt; //定义类型为int的名为myInt的变量
- long myLong; //定义类型为long的名为myLong的变量
- byte myByte;
- short myShort;
- }
- }
变量名需要是一个合法的标识符。
2.2.3 浮点类型
浮点类型可以用于储存所有的有理数,即除了整数以外还有小数。Java为我们提供了两个浮点类型,分别为double和float。所占空间和精度如下:
浮点类型 | 所占空间 | 精度 |
double | 64位 | 4.9^-324~1.7976931348623157^308 |
float | 32位 | 1.4^-45~3.4028235^38 |
声明浮点类型的方法也是一样。
- class FloatDemo{
- public static void main(String[] args){
- double myDouble;
- float myFloat;
- }
- }
- 数据类型 变量名,变量名2,变量名3.....,变量名n;
不过到现在为止,我们声明的变量还没有一个值,接下来我们学习赋值运算。
2.2.4 赋值运算
在Java中,通过等号“=”来把等号右侧的数赋给左侧的数。
右侧必须是一个字面量(例如5、7、2.3、3.14等用于表示固定值的量)或者已被赋值的变量/常量。
左侧必须是一个变量。如果已经被赋值过,覆盖以前的值。
- class AssignmentDemo{
- public static void main(String[] args){
- int x; //声明int类型变量x
- x = 233; //把字面量233赋给x
- int y;
- y = x; //将已被赋值过得x赋给y
- System.out.println("x的值为"+x);
- System.out.println("y的值为"+y);
- }
- }
在上面这个例子当中,我们是把先声明变量然后赋值。这两步可以合并:
- int x;
- x = 5;
- 等价于:
- int x = 5;
如果一个变量已经被赋值过,再次赋值会覆盖掉原本的量。
- //省略定义类
- //省略定义主方法
- int x = 5;
- x = 17;
- System.out.println("x的值为"+x);
注意:如果要再次赋值千万不要再写“int x”了!那样是重新声明了一个新的变量。如果要拿来使用直接用变量名即可。
如果通过字面量对long类型进行赋值,而且该字面量超出int的范围,要在该字面量后加上“L”或“l”。因为整数类型的字面量默认是int类型的。
- //省略定义类
- //省略定义主方法
- long l = 2147483652L; //2147483652超过int类型的取值范围,所以要在后面加“L”或“l”。
给float赋值也是一样。浮点字面量默认被看成double,如果要给float赋值,要加上“F”或“f”。
2.2.5 八进制和十六进制的赋值方法
八进制的字面量要以0开头。例如0777、01473等。
十六进制的字面量要以0x或0X开头,例如0xa13、0xdd1。
- class NumbersInDifferentBaseDemo{
- public static void main(String[] args){
- int num1 = 0xadc; //合法
- int num2 = 01633; //合法
- }
- }
本章小结:
- 基本数据类型中的数据类下又有两大类:整数类和浮点类
- 整数类有四个类型;浮点类有两个类型。不同的类型有不同的精度
- 声明变量的方法:“数据类型 变量名”
- 赋值方法:“被赋值的变量 = 赋的值”
2.3 四则运算以及取余数
2.3.1 概述
上一节我们学习了声明以及赋值变量。在程序当中,对变量的四则运算是十分重要的,所以这节课我们来学习如何在Java中实现四则运算。
2.3.2 实现方法
Java当中实现四则运算的运算符分别为“+”、“-”、“*”、“/”。取余数为“%”。
运算符左右两边必须为数值类的变量/常量,其运算完之后一般要赋值给另一个变量或直接打印输出。
- class OperationDemo{
- public static void main(String[] args){
- //定义变量
- int num1 = 5;
- int num2 = 2;
- //进行运算
- int sum = num1+num2;
- int difference = num1-num2;
- int product = num1*num2;
- int quotient = num1/num2;
- int remainder = num1%num2;
- //打印输出
- System.out.println("num1+num2="+sum);
- System.out.println("num1-num2="+difference);
- System.out.println("num1*num2="+product);
- System.out.println("num1/num2="+quotient+"......"+remainder);
- }
- }
在这个例子当中,我声明了两个变量,一个num1,一个num2。之后我把这两个变量进行了四则运算和取余数,并赋给了其他的变量。
现在大家对四则运算和取余数有了一定的了解。
学生提问:为什么我对两个int进行除法运算,结果却是向下取整的?我想要结果是一个精确的小数,怎么办?
答:两个int相除结果必定是向下取整的。如果两个数字中有一个以上是浮点的话,结果就会是小数。不过也不需要专门因为除法运算把变量声明为浮点,以后学到强制转换了就可以解决。目前来讲先暂时把一个变量声明为浮点吧。
2.3.4 实例:求平均数
学习完四则运算的计算方法后,为了巩固知识,我们写一个小程序:求平均数。
在这里我先回顾一下平均数的算法:平均数=所有数之和/所有数的数量。
在这里我们就先演示两个数的求平均数。
- class GetMean{
- public static void main(String[] args){
- double num1 = 3.4;
- double num2 = 6.3;
-
- System.out.println("num1和num2的平均数为"+(num1+num2)/2); //求平均数:(num1+num2)/2
-
- }
- }
本章小结:
- Java为我们提供四则运算的运算符分别为+-*/,取余数为%。
- 如果两个参与除法运算的数字都为整数类型,结果为向下取整的整数;如果有一者以上为浮点,结果为小数
2.4 布尔类型
2.4.1 布尔概述
在我们的生活中,有许多东西是“绝对的”,只有“是”或“否”。例如灯有没有开、门有没有关、引擎是否发动等。这类问题的答案无非只有两种。在逻辑学中,这类的值称为布尔。Java中同样给我们提供了这样的数据类型,关键字是boolean。
2.4.2 布尔的应用
布尔的声明方法和数值类也一样:“数值类型 变量名;”。boolean类的变量只有两种,true(真)或false(假)。
- class BooleanDemo{
- public static void main(String[] args){
- boolean b1 = true;
- boolean b2 = false;
- System.out.println("b1的值为"+b1);
- System.out.println("b2的值为"+b2);
- }
- }
布尔类型的应用最多用于进行逻辑判断,例如if、while等,不过现在还没有学到,在第三章中会开始着重讲流程控制,那个时候布尔可就是真正有用了。
本章小结
- 布尔类型只有两个值true或false
- 布尔类型一般用于逻辑判断
2.5 数值比较、逻辑运算以及位运算
2.5.1 数值比较
上一次我们学习了如何进行四则运算和取余数。现在我们来学习对数值类进行比较。比较的结果返回的是一个布尔类型。
比较运算符:
大于:>
小于:<
等于:==(请勿和赋值运算符“=”混淆)
大于等于:>=
小于等于<=
不等于:!=
- class Comparison{
- public static void main(String[] agrs){
- int a = 3;
- int b = 5;
- //开始比较
- boolean isGreater = a>b;
- boolean isLesser = a<b;
- boolean isEqual = a==b;
- boolean isGreaterOrEqual = a>=b;
- boolean isLesserOrEqual = a<=b;
- boolean isNotEqual = a!=b;
-
- System.out.println("a>b吗?"+isGreater);
- System.out.println("a<b吗?"+isLesser);
- System.out.println("a=b吗?"+isEqual);
- System.out.println("a>=b吗?"+isGreaterOrEqual);
- System.out.println("a<=b吗?"+isLesserOrEqual);
- System.out.println("a!=b吗?"+isNotEqual);
- }
- }
在这里面,我用上了所有的比较运算符,分别把结果赋给了几个布尔类型。然后在对布尔进行输出。
2.5.2 逻辑运算
Java为我们提供了四种逻辑运算的运算符,这四个运算符相对应的运算为:与、或、非、异或。其他的扩展的逻辑门可以通过上述的逻辑门进行组合运算来达到。
我先来简单的介绍一下这四种逻辑门:
与的真值表:
输入1 | 输入2 | 输出 |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
换句话说,只有所有输入都为真,输出才为真。
或的真值表:
输入1 | 输入2 | 输出 |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
只要有一个输入为真,输出则为真。
非的真值表:
输入 | 输出 |
0 | 1 |
1 | 0 |
可以理解为是对输入的“取反”。若为真,输出假;若为假,输出真。
异或的真值表:
输入1 | 输入2 | 输出 |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
若两个输入不同,则输出真;反之亦然。
好的,对这四个逻辑门有了了解之后,我们再来看看Java中为我们提供的运算符:
与:&或&&
或:|或||
非:!(请勿与比较运算符!=混淆)
异或:^
- class BitwiseDemo{
- public static void main(String[] args){
- boolean a = true;
- boolean b = false;
-
- boolean and = a&&b;
- boolean or = a||b;
- boolean notA = !a;
- boolean notB = !b;
- boolean xor = a^b;
-
- System.out.println("a&&b="+and);
- System.out.println("a||b="+or);
- System.out.println("!a="+notA);
- System.out.println("!b="+notB);
- System.out.println("a^b="+xor);
- }
- }
我们来分析一下:
在这个例子当中,由于a和b并非都为真,所以a&&b为假;a和b之间有一个真,所以a||b为真;a为真,所以!a为假;b为假,所以!b为真;a和b一个是真一个是假,两者不同,所以a^b为真。
学生提问:那么“&”和“&&”,“|”和“||”真的没有什么区别吗?
回答:其实有区别,主要有两点。第一点:与和非中有两个布尔参与运算。先说与运算。如果第一个布尔为假,那么结果肯定为假,两者的区别是&&一旦看到第一个布尔为假,就不会管第二个了,直接返回假;若使用&,就算第一个为假,他也会计算后面的布尔。或运算一样,如果第一个为真,结果肯定为真。若使用||,第一个为真,就不会去管第二个了,直接返回真;若使用|,就算第一个布尔是真,他也会去计算第二个布尔。这是第一点。第二点:&&和||双方只能用布尔类型来运算。但是&和|双方也可以是数值类。这点我们马上会讲。
2.5.3 数值类的逻辑运算
首先,数值类要进行逻辑运算的话需要用&或|,而非&&或||。
我们先看一段代码和结果,然后再来分析究竟结果的原理。
- class BitwiseDemo2{
- public static void main(String[] agrs){
- int num1 = 42;
- int num2 = 18;
-
- int and = num1&num2;
- int or = num1|num2;
-
- System.out.println(num1+"&"+num2+"="+and);
- System.out.println(num1+"|"+num2+"="+or);
- }
- }
好的,现在我们来分析一下究竟为什么是这个得数。
首先我们要把42和18转换成原码二进制:
42转换为二进制为0101010
18转换为二进制为010010
我们要干的事情首先是像我们学数学的时候列一个竖式:
把相对应的位的两个数字进行与/或运算(1为true,0为false):
拿与运算举例:第一位是两个0,那就相当于false&&false,结果还是false,所以是0.
第二位是1和1,那就是1。
接下来,把得到的数转换回十进制:
那就是我们所得到的结果。
2.5.4 位运算
位运算是对二进制进行左移、右移、无符号右移运算的统称。
左移运算符:<<
右移运算符:>>
无符号右移:>>>
先演示左移:
- class BitwiseDemo3 {
- public static void main(String[] args) {
- int num = 15;
-
- System.out.println(num << 2);
- }
- }
我们来分析一下为什么结果是这样的。
首先我们把15转换成二进制的形式。15的二进制是1111,为了便于理解,我在1111之前加上四个0:
现在呢,我们要把“1111”向左移两位,这样的话,最前面的两个0就被抛弃了,变成001111:
之后,我们得要在001111后面补上两个0,就变成了00111100。然后我们把这个数转换成十进制,那就是60。
总结一下:左移就是高位舍弃,低位补零。
右移和无符号右移
- class Bitwise4Demo {
- public static void main(String[] args) {
- int num = 19;
-
- System.out.println(num >> 2);
- System.out.println(num >>> 2);
- }
- }
也一样,我们先把19转换成二进制,那就是10011:
100在转换成十进制就是4。
那么右移和无符号右移有什么区别呢?
右移在补数字方面有所讲究:如果原来的数字是正数,那就在高位补若干个0;如果是负数,补若干个1。在刚才的例子当中,19是正数,所以在移位之后,补的是0。
无符号右移就是无论如何都是补0,就算原本的数字是负数。
我们把这三种运算写成代数的形式:
(无符号右移没有找到公式,抱歉)
本章小结:
- Java提供比较运算符、逻辑运算符,以及位运算符
- 比较运算符返回的是一个布尔;逻辑运算符返回什么取决于输入;位运算符返回数值
2.6 自增自减
2.6.1 自增自减概述
以后我们在编程时会常常对数值类的变量进行“增加1”和“减小1”等操作。根据我们之前学过的四则运算方法,这可以通过以下代码实现:
- class AddAndSubtractDemo{
- public static void main(String[] args){
- int num =5;
- num = num+1; //对自己+1然后赋给自己
- System.out.println("num="+num);
- }
- }
这样运算着实有些麻烦,Java给我们提供自增自减运算符,++和--。用法如下:
数值类变量名++;
++数值类变量名;
数值类变量名--;
--数值类变量名;
我们来用一下:
- class AddAndSubtractDemo2{
- public static void main(String[] args){
- int num = 5;
- num++; //使用自增运算符
- System.out.println("num="+num);
-
- int num2 = 10;
- num2--; //使用自减运算符
- System.out.println("num2="+num2);
- }
- }
那么,自增自减运算符我们基本上会用了,可是变量++和++变量有什么区别呢?
2.6.2 x++、x--和++x、--x的区别
运算符在变量前面和后面的区别在于“先运算还是先赋值”。
- class AddAndSubtractDemo3{
- public static void main(String[] args){
- int num = 5;
- int x = num++;
-
- System.out.println("num="+num);
- System.out.println("x="+x);
- }
- }
我们稍微改一下,把num++改成++num:
- class AddAndSubtractDemo3{
- public static void main(String[] args){
- int num = 5;
- int x = ++num;
-
- System.out.println("num="+num);
- System.out.println("x="+x);
- }
- }
两者结果不一样。如果使用num++,x的值为5,如果使用++num,x的值为6。
原因是如果变量在运算符前面,先赋值,然后自增/自减;如果变量在运算符后面,先自增/自减,然后赋值。
本章小结
- 自增自减对变量本身+1或-1
- 先写变量还是先写运算符的区别在于先赋值还是先运算
2.7 扩展赋值运算
2.7.1 扩展赋值运算概述
请观察下列代码:
- class AdvancedAssignmentDemo{
- public static void main(String[] args){
- int a = 10;
- a=a+10;
- System.out.println("第一次运算,a="+a);
- a=a-5;
- System.out.println("第二次运算,a="+a);
- a=a*3;
- System.out.println("第三次运算,a="+a);
- a=a/7;
- System.out.println("第四次运算,a="+a);
- }
- }
从这个程序中可以看出,每一次运算都是会对本身进行运算然后再赋给自己。这样的做法完全可行,但是Java给我们提供了一种更加方面的做法,那就是扩展运算符。
2.7.2 如何实现
扩展运算符可以和运算运算符、逻辑运算运算符、位运算符相结合,总共有下列几种:
扩展运算符 | 意义 |
+= | a+=b与a=a+b等价 |
-= | a-=b与a=a-b等价 |
*= | a*=b与a=a*b等价 |
/= | a/=b与a=a/b等价 |
%= | a%=b与a=a%b等价 |
&= | a&=b与a=a&b等价 |
|= | a|=b与a=a|b等价 |
^= | a^=b与a=a^b等价 |
<<= | a<<=b与a=a<<b等价 |
>>= | a>>=b与a=a>>b等价 |
>>>= | a>>>=b与a=a>>>b等价 |
现在,我们再把刚才的代码优化一下:
- class AdvancedAssignmentDemo{
- public static void main(String[] args){
- int a = 10;
- a+=10;
- System.out.println("第一次运算,a="+a);
- a-=5;
- System.out.println("第二次运算,a="+a);
- a*=3;
- System.out.println("第三次运算,a="+a);
- a/=7;
- System.out.println("第四次运算,a="+a);
- }
- }
现在呢,我们通过扩展运算符对程序进行了优化。这样做比原来的方法更加方便。
本章小结
- 扩展运算符用于简化“对变量进行运算然后在赋给自己”类的运算
- 扩展运算符的写法一般是运算符和等号,例如+=、*=等
2.8 字符类型
2.8.1 字符类型概述
基本数据类型我们已经讲完数值型和布尔型了,现在来讲最后一个——字符型。
字符型可以用来存储一个unicode的字符,而unicode包含所有国家的语言,所以说字符类型也可以用来存储中文的字符。
字符类型的关键字是char。声明方法和前几个介绍过的类型完全相同。
2.8.2 使用字符类型
字符类型的声明方法也依旧是“数据类型 变量名”,数据类型是char。那么赋值的时候赋的是什么呢?
- 用单引号'括起来的unicode字符,例如'g'、'4'、'哦'等
- Unicode值,格式为\uXXXX(XXXX为unicode的值),不过也要被单引号括起来
- 转义字符(第十一节讲到)
- class CharDemo{
- public static void main(String[] args){
- char myChar = '你';
- char myChar2 = '\u0043';
-
- System.out.println("myChar的值为:"+myChar);
- System.out.println("myChar2的值为:"+myChar2);
- }
- }
在该代码中,myChar存储的值是“你”,打印输出也就是“你”。\u0043是unicode中的“C”,所以打印的便是“C”。
学生提问:那么我想要储存一个句子,而非一个字符,如何做到?
答:要储存一个句子,也就是“一堆字符”,需要用到字符串String。String是一个类,我们在讲面向对象之后会学习到。
本章小结
- 字符类型用于存储unicode中存在的字符
- 下列形式可以赋值给char:用单引号括起来的字符、unicode值(格式\uXXXX)和转义字符
2.9 通过final修饰常量
2.9.1 final概述
我们之前定义一个变量之后呢,这个变量是可以随时随地被重新赋值的。这样有一定的安全隐患,如果你想要定义一个常数,不希望被改变,那该怎么办呢?Java为我们提供一个关键字,叫做final。被声明为final的变量称为常量,常量这可以赋值一次。
例如,我定义了一个叫做pi的变量,因为圆周率是一个数学常数,我不希望其被改变,这个时候就可以用到final关键字了。
2.9.2 final的应用
final是一个修饰符,其出现在数据类型前面,例如:
- class FinalDemo{
- public static void main(String[] args){
- final double PI = 3.1415926535;
- System.out.println("PI的值为"+PI);
- }
- }
在这个程序当中,PI被修饰为final,其成为一个常量。
- class FinalDemo2{
- public static void main(String[] args){
- final double PI = 3.1415926535;
-
- PI = 5; //非法
- System.out.println("PI的值为"+PI);
- }
- }
在这个程序当中,PI已经被赋值且声明为final了,所以说在第五行如果把字面量5赋给PI的话,会报错。
简单翻译一下报错信息:
FinalDemo.java:5:错误:不可以把一个值赋值给常量PI
总而言之,被声明为final的常量终身为其所被赋的值。
学生提问:如果被声明为final的常量刚开始没有被赋值会怎么样?例如:
复制代码
- class FinalDemo3{
- public static void main(String[] args){
- final double PI; //仅声明,没有赋值
- PI = 3.1415926535;
- System.out.println("PI的值为"+PI);
- }
- }
答:可以通过。常量的定义是只能赋值一次。在这个例子当中刚开始都没有赋值过,所以后来的赋值没有关系。
顺带一提:根据Java语言的编程规范,一般常量的名称是全部大写,词与词之间通过下划线“_”连接。就比如说刚才我用的是PI而非pi。再来举一些例子:MY_FINAL_VALUE、CONSTANT_NUMBER等。
本章小结:
- 被声明为final的变量会成为常量
- 常量不能被再次赋值,否则报错
- 常量的命名方法一般是全部大写,下划线连接
2.10 数据转换
2.10.1 数据转换概述
有的时候我们在程序中需要对数据进行转换来达到我们想要的效果。大家还记不记得再学四则运算的时候我曾经说过两个int相除,结果必定是向下取整的。如果想要一个小数的结果,必须要将被除数或除数之间的任意一个转换成浮点。可见数据转换的重要性,因此Java允许我们对数据类型进行相互转换。
2.10.2 隐式转换
假如说我有两个瓶子,一个是大瓶子,一个是小瓶子。如果我把小瓶子里的水全部倒进大瓶子(大瓶子原本没水),肯定不会溢出。
Java中,如果对低精度的数据类型转换成高精度的数据类型,肯定会成功,不会溢出。这类转换称为隐式转换。
隐式转换的方法很简单,是将低精度的变量赋给高精度的变量即可:
- class ConversionDemo{
- public static void main(String[] args){
- int num = 2147483647;
- long l = num; //隐式转换
-
- System.out.println("l的值为"+l);
- }
- }
在这里我们可以看到,num的值已经是int类型的最高支持范围了,也就是2^31-1,在这种情况下转换成功,毕竟long的范围比int长。这就是“把小水瓶的水倒进大水瓶”。
2.10.3 显式转换
上一节我们演示的是“小水瓶的水倒进大水瓶”,这种情况下是肯定不会溢出的。现在我们要把“大水瓶倒进小水瓶”。这样做有可能会溢出,这取决于“大水瓶”里有多少水。
显式转换其实就是强制转换。格式是:
- (低精度类型) 高精度量;
低精度类型是想要转换到的类型。
例如:
- class ConversionDemo{
- public static void main(String[] args){
- long l = 2147483647;
- int i = (int) l; //显式转换
-
- System.out.println("i="+i);
- }
- }
这一次转换是成功的,因为i=2147483647刚刚是int类型的最大值,所以成功。
- class ConversionDemo{
- public static void main(String[] args){
- long l = 100000000000L; //该值超过int类型的最大值
- int i = (int) l;
-
- System.out.println("i="+i);
- }
- }
这就是典型的溢出,因为100,000,000,000是long类型的范围内,但是int类型不接受。不过也没看到有什么报错信息,输出是一个看似毫无关系的数字。
那么这个数字是如何得出来的呢?
首先是将100,000,000,000转换成二进制1,011,101,001,000,011,101,101,110,100,000,000,000,这个二进制数字有37位数。不过int类型仅支持32位,所以说多余的位数将会被抛弃。
1011101001000011101101110100000000000
红色部分为被抛弃部分,黑色部分为留下的部分。我们把留下的部分转换回来成十进制,那就是1215752192,也就是我们得到的结果。
其实隐式转换也可以用显式转换的格式。例如:
- class ConversionDemo{
- public static void main(String[] args){
- int i = 2147483647;
- long l = (long) i;
- System.out.println(l);
- }
- }
另附渣图:
本章小结:
- Java中为我们提供两种转换方式,显式转换和隐式转换
- 显式转换是将高精度类型转换成低精度类型;隐式转换是将低精度类型转换成高精度类型
- 显式转换有可能溢出;但是隐式转换不可能溢出
2.11 转义字符
2.11.1 转义字符概述
转义字符是特殊的字符。是通过反斜线“\”来转变其后面字符的意义。对于大部分的字符来讲,转义没有多少意义。不过对特定的一些字符,转义会有特殊的意义。
2.11.2 有特殊意义的可被转义的字
可被转义的字符 | 意义 |
\n | 换行 |
\t | 按下tab |
\r | 按下回车 |
\b | 退格 |
\" | 双引号(不会开始/关闭字符串) |
\' | 单引号(不会开始/关闭字符) |
\\ | 反斜杠(不会转义字符) |
- class EscapeCharacterDemo{
- public static void main(String[] args){
- char myChar = '\n';
- System.out.println("hello"+myChar+"world");
- }
- }
在这个例子当中,我声明了一个叫做myChar的字符类型,把\n赋给了他它。在打印输出语句中\n的回车作用使打印hello之后换行,然后再打印world。
其等价于:
- System.out.println("hello\nworld");
两者的结果是相同的。
我们要来演示一下\t,按下tab。
- class EscapeCharacterDemo{
- public static void main(String[] args){
- System.out.println("hello\tworld");
- }
- }
结果是相当于在hello后面使用了tab键,所以数个空格出现在两个词当中。
如果我想要输出"Hello, world"(注意,双引号也要输出)或者\hello, world\怎么办呢?
这样做是不行的:
- System.out.println(""Hello, world"");//非法
- System.out.println("\Hello, world");//非法
在第一个输出语句当中,第二个双引号把第一个双引号结束了,后面也是,所以Hello, world并没有在字符串当中。可以把双引号转义,它就不会起到开始/关闭字符串的作用了。
第二条输出语句中,第二个反斜杠把双引号给转义了,所以第二个双引号就不会关闭这个字符串。如果我们可以把一个反斜线给转义,其就不会起到转义的作用了。
- System.out.println(""Hello, world"");//合法
- System.out.println("\\Hello, world\");//合法
本章小结
- 转义字符是指通过反斜杠\转变其下一个字符的意义
- 有一些字符被转义有特殊的意义,大部分没有
Java当中的运算符是有着优先级的,当多个运算符同时使用是有先后顺序的。
以下为Java中运算符的优先级排列(从上到下,优先级降低):
运算符 | 描述 |
() | 括号 |
+、- | 正负号 |
++、--、! | 一元运算符(自增自减以及非门) |
*、/、% | 乘除、取余数 |
+、- | 加减 |
<<、>>、>>> | 位移运算 |
<、>、<=、>= | 比较大小 |
==、!= | 比较是否相等 |
& | 数值与运算 |
^ | 数值异或运算 |
| | 数值或运算 |
&& | 布尔与运算 |
|| | 布尔或运算 |
? : | 三元运算符 |
=、+=、-=、*=、/=..... | 赋值运算或扩展赋值运算 |
[groupid=546]Command Block Logic[/groupid]