本帖最后由 ufof 于 2015-12-13 05:52 编辑



2.1 分隔符、标识符、命名方法、关键字



先说一下,从这章开始大家可以用稍微好一点的编辑器了,记事本毕竟过于单调。可以用notepad++、editplus、ultraedit等编辑器。

2.1.1 分隔符

在Java中,有一些符号具有分割的作用,这些被统称为分隔符。
分隔符有分号、花括号、方括号、空格、圆括号、远点。这里只介绍前两个,因为后面那些现在讲还不能够理解。

  • 1、分号 ;

分号一般用于结束一个语句,而非通过换行。所以说Java中支持一行书写多个语句,例如:


  1. 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 volatilewhile

注意: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语言中,通过如下格式声明变量:

  1. 数据类型  变量名;
复制代码

Java是强类型语言,所以说一个变量的类型是固定的。
以上格式是通用的,浮点类型、布尔类型和字符型也是这样的格式。

  1. class IntegerDemo{
  2.     public static void main(String[] args){
  3.         int myInt;                          //定义类型为int的名为myInt的变量
  4.         long myLong;                     //定义类型为long的名为myLong的变量
  5.         byte myByte;
  6.         short myShort;
  7.     }
  8. }
复制代码

变量名需要是一个合法的标识符。

2.2.3 浮点类型

浮点类型可以用于储存所有的有理数,即除了整数以外还有小数。Java为我们提供了两个浮点类型,分别为double和float。所占空间和精度如下:

浮点类型
所占空间
精度
double 64位
4.9^-324~1.7976931348623157^308
float 32位
1.4^-45~3.4028235^38

声明浮点类型的方法也是一样。

  1. class FloatDemo{
  2.     public static void main(String[] args){
  3.         double myDouble;
  4.         float myFloat;
  5.     }
  6. }
复制代码
如果要同时声明多个同类型的数据类型,可以简化成:
  1. 数据类型 变量名,变量名2,变量名3.....,变量名n;
复制代码


不过到现在为止,我们声明的变量还没有一个值,接下来我们学习赋值运算。

2.2.4 赋值运算

在Java中,通过等号“=”来把等号右侧的数赋给左侧的数。

右侧必须是一个字面量(例如5、7、2.3、3.14等用于表示固定值的量)或者已被赋值的变量/常量。

左侧必须是一个变量。如果已经被赋值过,覆盖以前的值。

  1. class AssignmentDemo{
  2.     public static void main(String[] args){
  3.         int x;        //声明int类型变量x
  4.         x = 233;   //把字面量233赋给x

  5.         int y;
  6.         y = x;      //将已被赋值过得x赋给y
  7.         System.out.println("x的值为"+x);
  8.         System.out.println("y的值为"+y);
  9.     }
  10. }
复制代码
结果:



在上面这个例子当中,我们是把先声明变量然后赋值。这两步可以合并:

  1. int x;
  2. x = 5;

  3. 等价于:

  4. int x = 5;
复制代码

如果一个变量已经被赋值过,再次赋值会覆盖掉原本的量。

  1. //省略定义类
  2. //省略定义主方法
  3. int x = 5;
  4. x = 17;

  5. System.out.println("x的值为"+x);
复制代码
结果:



注意:如果要再次赋值千万不要再写“int x”了!那样是重新声明了一个新的变量。如果要拿来使用直接用变量名即可。

如果通过字面量对long类型进行赋值,而且该字面量超出int的范围,要在该字面量后加上“L”或“l”。因为整数类型的字面量默认是int类型的。

  1. //省略定义类
  2. //省略定义主方法

  3. long l = 2147483652L;   //2147483652超过int类型的取值范围,所以要在后面加“L”或“l”。
复制代码

给float赋值也是一样。浮点字面量默认被看成double,如果要给float赋值,要加上“F”或“f”。

2.2.5  八进制和十六进制的赋值方法

八进制的字面量要以0开头。例如0777、01473等。
十六进制的字面量要以0x或0X开头,例如0xa13、0xdd1。

  1. class NumbersInDifferentBaseDemo{
  2.     public static void main(String[] args){
  3.         int num1 = 0xadc;  //合法
  4.         int num2 = 01633; //合法
  5.     }
  6. }
复制代码

本章小结:
  • 基本数据类型中的数据类下又有两大类:整数类和浮点类
  • 整数类有四个类型;浮点类有两个类型。不同的类型有不同的精度
  • 声明变量的方法:“数据类型 变量名”
  • 赋值方法:“被赋值的变量 =  赋的值”



