Java程序基础一

最近有学习Java语法的打算,忙里偷闲边学习边记笔记。
Java程序基础一包括:常量、变量、数据类型、运算符。

1.标识符

Java 区分大小写,thisvar和ThisVar是两个标识符

1.1 驼峰命名

  • 1.1.1 大驼峰

    • 主要用于类名和接口名
    • 全部单词首字母大写,如MyOne
  • 1.1.2 小驼峰

    • 一般用于变量名和方法名
    • 第一个单词首字母小写,其他单词首字母大写,如getMyNamename

2.关键字

Java 语言目前定义了 51 个关键字,这些关键字不能作为变量名类名和方法名来使用。以下对这些关键字进行了分类。

  • 数据类型:booleanintlongshortbytefloatdoublecharclassinterface
  • 流程控制:ifelsedowhileforswitchcasedefaultbreakcontinuereturntrycatchfinally
  • 修饰符:publicprotectedprivatefinalvoidstaticstrictabstracttransientsynchronizedvolatilenative
  • 动作:packageimportthrowthrowsextendsimplementsthissupperinstanceofnew
  • 保留字:truefalsenullgotoconst

注意:由于Java区分大小写,因此public是关键字,而Public则不是关键字。但是为了程序的清晰及可读性,要尽量避免使用关键字的其他形式来命名。


3.Java基础

一个.java文件中,只能有一个public class Main公共主类,如果想再要一个公共主类或公共类,可以再新建一个.java文件

3.1 变量与常量

3.1.1 常量值

常量值是常量的具体和直观的表现形式

  • 整型常量值

    • 十进制数形式:如 54、-67、0。
    • 八进制数形式:Java 中的八进制常数的表示以 0 开头,如 0125 表示十进制数 85,-013 表示十进制数 -11。
    • 十六进制数形式:Java 中的十六进制常数的表示以 0x 或 0X 开头,如 0x100 表示十进制数 256,-0x16 表示十进制数 -22。
  • 实型常量值

    • 十进制数形式:由数字和小数点组成,且必须有小数点,如 12.34、-98.0。
    • 科学记数法形式:如 1.75e5 或 32&E3,其中 e 或 E 之前必须有数字,且 e 或 E 之后的数字必须为整数。
  • 布尔型常量值

    • false
    • true
  • 字符型和字符串常量值

    • 字符型(char)常量值是用单引号引起来的一个字符,用来存放单个字符,如 ‘e’、E’。字符串常量值中的单引号和双引号不可混用。

    • 字符串(string)常量值是用双引号引起来的单个字符串,用来存储是char字符数组,如 “11”、”dt”。

    • 转义字符

      转义字符 说明
      \ddd 1~3 位八进制数所表示的字符
      \uxxxx 1~4 位十六进制数所表示的字符
      \‘ 单引号字符
      \“ 双引号字符
      \\ 双斜杠字符
      \r 回车
      \n 换行
      \b 退格
      \t 横向跳格

3.1.2 定义常量

常量是指在程序的整个运行过程中值保持不变的量,常量是形式化的表现。它可以在程序中用符号来代替常量值使用,因此在使用前必须先定义。

Java 使用final关键字来定义一个常量,语法如下:

1
2
3
4
5
6
7
final dataType variableName = value
/*
* final 是定义常量的关键字
* dataType 指明常量的数据类型
* variableName 是变量的名称
* value 是初始值
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class HelloWorld {
// 声明静态常量
public static final double PI = 3.14;
// 声明成员常量
final int y = 10;

public static void main(String[] args) {
// 声明局部常量
final double x = 3.3;
System.out.println(PI);
System.out.println(y); // 无法从 static 上下文引用非 static 字段 'y'
System.out.println(x);
}
}
    • 常量有三种类型:静态常量、成员常量和局部常量
    • 代码第 3 行的是声明静态常量,使用在 final 之前 public static 修饰。public static 修饰的常量作用域是全局的,不需要创建对象就可以访问它,在类外部访问形式为HelloWorld.PI。这种常量在编程中使用很多。
    • 代码第 5 行声明成员常量,作用域类似于成员变量,但不能修改。
    • 代码第 9 行声明局部常量,作用域类似于局部变量,但不能修改。
  • 在定义常量时,需要注意如下内容:

    • 在定义常量时就需要对该常量进行初始化。
    • final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
    • 为了与变量区别,常量取名一般都用大写字符。

3.1.3 变量声明

变量是用来描述一条信息的别名,变量中可以存储各种类型的信息

Java 中通过指定数据类型和标识符来声明变量,语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DataType identifier;

//或者

DataType identifier = value;
/*
* DataType:变量类型,如 int、string、 char 和 double 等
* identifier:标识符,也叫变量名称
* value:声明变量时的值
*/

