Java 基本语法
编写 Java 程序时,应注意以下几点:
- 大小写敏感:Java 是大小写敏感的,这就意味着标识符 Hello 与 hello 是不同的。
- 类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字母应该大写。
- 方法名:所有的方法名都应该以小写字母开头。如果方法名含有若干单词,则后面的每个单词首字母大写。
- 源文件名:源文件名必须和类名相同。当保存文件的时候,你应该使用类名作为文件名保存(切记 Java 是大小写敏感的),文件名的后缀为 .java。(如果文件名和类名不相同则会导致编译错误)。
- 主方法入口:所有的 Java 程序由 public static void main(String[] args) 方法开始执行。
Java 注释
用于对代码的介绍和说明,可以让人更加轻松的了解代码。
常见的注释风格:
- 单行注释
// 单行注释
- 多行注释
/*
* 这个是多⾏注释
*/
- 文档注释
/**
* 文档注释
* @author 晚倦清沐之秋
*/
Java 标识符
Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。
关于 Java 标识符,有以下几点需要注意:
- 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
- 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
Java 关键字
类别 | 关键字 | 说明 |
---|---|---|
访问控制 | private | 私有的 |
protected | 受保护的 | |
public | 公共的 | |
default | 默认 | |
类、方法和变量修饰符 | abstract | 声明抽象 |
class | 类 | |
extends | 扩充,继承 | |
final | 最终值,不可改变的 | |
implements | 实现(接口) | |
interface | 接口 | |
native | 本地,原生方法(非 Java 实现) | |
new | 新,创建 | |
static | 静态 | |
strictfp | 严格,精准 | |
synchronized | 线程,同步 | |
transient | 短暂 | |
volatile | 易失 | |
程序控制语句 | break | 跳出循环 |
case | 定义一个值以供 switch 选择 | |
continue | 继续 | |
do | 运行 | |
else | 否则 | |
for | 循环 | |
if | 如果 | |
instanceof | 实例 | |
return | 返回 | |
switch | 根据值选择执行 | |
while | 循环 | |
错误处理 | assert | 断言表达式是否为真 |
catch | 捕捉异常 | |
finally | 有没有异常都执行 | |
throw | 抛出一个异常对象 | |
throws | 声明一个异常可能被抛出 | |
try | 捕获异常 | |
包相关 | import | 引入 |
package | 包 | |
基本类型 | byte | 字节型 |
short | 短整型 | |
int | 整型 | |
long | 长整型 | |
float | 单精度浮点 | |
double | 双精度浮点 | |
char | 字符型 | |
boolean | 布尔型 | |
变量引用 | super | 父类,超类 |
this | 本类 | |
void | 无返回值 | |
保留关键字 | goto | 是关键字,但不能使用 |
const | 是关键字,但不能使用 |
注意:Java 的 null 不是关键字,类似于 true 和 false,它是一个字面常量,不允许作为标识符使用。
Java 修饰符
像其他语言一样,Java 可以使用修饰符来修饰类中方法和属性。主要有两类修饰符:
访问控制修饰符
Java 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。
- default (即默认,什么也不写):在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
- private:在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
- public:对所有类可见。使用对象:类、接口、变量、方法
- protected:对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
default | Y | Y | Y | N | N |
private | Y | N | N | N | N |
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N | N |
(1)默认访问修饰符-不使用任何关键字
① 使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public。
(2)私有访问修饰符-private
① 私有访问修饰符是最严格的访问级别,所以被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。
② 声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
③ private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。
(3)公有访问修饰符-public
① 被声明为 public 的类、方法、构造方法和接口能够被任何其他类访问。
② 如果几个相互访问的 public 类分布在不同的包中,则需要导入相应 public 类所在的包。由于类的继承性,类所有的公有方法和变量都能被其子类继承。
(4)受保护的访问修饰符-protected
① protected 需要从以下两个点来分析说明:
- 子类与基类在同一包中:被声明为 protected 的变量、方法和构造器能被同一个包中的任何其他类访问。
- 子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的 protected 方法。
② protected 可以修饰数据成员,构造方法,方法成员,不能修饰类(内部类除外)。
③ 接口及接口的成员变量和成员方法不能声明为 protected。
访问控制和继承
请注意以下方法继承的规则:
- 父类中声明为 public 的方法在子类中也必须为 public。
- 父类中声明为 protected 的方法在子类中要么声明为 protected,要么声明为 public,不能声明为 private。
- 父类中声明为 private 的方法,不能够被子类继承。
非访问控制修饰符
为了实现一些其他的功能,Java 也提供了许多非访问修饰符。
- static 修饰符,用来修饰类方法和类变量。
- final 修饰符,用来修饰类、方法和变量,final 修饰的类不能够被继承,修饰的方法不能被继承类重新定义,修饰的变量为常量,是不可修改的。
- abstract 修饰符,用来创建抽象类和抽象方法。
- synchronized 和 volatile 修饰符,主要用于线程的编程。
(1)static 修饰符
- 静态变量:
① static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。 静态变量也被称为类变量。局部变量不能被声明为 static 变量。
- 静态方法:
① static 关键字用来声明独立于对象的静态方法。静态方法不能使用类的非静态变量。静态方法从参数列表得到数据,然后计算这些数据。
对类变量和方法的访问可以直接使用 "类名.变量名" 和 "类名.方法名" 的方式访问。
(2)final 修饰符
- final 变量:
① final 表示"最后的、最终的"含义,变量一旦赋值后,不能被重新赋值。被 final 修饰的实例变量必须显式指定初始值。
② final 修饰符通常和 static 修饰符一起使用来创建类常量。
- final 方法
① 父类中的 final 方法可以被子类继承,但是不能被子类重写。
② 声明 final 方法的主要目的是防止该方法的内容被修改。
- final 类
① final 类不能被继承,没有类能够继承 final 类的任何特性。
(3)abstract 修饰符
- 抽象类:
① 抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。
② 一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。
③ 抽象类可以包含抽象方法和非抽象方法。
- 抽象方法:
① 抽象方法是一种没有任何实现的方法,该方法的具体实现由子类提供。
② 抽象方法不能被声明成 final 和 static。
③ 任何继承抽象类的子类必须实现父类的所有抽象方法,除非该子类也是抽象类。
④ 如果一个类包含若干个抽象方法,那么该类必须声明为抽象类。抽象类可以不包含抽象方法。
⑤ 抽象方法的声明以分号结尾。
(4)synchronized 修饰符
① synchronized 关键字声明的方法同一时间只能被一个线程访问。synchronized 修饰符可以应用于四个访问修饰符。
(5)volatile 修饰符
① volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值。而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
② 一个 volatile 对象引用可能是 null。
Java 数据类型
基本数据类型
Java 语言提供了八种基本类型。六种数值型(四个整数型,两个浮点型),一种字符型,还有一种布尔型。
分类 | 类型 | 占用字节空间大小 | 取值范围 | 默认值 |
---|---|---|---|---|
整数类型 | byte | 1字节(8 位) | -128 ~ 127 | 0 |
short | 2字节 | -32768 ~ 32767 | 0 | |
int | 4字节 | -2^31 ~ (2^31) - 1 | 0 | |
long | 8字节 | -2^63 ~ (2^63) - 1 | 0L | |
浮点类型 | float | 4字节 | 10^38 | 0.0f |
double | 8字节 | 10^308 | 0.0d | |
字符型 | char | 2字节 | 0 ~ 65535 | 'u0000' |
布尔型 | boolean | 视情况而定 | true、false | false |
(1)数值型
- 整数类型
- byte
- byte 数据类型是 8 位、有符号的,以二进制补码表示的整数
- 取值范围: -128(-2^7)~ 127(2^7-1)
- 默认值是 0
- byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一
- short
- short 数据类型是 16 位、有符号的以二进制补码表示的整数
- 取值范围: -32768(-2^15)~ 32767(2^15 - 1)
- 默认值是 0
- short 数据类型也可以像 byte 那样节省空间。一个 short 型变量是 int 型变量所占空间的二分之一
- int
- int 数据类型是 32 位、有符号的以二进制补码表示的整数
- 取值范围: -2,147,483,648(-2^31)~ 2,147,483,647(2^31 - 1)
- 默认值是 0
- 一般地整型变量默认为 int 类型
- long
- long 数据类型是 64 位、有符号的以二进制补码表示的整数
- 取值范围: -9,223,372,036,854,775,808(-2^63)~ 9,223,372,036,854,775,807(2^63 -1)
- 默认值是 0L( "L" 理论上不分大小写,但是若写成 "l" 容易与数字 "1" 混淆,不容易分辩。所以最好大写。)
- 这种类型主要使用在需要比较大整数的系统上
- 浮点类型
- float
- float 数据类型是单精度、32位、符合 IEEE 754 标准的浮点数
- float 在储存大型浮点数组的时候可节省内存空间
- 默认值是 0.0f
- 浮点数不能用来表示精确的值
- double
- double 数据类型是双精度、64 位、符合 IEEE 754 标准的浮点数
- 浮点数的默认类型为 double 类型
- 默认值是 0.0d
- double 类型同样不能表示精确的值
(2)字符型
- char
- char 类型是一个单一的 16 位 Unicode 字符
- 最小值是 \u0000(十进制等效值为 0)
- 最大值是 \uffff(即为 65535)
- char 数据类型可以储存任何字符
(2)布尔型
- boolean
- boolean 数据类型表示一位的信
- 只有两个取值:true 和 false
- 默认值是 false
- 这种类型只作为一种标志来记录 true/false 情况
引用数据类型
在 Java中,引用类型的变量非常类似于 C/C++ 的指针。引用类型指向一个对象,指向对象的变量是引用变量。这些变量在声明时被指定为一个特定的类型。变量一旦声明后,类型就不能被改变了。
引用数据类型非常多,大致包括:类、 接口类型、 数组类型。简单来说,所有的非基本数据类型都是引用数据类型。
所有引用类型的默认值都是 null。
注意:空引用(null)只能被转换成引用类型,不能转换成基本类型,因此不要把一个 null 值赋给基本数据类型的变量。
Java 变量
Java 语言支持的变量类型有:
- 类变量:独立于方法之外的变量,用 static 修饰。
- 实例变量:独立于方法之外的变量,不过没有 static 修饰。
- 局部变量:类的方法中的变量。
类变量(静态变量)
- 类变量也称为静态变量,在类中以 static 关键字声明,但必须在方法之外。
- 无论一个类创建了多少个对象,类只拥有类变量的一份拷贝。
- 静态变量除了被声明为常量外很少使用,静态变量是指声明为 public/private,final 和 static 类型的变量。静态变量初始化后不可改变。
- 静态变量储存在静态存储区。经常被声明为常量,很少单独使用 static 声明变量。
- 静态变量在第一次被访问时创建,在程序结束时销毁。
- 与实例变量具有相似的可见性。但为了对类的使用者可见,大多数静态变量声明为 public 类型。
- 默认值和实例变量相似。数值型变量默认值是 0,布尔型默认值是 false,引用类型默认值是 null。变量的值可以在声明的时候指定,也可以在构造方法中指定。此外,静态变量还可以在静态语句块中初始化。
- 静态变量可以通过:"类名.变量名" 的方式访问。
- 类变量被声明为 public static final 类型时,类变量名称一般建议使用大写字母。如果静态变量不是 public 和 final 类型,其命名方式与实例变量以及局部变量的命名方式一致。
实例变量
- 实例变量声明在一个类中,但在方法、构造方法和语句块之外。
- 当一个对象被实例化之后,每个实例变量的值就跟着确定。
- 实例变量在对象创建的时候创建,在对象被销毁的时候销毁
- 实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息。
- 实例变量可以声明在使用前或者使用后。
- 访问修饰符可以修饰实例变量。
- 实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见。
- 实例变量具有默认值。数值型变量的默认值是 0,布尔型变量的默认值是 false,引用类型变量的默认值是 null。变量的值可以在声明时指定,也可以在构造方法中指定。
- 实例变量可以直接通过变量名访问。但在静态方法以及其他类中,就应该使用完全限定名:"对象.变量名"。
局部变量
- 局部变量声明在方法、构造方法或者语句块中。
- 局部变量在方法、构造方法、或者语句块被执行的时候创建,当它们执行完成后,变量将会被销毁。
- 访问修饰符不能用于局部变量。
- 局部变量只在声明它的方法、构造方法或者语句块中可见。
- 局部变量是在栈上分配的。
- 局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
Java 运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java 也提供了一套丰富的运算符来操纵变量。我们可以把运算符分成以下几组:算术运算符、关系运算符、位运算符、逻辑运算符、赋值运算符、其他运算符。
(1)算术运算符
算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。
表格中的实例假设整数变量 A 的值为 10,变量 B 的值为 20:
操作符 | 描述 | 例子 |
---|---|---|
+ | 加法 - 相加运算符两侧的值 | A + B 等于 30 |
- | 减法 - 左操作数减去右操作数 | A – B 等于 -10 |
* | 乘法 - 相乘操作符两侧的值 | A * B 等于 200 |
/ | 除法 - 左操作数除以右操作数 | B / A 等于 2 |
% | 取余 - 左操作数除以右操作数的余数 | B % A 等于 0 |
++ | 自增: 操作数的值增加1 | B++ 或 ++B 等于 21 |
-- | 自减: 操作数的值减少1 | B-- 或 --B 等于 19 |
注意:
- 自增(++)自减(--)运算符是一种特殊的算术运算符,在算术运算符中需要两个操作数来进行运算,而自增自减运算符是一个操作数。
- 前缀自增自减法(++a,--a): 先进行自增或者自减运算,再进行表达式运算
- 后缀自增自减法(a++,a--): 先进行表达式运算,再进行自增或者自减运算
为了更好的理解前缀自增自减和后缀自增自减,首先初始变量 a、b、c、d 的值均为 10,并观察代码运行后的结果如下:
public static void main(String[] args) {
int a = 10;
// 先进行表达式运算,再进行自增运算
System.out.println(a++); // 10
int b = 10;
// 先进行自增运算,再进行表达式运算
System.out.println(++b); // 11
int c = 10;
// 先进行表达式运算,再进行自减运算
System.out.println(c--); // 10
int d = 10;
// 先自减运算运算,再进行表达式运算
System.out.println(--d); // 9
}
(2)关系运算符
用于数值的比较,不能是字符串等其他非数值。
表格中的实例假设整数变量 A 的值为 10,变量 B 的值为 20:
运算符 | 描述 | 例子 |
---|---|---|
== | 检查如果两个操作数的值是否相等,如果相等则条件为真。 | (A == B)为假。 |
!= | 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 | (A > B)为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 | (A < B)为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 | (A >= B)为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 | (A <= B)为真。 |
(3)位运算符
Java 定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。
下表列出了位运算符的基本运算,假设整数变量 A 的值为 60 和变量 B 的值为 13:
操作符 | 描述 | 例子 |
---|---|---|
& | 如果相对应位都是 1,则结果为 1,否则为 0 | (A & B)得到 12,即 0000 1100 |
| | 如果相对应位都是 0,则结果为 0,否则为 1 | (A | B)得到 61,即 0011 1101 |
^ | 如果相对应位值相同,则结果为 0,否则为 1 | (A ^ B)得到 49,即 0011 0001 |
〜 | 按位取反运算符翻转操作数的每一位,即 0 变成 1,1 变成 0。 | (〜A)得到 -61,即 1100 0011 |
<< | 按位左移运算符。左操作数按位左移右操作数指定的位数。 | (A << 2)得到 240,即 1111 0000 |
>> | 按位右移运算符。左操作数按位右移右操作数指定的位数。 | (A >> 2)得到 15,即 1111 |
>>> | 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 | (A >>> 2)得到 15,即 0000 1111 |
注:以下都是以计算机字长为 8 位的二进制举例。
Ⅰ. 原码、反码、补码
原码:是一种计算机中对数字的二进制定点表示方法,原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为 0,负数该位为 1(0有两种表示:+0 和 -0),其余位表示数值的大小。
十进制 +60 原码:0011 1100
十进制 -60 原码:1011 1100
反码:正数的反码是其原码本身;负数的反码是在其原码的基础上,符号位不变,其余各个位取反(1 -> 0,0 -> 1)。
十进制 +60 反码:0011 1100
十进制 -60 反码:1100 0011
补码:正数的补码就是其原码本身;负数的补码是在其原码的基础上,符号位不变, 其余各位取反(1 -> 0,0 -> 1),最后 +1。
十进制 +60 补码:0011 1100
十进制 -60 补码:1100 0100
已知一个数的补码,求原码的操作,有 2 种方法:
① 符号位不变,补码减 1 再取反。
十进制 +60 补码:0011 1100 ----> 正数反码、补码是原码本身,故原码就是 0011 1100
十进制 -60 补码:1100 0100 ----> 减 1:1100 0011 ----> 取反:1011 1100(原码)
② 符号位不变,对该补码再求补码,也就是补码取反再加 1。
十进制 +60 补码:0011 1100 ----> 正数反码、补码是原码本身,故原码就是 0011 1100
十进制 -60 补码:1100 0100 ----> 取反:1011 1011 ----> 加 1:1011 1100(原码)
Ⅱ. 位运算符操作
- 按位与:&
位与运算符为 &,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。
- 按位或:|
位或运算符为 |
,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1。
- 按位异或:^
位异或运算符为 ^,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。
- 按位非:~
位取反运算符为 ~
,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。
- 左位移:<<
左移位运算符为 <<,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
- 右位移:>>
右位移运算符为 >>,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。