2.3 四则运算以及取余数



2.3.1  概述

上一节我们学习了声明以及赋值变量。在程序当中,对变量的四则运算是十分重要的,所以这节课我们来学习如何在Java中实现四则运算。

2.3.2 实现方法

Java当中实现四则运算的运算符分别为“+”、“-”、“*”、“/”。取余数为“%”。

运算符左右两边必须为数值类的变量/常量,其运算完之后一般要赋值给另一个变量或直接打印输出。

  1. class OperationDemo{
  2.     public static void main(String[] args){
  3.         //定义变量
  4.         int num1 = 5;
  5.         int num2 = 2;
  6.         //进行运算
  7.         int sum = num1+num2;
  8.         int difference = num1-num2;
  9.         int product = num1*num2;
  10.         int quotient = num1/num2;
  11.         int remainder = num1%num2;
  12.         //打印输出
  13.         System.out.println("num1+num2="+sum);
  14.         System.out.println("num1-num2="+difference);
  15.         System.out.println("num1*num2="+product);
  16.         System.out.println("num1/num2="+quotient+"......"+remainder);               
  17.     }
  18. }
复制代码
结果:



在这个例子当中,我声明了两个变量,一个num1,一个num2。之后我把这两个变量进行了四则运算和取余数,并赋给了其他的变量。
现在大家对四则运算和取余数有了一定的了解。

学生提问:为什么我对两个int进行除法运算,结果却是向下取整的?我想要结果是一个精确的小数,怎么办?

答:两个int相除结果必定是向下取整的。如果两个数字中有一个以上是浮点的话,结果就会是小数。不过也不需要专门因为除法运算把变量声明为浮点,以后学到强制转换了就可以解决。目前来讲先暂时把一个变量声明为浮点吧。

2.3.4 实例:求平均数

学习完四则运算的计算方法后,为了巩固知识,我们写一个小程序:求平均数。
在这里我先回顾一下平均数的算法:平均数=所有数之和/所有数的数量。

在这里我们就先演示两个数的求平均数。

  1. class GetMean{
  2.     public static void main(String[] args){
  3.         double num1 = 3.4;
  4.         double num2 = 6.3;
  5.         
  6.         System.out.println("num1和num2的平均数为"+(num1+num2)/2);    //求平均数:(num1+num2)/2
  7.         
  8.     }
  9. }
复制代码
结果:



本章小结:
  • Java为我们提供四则运算的运算符分别为+-*/,取余数为%。
  • 如果两个参与除法运算的数字都为整数类型,结果为向下取整的整数;如果有一者以上为浮点,结果为小数




2.4 布尔类型



2.4.1 布尔概述

在我们的生活中,有许多东西是“绝对的”,只有“是”或“否”。例如灯有没有开、门有没有关、引擎是否发动等。这类问题的答案无非只有两种。在逻辑学中,这类的值称为布尔。Java中同样给我们提供了这样的数据类型,关键字是boolean。

2.4.2 布尔的应用

布尔的声明方法和数值类也一样:“数值类型 变量名;”。boolean类的变量只有两种,true(真)或false(假)。

  1. class BooleanDemo{
  2.     public static void main(String[] args){
  3.         boolean b1 = true;
  4.         boolean b2 = false;
  5.         System.out.println("b1的值为"+b1);
  6.         System.out.println("b2的值为"+b2);
  7.     }
  8. }
复制代码
结果:



布尔类型的应用最多
用于进行逻辑判断,例如if、while等,不过现在还没有学到,在第三章中会开始着重讲流程控制,那个时候布尔可就是真正有用了。

本章小结
  • 布尔类型只有两个值true或false
  • 布尔类型一般用于逻辑判断




2.5 数值比较、逻辑运算以及位运算



2.5.1 数值比较

上一次我们学习了如何进行四则运算和取余数。现在我们来学习对数值类进行比较。比较的结果返回的是一个布尔类型。
比较运算符:
大于:>
小于:<
等于:==(请勿和赋值运算符“=”混淆)
大于等于:>=
小于等于<=
不等于:!=

  1. class Comparison{
  2.     public static void main(String[] agrs){
  3.         int a = 3;
  4.         int b = 5;
  5.         //开始比较
  6.         boolean isGreater = a>b;
  7.         boolean isLesser = a<b;
  8.         boolean isEqual = a==b;
  9.         boolean isGreaterOrEqual = a>=b;
  10.         boolean isLesserOrEqual = a<=b;
  11.         boolean isNotEqual = a!=b;
  12.         
  13.         System.out.println("a>b吗?"+isGreater);
  14.         System.out.println("a<b吗?"+isLesser);
  15.         System.out.println("a=b吗?"+isEqual);
  16.         System.out.println("a>=b吗?"+isGreaterOrEqual);
  17.         System.out.println("a<=b吗?"+isLesserOrEqual);
  18.         System.out.println("a!=b吗?"+isNotEqual);
  19.     }
  20. }