/*
* 标识符命名规范如下:
* 首字符必须是字母、下划线(―)、美元符号($)或者人民币符号(¥)
* 标识符由数字(0~9)、大写字母(A~Z)、小写字母(a~z)、下划线(―)、美元符号($)、人民币符号(¥)以及所有在十六进制 0xc0 前的 ASCII 码组成
* 不能把关键字、保留字作为标识符
* 标识符的长度没有限制
* 标识符区分大小写
*/
1
2
3
String employee;    // String 类型的变量
boolean isSave; // boolean 类型的变量
int create_at; // int 类型的变量

3.1.4 变量赋值

变量初始化变量有两种方式:一种是声明时直接赋值,一种是先声明、后赋值

1
2
3
4
5
6
7
char usersex='女';    // 直接赋值

String username; // 先声明
username ="wuyong"; // 后赋值

String username,phone,email; // 声明多个变量
int num1=10,num2=20,result=50; // 声明并初始化多个变量

3.2 变量作用域

3.2.1 成员变量之实例变量(全局变量)

static修饰,通过对象名.变量名访问。只要对象被当作引用,实例变量就将存在
无需显式初始化,系统会自动对其进行默认初始化

1
2
3
4
5
6
7
8
9
public class HelloWorld {

public int data=50; // 实例变量
public int age; //没有初始化的成员变量

public static void main(String[] args) {
System.out.println("Hello world!");
}
}

3.2.2 成员变量之静态变量(类变量)

static修饰,通过类名.变量名对象名.变量名访问。其生命周期取决于类的生命周期。类被垃圾回收机制彻底回收时才会被销毁
无需显式初始化,系统会自动对其进行默认初始化

1
2
3
4
5
6
7
8
9
public class HelloWorld {

public static int m=10; // 静态变量
public String name; //没有初始化的成员变量

public static void main(String[] args) {
System.out.println("Hello world!");
}
}

3.2.3 局部变量

局部变量是指在方法或者方法代码块中定义的变量,作用域是其所在的代码块。分为方法参数变量(形参)、方法局部变量(方法内定义)、代码块局部变量(代码块内定义)
局部变量除了形参外,都必须显示初始化,也就是要指定一个初始值,否则不能访问。

  • 方法参数变量(形参):在整个方法内有效。
1
2
3
4
5
6
7
8
public class Test1 {
public static void testFun(int n) {
System.out.println("n=" + n);
}
public static void main(String[] args) {
testFun(3);
}
}
  • 方法局部变量(方法内定义): 从定义这个变量开始到方法结束这一段时间内有效。
1
2
3
4
5
6
public class Test2 {
public static void main(String[] args) {
int i = 10;
System.out.println("i = " + i);
}
}
  • 代码块局部变量(代码块内定义):从定义这个变量开始到代码块结束这一段时间内有效。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test3 {
public static void test() {
try {
String x = "--"; // x的作用域是try块
System.out.println("Hello" + x + "World");
} catch (Exception e) {
e.printStackTrace(); //e的作用域是catch块
}
}
public static void main(String[] args) {
test();
}
}


3.3 数据类型

Java 语言支持的数据类型分为两种:基本数据类型(Primitive Type)和引用数据类型(Reference Type)

3.3.1 基本数据类型

基本数据类型包括 boolean(布尔型)、float(单精度浮点型)、char(字符型)、byte(字节型)、short(短整型)、int(整型)、long(长整型)和 double(双精度浮点型)共8种

类型 关键字 占用内存 取值范围
字节型 byte 1字节 128~127
短整型 short 2字节 -32768~32767
整型 整型 4字节 -2147483648~2147483647
长整型 long 8字节 -9223372036854775808L~9223372036854775807L
单精度浮点型 float 4字节 +/-3.4E+38F(6~7 个有效位)
双精度浮点型 double 8字节 +/-1.8E+308 (15 个有效位)
字符型 char 2字节 ISO 单一字符集
布尔型 boolean 1字节 true 或 false

