之前一直对 Java 怀有固执的偏见,以为 Java 是编写前端的语言,作为一个机械生,非常抗拒去学它。 但是最近接触一点以后,完全改观了先前的看法,于是开启了对 Java 的大学习。
之前一直对 Java 怀有固执的偏见,以为 Java 是编写前端的语言,作为一个机械生,非常抗拒去学它。
但是最近接触一点以后,完全改观了先前的看法,于是开启了对 Java 的大学习。
一、数据1.1 标识符
- 由数字、字母、美元符号($)、下划线以及Unicode字符集中符号大于0xc0的所有符号组合构成。
- 以字母、下划线、美元符号开头。
- 区分大小写。
- 不能使用任何 Java 关键字作为标识符,而且不能赋予标识符任何标准的方法名。
1.1.1 关键字
Java 语言目前定义了 51 个关键字,这些关键字不能作为变量名、类名和方法名来使用。以下对这些关键字进行了分类。
- 数据类型:boolean、int、long、short、byte、float、double、char、class、interface。
- 流程控制:if、else、do、while、for、switch、case、default、break、continue、return、try、catch、finally。
- 修饰符:public、protected、private、final、void、static、strict、abstract、transient、synchronized、volatile、native。
- 动作:package、import、throw、throws、extends、implements、this、supper、instanceof、new。
- 保留字:true、false、null、goto、const。
1.1.2 常量
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;
}
}
在定义常量时,需要注意如下内容:
- 在定义常量时就需要对该常量进行初始化。
- final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。
- 常量命名全大写。
1.1.3 变量
- 变量标识符的命名规范如下:
- 由数字、字母、下划线、美元符号($)、人民币符号(¥)以及所有在十六进制 0xc0 前的 ASCII 码组成。
- 字母、下划线、美元符号($)或者人民币符号(¥)开头。
- 不能把关键字、保留字作为标识符。
- 区分大小写。
Java 中初始化变量时需要注意以下事项:
- 变量是类或者结构中的字段,如果没有显式地初始化,默认状态下创建变量并默认初始值为 0。
- 方法中的变量必须显式地初始化,否则在使用该变量时就会出错。
名称 | 修饰 | 访问 | 生命周期 |
全局变量 (实例变量) | 无 | 对象名.变量名 | 只要对象被当作引用,实例变量就将存在 |
静态变量 (类变量) | 用 static 修饰 | 类名.变量名 or 对象名.变量名 | 其生命周期取决于类的生命周期。 类被垃圾回收机制彻底回收时才会被销毁 |
例如,变量声明代码如下所示:
public class DataClass {
String name; // 成员变量、实例变量
int age; // 成员变量、实例变量
static final String website = "C语言中文网"; // 成员变量、静态变量(类变量)
static String URL = "http://c.biancheng.net"; // 成员变量、静态变量(类变量)
}
测试类代码如下所示:
public class Test {
public static void main(String[] args) {
// 创建类的对象
DataClass dc = new DataClass();
// 对象名.变量名调用实例变量(全局变量)
System.out.println(dc.name);
System.out.println(dc.age);
// 对象名.变量名调用静态变量(类变量)
System.out.println(dc.website);
System.out.println(dc.URL);
// 类名.变量名调用静态变量(类变量)
System.out.println(DataClass.website);
System.out.println(DataClass.URL);
}
}
运行效果:
(此例引自 C语言中文网)
1.2 数据类型
1.2.1 基本数据类型
类型名称 | 关键字 | 占用内存 | 取值范围 |
字节型 | byte | 1 字节 | -128~127 |
短整型 | short | 2 字节 | -32768~32767 |
整型 | int | 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 |
1.2.2 引用数据类型
引用数据类型是有用户自定义,用来限制其他数据的类型,
包括class(类)、interface(接口)、[](数组),
不支持C++中的指针类型、结构类型、联合类型、枚举类型。
所谓引用数据类型就是对一个对象的引用,对象包括实例和数组两种。实际上,引用类型就是一个指针,只是Java语言里不再使用指针这个说法。
注意:null(空引用)只能赋给引用数据类型。
1.2.3 数据类型转换
(1)隐式转换(自动类型转换)
条件:
- 两种数据类型兼容
- 低转高
如,数值型数据的转换:byte→short→int→long→float→double。
字符型转换为数值型:char→int→long→float→double。
注意:自动类型提升有好处,但它也会引起令人疑惑的编译错误。
例如,下面看起来正确的程序却会引起问题:
byte b = 50;
b = b * 2; // Type mismatch: cannot convert from int to byte
如上所示,第二行会报“类型不匹配:无法从int转换为byte”错误。
该程序试图将一个完全合法的 byte 型的值 50*2 再存储给一个 byte 型的变量。但是当表达式求值的时候,操作数被自动的提升为 int 型,计算结果也被提升为 int 型。这样表达式的结果现在是 int 型,不强制转换它就不能被赋为 byte 型。
所以应该使用一个显示的强制类型转换,例如:
byte b = 50;
b = (byte)(b*2);
这样就能产生正确的值 100。
(2)显式转换(强制类型转换)
如,上一个例程。
1.3 直接量的类型
直接量:在程序中通过源代码直接给出的值,例如在代码
int a = 5;
中,为变量 a 所分配的初始值 5 就是一个直接量。
并不是所有的数据类型都可以指定直接量,能指定直接量的通常只有三种类型:基本类型、字符串类型和 null 类型。具体而言,Java支持如下 8 种类型的直接量。
1)int 类型的直接量
在程序中直接给出的整型数值,可分为二进制、十进制、八进制和十六进制 4 种,其中二进制需要以 0B 或 0b 开头,八进制需要以 0 开头,十六进制需要以 0x 或 0X 开头。例如 123、012(对应十进制的 10)、0x12(对应十进制的 18)等。
2)long 类型的直接量
在整型数值后添加 l 或 L 后就变成了 long 类型的直接量。例如 3L、0x12L(对应十进制的 18L)。
3)float 类型的直接量
在一个浮点数后添加 f 或 F 就变成了 float 类型的直接量,这个浮点数可以是标准小数形式,也可以是科学计数法形式。例如 5.34F、3.14E5f。
4)double 类型的直接量
直接给出一个标准小数形式或者科学计数法形式的浮点数就是 double 类型的直接量。例如 5.34、3.14E5。
5)boolean 类型的直接量
这个类型的直接量只有 true 和 false。
6)char 类型的直接量
char 类型的直接量有三种形式,分别是用单引号括起来的字符、转义字符和 Unicode 值表示的字符。例如‘a’,‘\n’和‘\u0061’。
7)String 类型的直接量
一个用双引号括起来的字符序列就是 String 类型的直接量。
注意:Java 会使用常量池(constant pool)来缓存该字符串直接量,如果程序后面的部分需要用到该字符串直接量时,Java 会直接使用常量池(constantpool)中的字符串直接量。
因此,
- 由于 String 类是一个典型的不可变类,因此 String 对象创建出来的就不可能改变,因此无需担心共享 String 对象会导致混乱。
- 常量池(constant pool)指的是在编译期被确定,并被保存在已编译的 .class 文件中的一些数据,它包括关于类、方法、接口中的常量,也包括字符串直接量。
在大多数其他语言中,包括 C/C++,字符串作为字符的数组被实现。然而,在 Java 中并非如此。在 Java 中,字符串实际上是对象类型。在教程后面你将看到,因为 Java 对字符串是作为对象实现的,因此,它有广泛的字符串处理能力,而且功能既强又好用。
8)null 类型的直接量
这个类型的直接量只有一个值,即 null。可以赋给任何引用类型的变量,用以表示这个引用类型变量中保存的地址为空,即还未指向任何有效对象。
二、运算符这边介绍与C语言不同的地方。
关系运算符
运算符 | 含义 | 说明 | 实例 | 结果 |
== | 相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。Java 也支持两个 boolean 类型的值进行比较。 | 4 == 4 97 == 'a' 5.0 == 5 true==false | true true true false |
!= | 不相等运算符 | 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。 如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。 | 4!=2 | true |
注意点如下所示:
- 基本类型的变量、值不能和引用类型的变量、值使用 == 进行比较;boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较;如果两个引用类型之间没有父子继承关系,那么它们的变量也不能使用 == 进行比较。
- == 和 != 可以应用于基本数据类型和引用类型。当用于引用类型比较时,比较的是两个引用是否指向同一个对象,但当时实际开发过程多数情况下,只是比较对象的内容是否相当,不需要比较是否为同一个对象。
关于String类型的不可变性:
String s0 = "hello";
String s1 = "hello";
String s2 = "he" + "llo";
System.out.println(s0 == s1);
System.out.println(s0 == s2);
运行结果为:
true
true
Java 会确保每个字符串常量只有一个,不会产生多个副本。例子中的 s0 和 s1 中的“hello”都是字符串常量,它们在编译期就被确定了,所以 s0 = s1
返回 true。而“he”和“llo”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它本身也是字符串常量,s2 同样在编译期就被解析为一个字符串常量,所以 s2 也是常量池中“hello”的引用。因此,程序输出 s0 == s1
返回 true,s1 == s2
也返回 true。
逻辑运算符
&&(短路与):&(逻辑与)的优化,前面是false
就不算后面
||(短路或):|(逻辑或)的优化,前面是true
就不算后面
位逻辑运算符
运算符 | 含义 | 实例 | 结果 |
& | 按位进行与运算(AND) | 4 & 5 | 4 |
| | 按位进行或运算(OR) | 4 | 5 | 5 |
^ | 按位进行异或运算(XOR) | 4 ^ 5 | 1 |
~ | 按位进行取反运算(NOT) | ~ 4 | -5 |
要注意的是,Java中的位运算符跟C中不一样,位逻辑运算符是单个&和|,而不是&&和||;
相反,在布尔逻辑运算符中,&&和||比单个&和|效率都要高,是为首选。
优先级
优先级 | 运算符 | 结合性 |
1 | ()、[]、{} | → |
2 | !、+、-、~、++、-- | ← |
3 | *、/、% | → |
4 | +、- | → |
5 | <<、>>、>>> | → |
6 | <、<=、>、>=、instanceof | → |
7 | ==、!= | → |
8 | & | → |
9 | ^ | → |
10 | | | → |
11 | && | → |
12 | || | → |
13 | ?: | ← |
14 | =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= | ← |
单行注释 //
多行注释 /* balabala */
文档注释 /** balabala */ 写在类、方法、变量上面,引用处鼠标碰到会自动显示
学习资料C语言中文网