复制代码
结果:



在这里面,我用上了所有的比较运算符,分别把结果赋给了几个布尔类型。然后在对布尔进行输出。

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中为我们提供的运算符:

与:&或&&
或:|或||
非:!(请勿与比较运算符!=混淆)
异或:^

  1. class BitwiseDemo{
  2.     public static void main(String[] args){
  3.         boolean a = true;
  4.         boolean b = false;
  5.         
  6.         boolean and = a&&b;
  7.         boolean or = a||b;
  8.         boolean notA = !a;
  9.         boolean notB = !b;
  10.         boolean xor = a^b;
  11.         
  12.         System.out.println("a&&b="+and);
  13.         System.out.println("a||b="+or);
  14.         System.out.println("!a="+notA);
  15.         System.out.println("!b="+notB);
  16.         System.out.println("a^b="+xor);
  17.     }
  18. }
复制代码
结果:



我们来分析一下:
在这个例子当中,由于a和b并非都为真,所以a&&b为假;a和b之间有一个真,所以a||b为真;a为真,所以!a为假;b为假,所以!b为真;a和b一个是真一个是假,两者不同,所以a^b为真。

学生提问:那么“&”和“&&”,“|”和“||”真的没有什么区别吗?

回答:其实有区别,主要有两点。第一点:与和非中有两个布尔参与运算。先说与运算。如果第一个布尔为假,那么结果肯定为假,两者的区别是&&一旦看到第一个布尔为假,就不会管第二个了,直接返回假;若使用&,就算第一个为假,他也会计算后面的布尔。或运算一样,如果第一个为真,结果肯定为真。若使用||,第一个为真,就不会去管第二个了,直接返回真;若使用|,就算第一个布尔是真,他也会去计算第二个布尔。这是第一点。第二点:&&和||双方只能用布尔类型来运算。但是&和|双方也可以是数值类。这点我们马上会讲。

2.5.3 数值类的逻辑运算

首先,数值类要进行逻辑运算的话需要用&或|,而非&&或||。
我们先看一段代码和结果,然后再来分析究竟结果的原理。

  1. class BitwiseDemo2{
  2.     public static void main(String[] agrs){
  3.         int num1 = 42;
  4.         int num2 = 18;
  5.         
  6.         int and = num1&num2;
  7.         int or = num1|num2;
  8.         
  9.         System.out.println(num1+"&"+num2+"="+and);
  10.         System.out.println(num1+"|"+num2+"="+or);
  11.     }
  12. }
复制代码
结果:



好的,现在我们来分析一下究竟为什么是这个得数。

首先我们要把42和18转换成原码二进制:

42转换为二进制为0101010
18转换为二进制为010010

我们要干的事情首先是像我们学数学的时候列一个竖式:



把相对应的位的两个数字进行与/或运算(1为true,0为false)



拿与运算举例:第一位是两个0,那就相当于false&&false,结果还是false,所以是0.
第二位是1和1,那就是1。
接下来,把得到的数转换回十进制:



那就是我们所得到的结果。

2.5.4 位运算

位运算是对二进制进行左移、右移、无符号右移运算的统称。

左移运算符:<<
右移运算符:>>
无符号右移:>>>

先演示左移:
  1. class BitwiseDemo3 {
  2.     public static void main(String[] args) {
  3.         int num = 15;
  4.         
  5.         System.out.println(num << 2);
  6.     }
  7. }
复制代码
结果:



我们来分析一下为什么结果是这样的。

首先我们把15转换成二进制的形式。15的二进制是1111,为了便于理解,我在1111之前加上四个0:



现在呢,我们要把“1111”向左移两位,这样的话,最前面的两个0就被抛弃了,变成001111:



之后,我们得要在001111后面补上两个0,就变成了00111100。然后我们把这个数转换成十进制,那就是60。

总结一下:左移就是高位舍弃,低位补零。

右移和无符号右移


  1. class Bitwise4Demo {
  2.     public static void main(String[] args) {
  3.         int num = 19;
  4.         
  5.         System.out.println(num >> 2);
  6.         System.out.println(num >>> 2);
  7.     }
  8. }