注意:在 Java 语言中,布尔类型的值不能转换成任何数据类型,true 常量不等于 1,而 false 常量也不等于 0。这两个值只能赋给声明为 boolean 类型的变量,或者用于布尔运算表达式中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package org.example;

public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

/**
* 整型
* byte:-128 ~ 127
* short: -32768 ~ 32767
* int: -2147483648 ~ 2147483647
* long: -9223372036854775808 ~ 9223372036854775807
*/
class Z {
public static void main(String[] args) {
int i = 2147483647;
int i2 = -2147483648;
int i3 = 2_000_000_000; // 加下划线更容易识别
int i4 = 0xff0000; // 十六进制表示的16711680
int i5 = 0b1000000000; // 二进制表示的512
long l = 9000000000000000000L; // long型的结尾需要加L
System.out.println("i = " + i);
System.out.println("i2 =" + i2);
System.out.println("i3 = " + i3);
System.out.println("i4 = " + i4);
System.out.println("i5 = " + i5);
System.out.println("l = " + l);
}
}

/**
* float:最大表示3.4x10^38
* double:最大表示1.79x10^308
*/
class F {
public static void main(String[] args) {
float f1 = 3.14f;
float f2 = 3.14e38f; // 科学计数法表示的3.14x10^38
double d = 1.79e308;
double d2 = -1.79e308;
double d3 = 4.9e-324; // 科学计数法表示的4.9x10^-324
System.out.println("f1 = " + f1);
System.out.println("f2 = " + f2);
System.out.println("d = " + d);
System.out.println("d2 = " + d2);
System.out.println("d3 = " + d3);
}
}

/**
* boolean只有true和false两个值
*/
class B {
public static void main(String[] args) {
boolean b1 = true;
boolean b2 = false;
boolean isGreater = 5 > 3; // 计算结果为true
int age = 12;
boolean isAdult = age >= 18; // 计算结果为false
System.out.println(isGreater);
System.out.println(isAdult);
}
}

3.3.2 引用数据类型

引用数据类型建立在基本数据类型的基础上,包括数组([ ])、类(class)和接口(interface)。引用数据类型是由用户自定义,用来限制其他数据的类型。


3.4 数据类型的转换

数据类型的转换可以分为隐式转换(自动类型转换)和显式转换(强制类型转换)两种。

3.4.1 隐式转换(自动类型转换)

如果以下2个条件都满足,那么将一种类型的数据赋给另外一种类型变量的时,将执行自动类型转换(automatic type conversion)。

  • 两种数据类型彼此兼容
  • 目标类型的取值范围大于源数据类型(低级类型数据转换成高级类型数据)

当以上2个条件都满足时,拓宽转换(widening conversion)发生。例如 byte 类型向 short 类型转换时,由于 short 类型的取值范围较大,会自动将 byte 转换为 short 类型。

在运算过程中,由于不同的数据类型会转换成同一种数据类型,所以整型、浮点型以及字符型都可以参与混合运算。自动转换的规则是从低级类型数据转换成高级类型数据。转换规则如下:

  • 数值型数据的转换:byte→short→int→long→float→double
  • 字符型转换为整型:char→int

以上数据类型的转换遵循从左到右的转换顺序,最终转换成表达式中表示范围最大的变量的数据类型。

1
2
3
4
5
6
7
8
public static void main(String[] args) {
float toothpaste_price = 12.5f;
double towel_price = 19.9;
int toothpaste_num = 2;
int towel_num = 3;
double count = toothpaste_price * toothpaste_num + towel_price * towel_num;
System.out.println("一共"+ count + "元"); // 一共84.69999999999999元
}

自动类型提升也会引起令人疑惑的编译错误,比如第二行会报“类型不匹配:无法从int转换为byte”错误:

1
2
byte b = 50;
b = b * 2; // Type mismatch: cannot convert from int to byte

该程序试图将一个完全合法的 byte 型的值 50x2 再存储给一个 byte 型的变量。但是当表达式求值的时候,操作数被自动的提升为 int 型,计算结果也被提升为 int 型。这样表达式的结果现在是 int 型,不强制转换它就不能被赋为 byte 型。

所以应该使用一个显示的强制类型转换,比如:

1
2
byte b = 50;
b = (byte)(b*2);

注意:char 类型比较特殊,char 自动转换成 int、long、float 和 double,但 byte 和 short 不能自动转换为 char,而且 char 也不能自动转换为 byte 或 short。

3.4.2 显式转换(强制类型转换)