复制代码
结果:



也一样,我们先把19转换成二进制,那就是10011:



100在转换成十进制就是4。

那么右移和无符号右移有什么区别呢?

右移在补数字方面有所讲究:如果原来的数字是正数,那就在高位补若干个0;如果是负数,补若干个1。在刚才的例子当中,19是正数,所以在移位之后,补的是0。

无符号右移就是无论如何都是补0,就算原本的数字是负数。

我们把这三种运算写成代数的形式:



(无符号右移没有找到公式,抱歉)

本章小结:
  • Java提供比较运算符、逻辑运算符,以及位运算符
  • 比较运算符返回的是一个布尔;逻辑运算符返回什么取决于输入;位运算符返回数值




2.6 自增自减



2.6.1 自增自减概述

以后我们在编程时会常常对数值类的变量进行“增加1”和“减小1”等操作。根据我们之前学过的四则运算方法,这可以通过以下代码实现:

  1. class AddAndSubtractDemo{
  2.     public static void main(String[] args){
  3.         int num =5;
  4.         num = num+1; //对自己+1然后赋给自己
  5.         System.out.println("num="+num);
  6.     }
  7. }
复制代码
结果:



这样运算着实有些麻烦,Java给我们提供自增自减运算符,++和--。用法如下:

数值类变量名++;
++
数值类变量名;
数值类变量名--;
--
数值类变量名;

我们来用一下:

  1. class AddAndSubtractDemo2{
  2.     public static void main(String[] args){
  3.         int num = 5;
  4.         num++;   //使用自增运算符
  5.         System.out.println("num="+num);
  6.         
  7.         int num2 = 10;
  8.         num2--;    //使用自减运算符
  9.         System.out.println("num2="+num2);
  10.     }
  11. }
复制代码
结果:



那么,自增自减运算符我们基本上会用了,可是变量++和++变量有什么区别呢?

2.6.2 x++、x--和++x、--x的区别

运算符在变量前面和后面的区别在于“先运算还是先赋值”。

  1. class AddAndSubtractDemo3{
  2.     public static void main(String[] args){
  3.         int num = 5;
  4.         int x = num++;
  5.         
  6.         System.out.println("num="+num);
  7.         System.out.println("x="+x);
  8.     }
  9. }
复制代码
结果:



我们稍微改一下,把num++改成++num:

  1. class AddAndSubtractDemo3{
  2.     public static void main(String[] args){
  3.         int num = 5;
  4.         int x = ++num;
  5.         
  6.         System.out.println("num="+num);
  7.         System.out.println("x="+x);
  8.     }
  9. }
复制代码
结果:



两者结果不一样。如果使用num++,x的值为5,如果使用++num,x的值为6。

原因是如果变量在运算符前面,先赋值,然后自增/自减;如果变量在运算符后面,先自增/自减,然后赋值

本章小结
  • 自增自减对变量本身+1或-1
  • 先写变量还是先写运算符的区别在于先赋值还是先运算




2.7 扩展赋值运算



2.7.1  扩展赋值运算概述

请观察下列代码:

  1. class AdvancedAssignmentDemo{
  2.         public static void main(String[] args){
  3.                 int a = 10;
  4.                 a=a+10;
  5.                 System.out.println("第一次运算,a="+a);
  6.                 a=a-5;
  7.                 System.out.println("第二次运算,a="+a);
  8.                 a=a*3;
  9.                 System.out.println("第三次运算,a="+a);
  10.                 a=a/7;
  11.                 System.out.println("第四次运算,a="+a);
  12.         }
  13. }
复制代码
结果:



从这个程序中可以看出,每一次运算都是会对本身进行运算然后再赋给自己。这样的做法完全可行,但是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等价


现在,我们再把刚才的代码优化一下:

  1. class AdvancedAssignmentDemo{
  2.         public static void main(String[] args){
  3.                 int a = 10;
  4.                 a+=10;
  5.                 System.out.println("第一次运算,a="+a);
  6.                 a-=5;
  7.                 System.out.println("第二次运算,a="+a);
  8.                 a*=3;
  9.                 System.out.println("第三次运算,a="+a);
  10.                 a/=7;
  11.                 System.out.println("第四次运算,a="+a);
  12.         }
  13. }
复制代码
结果:



现在呢,我们通过扩展运算符对程序进行了优化。这样做比原来的方法更加方便。

本章小结
  • 扩展运算符用于简化“对变量进行运算然后在赋给自己”类的运算
  • 扩展运算符的写法一般是运算符和等号,例如+=、*=等





2.8  字符类型



2.8.1 字符类型概述

基本数据类型我们已经讲完数值型和布尔型了,现在来讲最后一个——字符型。
字符型可以用来存储一个unicode的字符,而unicode包含所有国家的语言,所以说字符类型也可以用来存储中文的字符。
字符类型的关键字是char。声明方法和前几个介绍过的类型完全相同。

2.8.2 使用字符类型

字符类型的声明方法也依旧是“数据类型 变量名”,数据类型是char。那么赋值的时候赋的是什么呢?

  • 用单引号'括起来的unicode字符,例如'g'、'4'、'哦'等
  • Unicode值,格式为\uXXXX(XXXX为unicode的值),不过也要被单引号括起来
  • 转义字符(第十一节讲到)

  1. class CharDemo{
  2.     public static void main(String[] args){
  3.         char myChar = '你';
  4.         char myChar2 = '\u0043';
  5.         
  6.         System.out.println("myChar的值为:"+myChar);
  7.         System.out.println("myChar2的值为:"+myChar2);
  8.     }
  9. }
复制代码
结果:



在该代码中,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是一个修饰符,其出现在数据类型前面,例如:

  1. class FinalDemo{
  2.     public static void main(String[] args){
  3.         final double PI = 3.1415926535;
  4.         System.out.println("PI的值为"+PI);
  5.     }
  6. }
复制代码
结果:



在这个程序当中,PI被修饰为final,其成为一个常量。

  1. class FinalDemo2{
  2.     public static void main(String[] args){
  3.         final double PI = 3.1415926535;
  4.         
  5.         PI = 5; //非法
  6.         System.out.println("PI的值为"+PI);
  7.     }
  8. }
复制代码
结果:



在这个程序当中,PI已经被赋值且声明为final了,所以说在第五行如果把字面量5赋给PI的话,会报错。

简单翻译一下报错信息:
FinalDemo.java:5:错误:不可以把一个值赋值给常量PI

总而言之,被声明为final的常量终身为其所被赋的值。

学生提问:如果被声明为final的常量刚开始没有被赋值会怎么样?例如:

  1. class FinalDemo3{
  2.     public static void main(String[] args){
  3.         final double PI;    //仅声明,没有赋值
  4.         
  5.         PI = 3.1415926535;
  6.         System.out.println("PI的值为"+PI);
  7.     }
  8. }
复制代码

答:可以通过。常量的定义是只能赋值一次。在这个例子当中刚开始都没有赋值过,所以后来的赋值没有关系。

顺带一提:根据Java语言的编程规范,一般常量的名称是全部大写,词与词之间通过下划线“_”连接。就比如说刚才我用的是PI而非pi。再来举一些例子:MY_FINAL_VALUE、CONSTANT_NUMBER等。

本章小结:
  • 被声明为final的变量会成为常量
  • 常量不能被再次赋值,否则报错
  • 常量的命名方法一般是全部大写,下划线连接




2.10   数据转换



2.10.1 数据转换概述

有的时候我们在程序中需要对数据进行转换来达到我们想要的效果大家还记不记得再学四则运算的时候我曾经说过两个int相除,结果必定是向下取整的。如果想要一个小数的结果,必须要将被除数或除数之间的任意一个转换成浮点。可见数据转换的重要性,因此Java允许我们对数据类型进行相互转换。

2.10.2 隐式转换

假如说我有两个瓶子,一个是大瓶子,一个是小瓶子。如果我把小瓶子里的水全部倒进大瓶子(大瓶子原本没水),肯定不会溢出。

Java中,如果对低精度的数据类型转换成高精度的数据类型,肯定会成功,不会溢出。这类转换称为隐式转换。
隐式转换的方法很简单,是将低精度的变量赋给高精度的变量即可:

  1. class ConversionDemo{
  2.     public static void main(String[] args){
  3.         int num = 2147483647;
  4.         long l = num; //隐式转换
  5.         
  6.         System.out.println("l的值为"+l);
  7.     }
  8. }
复制代码
结果:



在这里我们可以看到,num的值已经是int类型的最高支持范围了,也就是2^31-1,在这种情况下转换成功,毕竟long的范围比int长。这就是“把小水瓶的水倒进大水瓶”。

2.10.3 显式转换

上一节我们演示的是“小水瓶的水倒进大水瓶”,这种情况下是肯定不会溢出的。现在我们要把“大水瓶倒进小水瓶”。这样做有可能会溢出,这取决于“大水瓶”里有多少水。