所以当两种数据类型不兼容,或目标类型的取值范围小于源类型时,自动转换将无法进行,这时就需要进行强制类型转换

语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
(type)variableName

/**
* type:variableName要转换成的数据类型
* variableName:是指要进行类型转换的变量名称
*/

byte a = 5;
double b = 8;
a = (byte)b;
System.out.println("a=" + a); // a=8
System.out.println("b=" + b); // b=8.0
1
2
3
4
5
6
7
8
public static void main(String[] args) {
float toothpaste_price = 12.5f;
double towel_price = 19.9;
int toothpaste_num = 2;
int towel_num = 3;
double count2 = (int)(toothpaste_price * toothpaste_num + towel_price * towel_num);
System.out.println("一共"+ count2 + "元"); // 一共84.0元
}

3.5 运算符

最基本的运算符包括算术运算符、赋值运算符、逻辑运算符和关系运算符等。

按照操作数的数量可以分为单目运算符、双目运算符和三目运算符。

3.5.1 算数运算符

3.5.1.1 一元运算符
运算符 名称 说明 举例
- 取反符号 取反运算 b=-a
++ 自加一 先赋值再加一 或 先加一再赋值 a++ 或 ++a
-- 自减一 先赋值再减一 或 先减一再赋值 a-- 或 --a
1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
int a = 10;
System.out.println(-a); // -10
int b = a++;
System.out.println(a); // 11
System.out.println(b); // 10
b = ++a;
System.out.println(a); // 12
System.out.println(b); // 12
}
3.5.1.2 二元运算符
运算符 名称 说明 举例
+ 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 a + b
- 求 a 减 b 的差 a - b
* 求 a 乘以 b 的积 a * b
/ 求 a 除以 b 的商 a / b
% 取余 求 a 除以 b 的余数 a % b

算术运算符都是双目运算符,运算规则与数学运算中的规则是相同的。

3.5.1.3 算术赋值运算符
运算符 名称 说明 举例
+= 加赋值 相当于 a = a + b a += b、a += b+3
-= 减赋值 相当于 a = a - b a -= b
*= 乘赋值 相当于 a = a * b a *= b
/= 除赋值 相当于 a = a / b a /= b
%= 取余赋值 相当于 a = a % b a %= b

算术赋值运算符只是一种简写,一般用于变量自身的变化。

3.5.2 赋值运算符

赋值运算符是指为变量或常量指定数值的符号。赋值运算符的符号为“=”,它是双目运算符,左边的操作数必须是变量,不能是常量或表达式。

语法如下:

1
2
3
4
5
变量名称 = 表达式内容

/*
* “变量名称”和“表达式”内容的类型必须匹配,如果类型不匹配则需要自动转化为对应的类型。
*/

3.5.3 逻辑运算符

逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。逻辑运算符是对布尔型变量进行运算,其结果也是布尔型。

运算符 用法 含义 说明 实例 结果
&& a&&b 短路与 ab 全为 true 时,计算结果为 true,否则为 false。 2>1&&3<4 true
|| a||b 短路或 ab 全为 false 时,计算结果为 false,否则为 true。 2<1||3>4 false
! !a 逻辑非 a 为 true 时,值为 false,a 为 false 时,值为 true !(2>4) true
| a|b 逻辑或 ab 全为 false 时,计算结果为 false,否则为 true 1>2|3>5 false
& a&b 逻辑与 ab 全为 true 时,计算结果为 true,否则为 false 1<2&3<5 true
  • && 与 & 区别:如果 a 为 false,则不计算 b(因为不论 b 为何值,结果都为 false)
  • || 与 | 区别:如果 a 为 true,则不计算 b(因为不论 b 为何值,结果都为 true)
  • 短路与(&&)和短路或(||)能够采用最优化的计算方式,从而提高效率。在实际编程时,应该优先考虑使用短路与和短路或。

注意:逻辑运算符的优先级为:

  • !运算级别最高。!运算符的优先级高于算术运算符
  • && 运算高于 || 运算。 && 和 || 运算则低于关系运算符。
  • 结合方向是:逻辑非(单目运算符)具有右结合性,逻辑与和逻辑或(双目运算符)具有左结合性。

3.5.4 关系运算符

关系运算符(relational operators)也可以称为“比较运算符”,用于用来比较判断两个变量或常量的大小。关系运算符是二元运算符,运算结果是 boolean 型。当运算符对应的关系成立时,运算结果是 true,否则是 false。

运算符 含义
> 大于运算符
>= 大于或等于运算符
< 小于运算符
<= 小于或等于运算符
== 相等运算符
!= 不相等运算符

注意:关系运算符的优先级为:

  • >、<、>=、<= 具有相同的优先级,并且高于具有相同优先级的 !=、==。
  • 关系运算符的优先级高于赋值运算符而低于算术运算符,结合方向是自左向右。

由于计算机内存放的实数与实际的实数存在着一定的误差,如果对浮点数进行 ==(相等)或 !=(不相等)的比较,容易产生错误结果,应该尽量避免

3.5.5 自增自减运算符

++ 或 – 是单目运算符,放在操作数的前面或后面都是允许的。++ 与 – 的作用是使变量的值增 1 或减 1。操作数必须是一个整型或浮点型变量。

运算符 含义 实例 结果
i++ 将 i 的值先使用,再加 1 赋值给 i 变量本身 int i=1; int j=i++; i=2; j=1
++i 将 i 的值先加 1 赋值给变量 i 本身后,再使用 int i=1; int j=++i; i=2; j=2
i– 将 i 的值先使用,再减 1 赋值给变量 i 本身 int i=1; int j=i–; i=0; j=1
–i 将 i 的值先减 1 后赋值给变量 i 本身,再使用 int i=1; int j=–i; i=0; j=0

3.5.6 位运算符

Java 定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括 long,int,short,char 和 byte。

位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值。

Java 语言中的位运算符分为位逻辑运算符和位移运算符两类

3.5.6.1 位逻辑运算符

位逻辑运算符包含 4 个:&(与)、|(或)、~(非)和 ^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符

运算符 含义 运算规则 实例 结果
& 按位进行与运算(AND) 参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0 4 & 5 4
| 按位进行或运算(OR) 参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0 4 | 5 5
^ 按位进行异或运算(XOR) 参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1 4 ^ 5 1
~ 按位进行取反运算(NOT) 只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1 ~ 4 -5

注意:位运算符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。

3.5.6.2 位移运算符

位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数

运算符 含义 运算规则 实例 结果
» 右移位运算符 按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零 8»1 4
« 左移位运算符 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零 9«2 36
3.5.6.3 复合位赋值运算符

所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。复合位赋值运算符由赋值运算符与位逻辑运算符和位移运算符组合而成

运算符 含义 实例 结果
&= 按位与赋值 num1 &= num2 等价于 num 1=num 1 & num2
|= 按位或赋值 num1 |= num2 等价于 num 1=num 1 | num2
^= 按位异或赋值 num1 ^= num2 等价于 num 1=num 1 ^ num2
-= 按位取反赋值 num1 -= num2 等价于 num 1=num 1 - num2
«= 按位左移赋值 num1 «= num2 等价于 num 1=num 1 « num2
»= 按位右移赋值 num1 »= num2 等价于 num 1=num 1 » num2

3.5.7 条件运算符?:

Java 提供了一个特别的三元运算符(也叫三目运算符)经常用于取代某个类型的 if-then-else 语句。条件运算符的符号表示为“?:”,使用该运算符时需要有三个操作数,因此称其为三目运算符

语法如下:

1
2
3
4
5
6
7
result = <expression> ? <statement1> : <statement3>;

/*
* expression 是一个布尔表达式。
* 当 expression 为真时,执行 statement1, 否则就执行 statement3。
* 此三元运算符要求返回一个结果,因此要实现简单的二分支程序,即可使用该条件运算符。
*/

注意:在使用条件运算符时,还应该注意优先级问题

1
2
3
4
5
6
7
8
// 例如下面的表达式:
x>y ? x-=y : x+=y;

// 在编译时会出现语法错误,因为条件运算符优先于赋值运算符,上面的语句实际等价于:
(x>y ? x-=y : x)+=y;

// 而运算符“+=”是赋值运算符,该运算符要求左操作数应该是一个变量,因此出现错误。为了避免这类错误,可以使用括号“0”来加以区分。例如,下面是正确的表达式。
(x>y) ? (x-=y): (x+=y);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.Scanner;

public class HelloWorld {
public static void main(String[] args) {
int x, y, z; // 声明三个变量
System.out.print("请输入一个数:");
Scanner input = new Scanner(System.in);
x = input.nextInt(); // 由用户输入x的值
// 判断x的值是否大于5,如果是y=x,否则y=-x
y = x > 5 ? x : -x;
// 判断y的值是否大于x,如果是z=y,否则z=5
z = y > x ? y : 5;
System.out.printf("x=%d \n", x);
System.out.printf("y=%d \n", y);
System.out.printf("z=%d \n", z);
}
}