显式转换其实就是强制转换。格式是:
  1. (低精度类型) 高精度量;
复制代码
高精度量可以是一个字面量或一个变量/常量。
低精度类型是想要转换到的类型。

例如:

  1. class ConversionDemo{
  2.     public static void main(String[] args){
  3.         long l = 2147483647;
  4.         int i = (int) l; //显式转换
  5.         
  6.         System.out.println("i="+i);
  7.     }
  8. }
复制代码
结果:



这一次转换是成功的,因为i=2147483647刚刚是int类型的最大值,所以成功。

  1. class ConversionDemo{
  2.     public static void main(String[] args){
  3.         long l = 100000000000L;  //该值超过int类型的最大值
  4.         int i = (int) l;
  5.         
  6.         System.out.println("i="+i);
  7.     }
  8. }
复制代码
结果:



这就是典型的溢出,因为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,也就是我们得到的结果。

其实隐式转换也可以用显式转换的格式。例如:
  1. class ConversionDemo{
  2.     public static void main(String[] args){
  3.         int i = 2147483647;
  4.         long l = (long) i;
  5.         System.out.println(l);
  6.     }
  7. }
复制代码
结果:



另附渣图:


本章小结:
  • Java中为我们提供两种转换方式,显式转换和隐式转换
  • 显式转换是将高精度类型转换成低精度类型;隐式转换是将低精度类型转换成高精度类型
  • 显式转换有可能溢出;但是隐式转换不可能溢出




2.11  转义字符



2.11.1  转义字符概述

转义字符是特殊的字符。是通过反斜线“\”来转变其后面字符的意义。对于大部分的字符来讲,转义没有多少意义。不过对特定的一些字符,转义会有特殊的意义。

2.11.2  有特殊意义的可被转义的字

可被转义的字符
意义
\n 换行
\t 按下tab
\r 按下回车
\b 退格
\" 双引号(不会开始/关闭字符串)
\' 单引号(不会开始/关闭字符)
\\ 反斜杠(不会转义字符)


  1. class EscapeCharacterDemo{
  2.     public static void main(String[] args){
  3.         char myChar = '\n';
  4.         System.out.println("hello"+myChar+"world");
  5.     }
  6. }
复制代码
结果:



在这个例子当中,我声明了一个叫做myChar的字符类型,把\n赋给了他它。在打印输出语句中\n的回车作用使打印hello之后换行,然后再打印world。

其等价于:
  1. System.out.println("hello\nworld");
复制代码

两者的结果是相同的。

我们要来演示一下\t,按下tab。

  1. class EscapeCharacterDemo{
  2.     public static void main(String[] args){
  3.         System.out.println("hello\tworld");
  4.     }
  5. }
复制代码
结果:



结果是相当于在hello后面使用了tab键,所以数个空格出现在两个词当中。

如果我想要输出"Hello, world"(注意,双引号也要输出)或者\hello, world\怎么办呢?

这样做是不行的:
  1. System.out.println(""Hello, world"");//非法
  2. System.out.println("\Hello, world");//非法
复制代码

在第一个输出语句当中,第二个双引号把第一个双引号结束了,后面也是,所以Hello, world并没有在字符串当中。可以把双引号转义,它就不会起到开始/关闭字符串的作用了。

第二条输出语句中,第二个反斜杠把双引号给转义了,所以第二个双引号就不会关闭这个字符串。如果我们可以把一个反斜线给转义,其就不会起到转义的作用了。

  1. System.out.println(""Hello, world"");//合法
  2. System.out.println("\\Hello, world\");//合法
复制代码

本章小结
  • 转义字符是指通过反斜杠\转变其下一个字符的意义
  • 有一些字符被转义有特殊的意义,大部分没有



Java当中的运算符是有着优先级的,当多个运算符同时使用是有先后顺序的。

以下为Java中运算符的优先级排列(从上到下,优先级降低):

运算符
描述
() 括号
+、-
正负号
++、--、!
一元运算符(自增自减以及非门)
*、/、%
乘除、取余数
+、-
加减
<<、>>、>>>
位移运算
<、>、<=、>=
比较大小
==、!=比较是否相等
&
数值与运算
^数值异或运算
|数值或运算
&&
布尔与运算
||布尔或运算
? :
三元运算符
=、+=、-=、*=、/=.....
赋值运算或扩展赋值运算


[groupid=546]Command Block Logic[/groupid]