3.5.8 运算符优先级

一般而言,单目运算符优先级较高,赋值运算符优先级较低。算术运算符优先级较高,关系和逻辑运算符优先级较低。多数运算符具有左结合性,单目运算符、三目运算符、赋值运算符具有右结合性

Java 语言中运算符的优先级共分为 14 级,其中 1 级最高,14 级最低。在同一个表达式中运算符优先级高的先执行。

优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、– 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 «、»、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= 从右向左

注意:源代码就是一份文档,源代码的可读性比代码运行效率更重要。

  • 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
  • 不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序。

3.6 直接量

直接量是指在程序中通过源代码直接给出的值,例如在int a = 5;代码中,为变量 a 所分配的初始值 5 就是一个直接量。

3.6.1 直接量的类型

并不是所有的数据类型都可以指定直接量,能指定直接量的通常只有三种类型:基本类型、字符串类型和 null 类型。具体而言,Java 支持如下 8 种类型的直接量。

  • int 类型的直接量
    在程序中直接给出的整型数值,可分为二进制、十进制、八进制和十六进制 4 种,其中二进制需要以 0B 或 0b 开头,八进制需要以 0 开头,十六进制需要以 0x 或 0X 开头。例如 123、012(对应十进制的 10)、0x12(对应十进制的 18)等。

  • long 类型的直接量
    在整型数值后添加 l 或 L 后就变成了 long 类型的直接量。例如 3L、0x12L(对应十进制的 18L)。

  • float 类型的直接量
    在一个浮点数后添加 f 或 F 就变成了 float 类型的直接量,这个浮点数可以是标准小数形式,也可以是科学计数法形式。例如 5.34F、3.14E5f。

  • double 类型的直接量
    直接给出一个标准小数形式或者科学计数法形式的浮点数就是 double 类型的直接量。例如 5.34、3.14E5。

  • boolean 类型的直接量
    这个类型的直接量只有 true 和 false。

  • char 类型的直接量
    char 类型的直接量有三种形式,分别是用单引号括起来的字符、转义字符和 Unicode 值表示的字符。例如‘a’,‘\n’和‘\u0061’。

  • String 类型的直接量
    一个用双引号括起来的字符序列就是 String 类型的直接量。
    在大多数其他语言中,包括 C/C++,字符串作为字符的数组被实现。然而,在 Java 中并非如此。在 Java 中,字符串实际上是对象类型。在教程后面你将看到,因为 Java 对字符串是作为对象实现的,因此,它有广泛的字符串处理能力,而且功能既强又好用。

  • null 类型的直接量
    这个类型的直接量只有一个值,即 null。
    在上面的 8 种类型的直接量中,null 类型是一种特殊类型,它只有一个值:null。而且这个直接量可以赋给任何引用类型的变量,用以表示这个引用类型变量中保存的地址为空,即还未指向任何有效对象。

3.6.2 直接量的赋值

通常总是把一个直接量赋值给对应类型的变量,例如:

1
2
3
4
5
6
7
int a = 1;
char c = 'c';
boolean b = true;
float f = 3.12f;
double d = 4.23;
String name = "小明";
String url = "https://www.baidu.com/";
  • 除此之外,Java 还支持数值之间的自动类型转换,因此允许把一个数值直接量直接赋给另一种类型的变量,这种赋值必须是系统所支持的自动类型转换,例如把 int 类型的直接量赋给一个 long 类型的变量。

  • String 类型的直接量不能赋给其他类型的变量,null 类型的直接量可以直接赋给任何引用类型的变量,包括 String 类型。boolean 类型的直接量只能赋给 boolean 类型的变量,不能赋给其他任何类型的变量。

  • 关于字符串直接量有一点需要指出,当程序第一次使用某个字符串直接量时,Java 会使用常量池(constant pool)来缓存该字符串直接量,如果程序后面的部分需要用到该字符串直接量时,Java 会直接使用常量池(constantpool)中的字符串直接量。

注意

  • 由于 String 类是一个典型的不可变类,因此 String 对象创建出来的就不可能改变,因此无需担心共享 String 对象会导致混乱。
  • 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的 .class 文件中的一些数据,它包括关于类、方法、接口中的常量,也包括字符串直接量。