-- 基础 --
特点
- 强类型语言: 变量必须声明数据类型, 且变量的数据类型不可被改变
- 赋值: java的赋值有返回值, 返回值即赋的值(等号右边的值)
- 字符: 单引号代表单个字符, 而双引号代表一个字符串
- 条件表达式: 判断语句只能接受布尔值, 连0和1都不能接收
- 版本: JDK1.0 JDK1.1 JDK1.2 JDK1.5(Java5) Java6 Java7 Java8 Java11 Java17 Java21
源文件
- 源文件与类: 文件中只能有一个
public外部类(且该类的名称与文件要相同), 可以有多个非public外部类 - 源文件程序开始: Java程序从包含
public static void main(String[] args)方法的类开始执行
注: main方法只能由public static修饰符修饰, 且返回值只能是void - 源文件编译:
javac 文件名编译后生成.class文件(数量为外部类+内部类的数量), 为 java 的字节码文件
注: 编译并不是只会生成public外部类的类名.class文件, 还会生成其它所有类的, 其中内部类为外部类名$内部类名.class - 源文件执行:
java 类的全限定名 - 命令行参数:在命令行使用
java命令执行Java程序时传入的参数, 会作为字符串数组传递给main方法的String[] args形参, 可以通过args数组来访问这些命令行参数
指令
javac <java源文件>
作用:编译.java文件(生成.class字节码文件)
-d <目录> 指定生成.class文件的存放目录
-cp <classpath> 指定编译时的(临时)类路径,若不指定该选项则会读取CLASSPATH环境变量
-source <release> 指定源代码的版本
-target <release> 指定生成的字节码的目标版本
java <类的全限定名> [args...]
作用:运行编译好的.class字节码文件(会启动一个JVM实例,并在该实例中加载并执行该类的main方法),args为传递给main方法的命令行参数
-cp <classpath> 指定运行时的(临时)类路径,若不指定该选项则会读取CLASSPATH环境变量
-D<系统属性>=<值> 更改运行时的系统属性(更改多个系统属性需要多个-D)
-jar 运行可执行jar文件,类的全限定名 变为 jar文件路径
jar {c t x u}[f v m e 0 M i ][-C 目录]文件名...
作用:创建 查看 提取 Java归档文件(.jar文件)
其中{ctxu}这四个参数必须选选其一 [v f m e 0 M i ]是可选参数
-c 创建一个jar包
-t 显示jar中的内容列表
-x 解压jar包
-u 添加文件到jar包中
-f 指定jar包的文件名
-v 生成详细的报告,并输出至标准设备 (控制台)
-m 指定manifest.mf文件(manifest.mf文件中可以对jar包及其中的内容作一些一设置)
-0 产生jar包时不对其中的内容进行压缩处理
-M 不产生所有文件的清单文件(Manifest.mf),这个参数与忽略掉-m参数的设置
-i 为指定的jar文件创建索引文件
-C 表示转到相应的目录下执行jar命令,相当于cd到那个目录,然后不带-C执行jar命令
基础操作
- 注释:单行
//多行/* */文档注释/** */ - 变量声明:
<数据类型> <变量> [ = <值>][, <变量> [= <值>] ...] ;
var <变量> = <值>(var声明会自动判断数据类型, >java 10) - 常量声明:
final <数据类型> <变量> [ = <值>][, <变量> [= <值>] ...] ; - 类型转换:
(数据类型)数据
浮点数->整数 舍弃小数 而非四舍五入
字符->数字 使用Unicode码对应数字 - 自动类型转换:
运算时不同类型数据先转化为同一类型, 然后进行运算(boolean 无法转换)
byte,short,char—> int —> long—> float —> double (转换从低级到高级) - 循环:
while( 布尔表达式 ) {
//循环内容
}
-- -- -- -- -- -- -- -- --
do {
//代码语句
}while(布尔表达式);
-- -- -- -- -- -- -- -- --
for(初始化; 布尔表达式; 更新) {
}
-- -- -- -- -- -- -- -- --
>=java5
for(声明语句 : 表达式) { //类似于foreach
//声明语句声明新的局部变量,该变量的类型必须和数组元素的类型匹配,其作用域限定在循环语句块,其值与此时数组元素的值相等
//表达式是要访问的数组名,或者是返回值为数组的方法
//代码句子
}
-- -- -- -- -- -- -- -- --
break 跳出最里层的一层循环
continue 跳转到下一次循环
- 条件语句
if(布尔表达式 1){
//如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
//如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
//如果布尔表达式 3的值为true执行代码
}else {
//如果以上布尔表达式都不为true执行代码
}
-- -- -- -- -- -- -- -- --
switch(expression){
case value :
// 语句
break; // 可选,若没有break,会执行后面的case语句
case value :
// 语句
break; // 可选,若没有break,会执行后面的default语句
default : // 可选
// 语句
}
-- -- -- -- -- -- -- -- --
布尔表达式?表达式1:表达式2;
注:判断语句只能接受布尔值, 连0和1都不能接收
运算符
- 算数运算符:
加+ 减- 乘* 除/ 取模%及其 复合赋值运算符+= -= *= /= %= - 自增/自减运算符:
++x --x y++ y-- - 关系运算符:
等于== 不等于!= 大于> 小于< 大于等于>= 小于等于<=(java没有强等于) - 逻辑运算符:
与 &&;或 ||;非 ! - 位运算符:
与& 或| 异或^ 取反~ 左移<< 右移>> 无符号右移>>>及其复合赋值运算符(略) - 三元运算符:
表达式1 ? 表达式2 : 表达式3 - instanceof运算符
使用:<对象> instanceof <类或接口>
介绍: 若对象, 是操作符右侧类/接口自身或子类的一个实例, 那么返回true
作用:- 类型转换前检查数据类型, 以防报错(若转换成的数据类型 非 当前数据类型的子类, 则报错)
- 进行多态处理(根据对象类型执行不同逻辑)
- 泛型类型擦除后的补救
- 等等 使用规则:
- instanceof 不能用于基础数据类型(只能用于对应的 引用型类型)
- 如果 对象 是 null, 则直接返回false
基本数据类型
- 基本数据类型: byte short int long float double boolean char
byte: 8位, 有符号, 默认值为0-128(-2^7) ->127(2^7-1)
short: 16位, 有符号, 默认值为0-32768(-2^15) -> 32767(2^15-1)
int: 32位, 有符号, 默认值为0-2^31 -> 2^31-1
long: 64位, 有符号, 默认值为0L-2^63 -> 2^63-1
float: 32位, 单精度, 默认值为0.0f
double: 64位, 双精度, 默认值位0.0d boolean: 只有true和flase两个值, 默认值为false
char: 储存单一16位Unicode字符, 默认值为 \'u0000\'
注:字面量中整数的默认类型是int,小数默认是double
注:要想字面量为long 值后面要加上l/L, float值后要加上f/F, double值后要加上d/D(可选)
声明但未初始化的变量的值为默认值,声明但未初始化的数组的元素值为默认值 - 引用类型: 对象 数组 (默认值为null)
- 传递:
基本数据类型是值传递,
引用类型变量传递的为本身的副本,但副本也指向同一个对象,本质也为值传递
(Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用)
变量
-
变量: 局部变量 实例变量(非静态变量) 类变量(静态变量) 参数变量(即形参)
局部变量: 在方法, 构造方法 或 语句块 中定义的变量- 在声明的方法、构造函数 或 块 执行结束后被销毁
- 局部变量在声明后需要初始化后才能使用,否则会导致编译错误
实例变量: 声明在类中, 方法、构造函数 或 块之外的变量
- 在创建对象的时候实例化, 实例变量值不共享, 可被类中方法、构造方法 和 特定类的语句块 访问
- 可不初始化就使用, 会被赋予相关数据类型的默认值
类变量: 类变量也声明在类中,方法、构造函数 或 块之外,但必须声明为 static 类型
- 同一个类的所有实例共享同一个类变量的值, 可被类中方法、构造方法 和 特定类的语句块 访问
- 可不初始化就使用, 会被赋予相关数据类型的默认值
修饰符
- 访问修饰符(从严到松):
private : 在同一类内可见 使用对象:字段、方法、内部类(外部类不可用)
default(即什么也不写): 对同一包内的类可见 使用对象:类、接口、字段、方法
protected : 对同一包内的类 和 所在类的所有子类(包括不同包的)可见 使用对象:字段、方法、内部类(外部类不可用)
public : 对所有类可见 使用对象:类、接口、字段、方法 - final关键字:
可使用对象:变量(包括类属性、对象属性、局部变量和形参),方法(包括类方法和对象方法)和类
修饰类:类不能被继承
修饰方法:方法不能被子类重写
修饰变量:定义常量 - static关键字:
可使用对象:类属性 类方法 代码块 import导入 内部类
修饰类属性(静态变量):使属性属于类,可通过类名直接访问,该类创建的所有实例共享该变量的值
修饰方法(静态方法):可通过类名直接访问,在静态方法中只能访问静态成员,且无法使用this关键字,直接用对应名称即可(可以通过实例来访问静态方法,但不推荐)
修饰代码块(静态代码块):用于初始化静态变量,在类首次被加载时执行一次(如第一次调用类的静态方法或静态变量之前 或 第一次创建类的实例之前), 且无法使用this关键字,直接用对应名称即可
修饰import:可导入特定/全部的静态成员
修饰内部类:使内部类可以访问外部类的静态变量与静态方法
类与对象
- 创建类:
[修饰符] class 类名{} - 继承:
[修饰符] class 类名 extends 要继承的类名{}
[修饰符] class 类名 implements 接口,... { }
作用: 继承父类非private的属性和方法 (静态字段/方法也会继承, 但子类静态字段与父类的指向不同)
多继承: 不支持多继承, 一次只能继承一个类(用extends), 但可做到多继承接口(用implements)
构造方法: 不会继承父类的构造方法
特点: 所有的类都是继承于 java.lang.Object,当一个类没有继承的两个关键字,则默认继承 Object - 构造方法:
定义: 必须与类同名, 不用写返回值类型(因为没有返回值)
特点: 创建对象时,若没有显式地定义构造方法,编译器将会为该类提供一个默认的构造方法
构造方法链: 可在构造方法中用this(参数)来调用其它构造方法, 使得创建对象时使用多个构造方法 - 方法重载: 同一个类中可设定多个同名方法, 但形参列表不同(数据类型 顺序或数量不同), 访问方法时会根据传入的实参(数据类型 顺序或数量)来自动判断运用哪个方法(类的方法也可在子类中被重载)
- 方法重写: 在方法前一行加上
@Override(可不加),子类中可重新定义继承自父类的同名方法
条件:
方法名相同 参数列表相同 返回类型必须相同或为父类返回类型的子类型(<=java5) 返回值可以不同(>=java7)
访问修饰符不能比父类方法更严格 不能抛出比父类方法更广泛的检查异常
final方法不能被重写,static方法无法被重写但能被再次声明
无法重写构造方法(因为不会继承构造方法) - 父类引用指向子类对象:
父类名 变量1 = new 子类();
特点: java 中可以用 父类 引用指向 子类对象, 也可以指向子类的子类 ...
特点:使得 可以通过该引用 访问 子类从父类继承的 成员变量 与 方法, 而不能访问子类特有的 成员变量 与 方法
特点: 对于被子类重写后的方法, 通过该引用 访问的是 重写后的方法
特点: 可通过子类名 变量2 = (子类名)变量1;来再将类型变回子类引用 - this关键字: 代表当前对象自身
调用所在类的字段与方法(在方法体中):this.字段和this.方法(...)此时可省略this, 当形参与成员名重名时才需加上this以区分
调用所在类的其它构造方法(在构造方法体中):this(...)应为所在构造函数的第一条语句
返回当前对象(实现链式调用):return this - super关键字: 代表当前对象的父类实例部分
调用从父类继承的非private字段与方法(在方法体中):super.字段和super.方法(...)
此时可省略super, 当子类字段与父类字段重名时 或 父类方法被子类重写时 才需加上super以区分
子类中调用的父类的方法时 其中的字段/方法()与this.字段/方法()与super.字段/方法与在子类中使用相同内容的效果相同
调用父类的构造函数(在构造方法体中):super(...)
子类中调用的父类的方法时 其中的字段/方法()与this.字段/方法()与super.字段/方法与在子类中使用效果相同
应为所在构造函数的第一条语句
调用子类构造函数时, 若检测到没用super(...)调用父类构造方法, 系统会自动调用父类的无参数构造方法(相当于在第一行加上super()) - 实例化:
类名 变量 = new 类名(形参)
创建实例数组:类名[] 变量 = new 类名[] {实例,...} - 访问实例:
实例变量.成员 - 抽象类/方法: 通过在类/方法的定义前(修饰符后)加上 abstract 关键词以声明
抽象类特点: 抽象类 不能用 new 创建对象(实例化), 必须被继承, 才能被使用
抽象类的方法: 抽象类 中可以有 构造方法 正常方法 与 抽象方法
抽象方法特点: 抽象方法不包含方法体(即没有花括号即其内的内容), 且只能存在于 抽象类中, 构造方法 与 类方法 不能声明为 抽象方法
抽象方法的实现: 抽象方法所在抽象类的子类 必须为 抽象类 或 重写了所有从 父类继承来的抽象方法(抽象方法的实现) - 代码块:
普通: 在类中没有任何修饰的代码块, 其内容会在实例化时执行(并且先于构造函数执行)
静态代码块: 在类被第一次加载时执行(如第一次调用类的静态方法或静态变量之前 或 第一次创建类的实例之前) - 内部类与外部类:
概念: 在类中定义的类, 叫内部类, 而包含该内部类的类叫外部类
特点: 内部类可以使用外部类的成员变量(包括私有) - 多态: 概念, 同一个接口, 使用不同的实例而执行不同操作(功能), 常用 继承 重写 父类引用指向子类对象 接口 抽象类/方法 来实现
- 封装: 概念, 将对象的 成员变量 私有化(private), 在对象外部通过公共(public)方法访问 这些成员变量
- 单例模式: 概念, 将构造方法设置为私有的, 在私有静态属性N中储存实例, 利用静态方法返回该静态属性(若N为空则创建实例存储在N中)
作用: 保证了从头到尾只有一个实例, 对于全局只想进行一次并维持结果(因为类属性不会像对象一样被销毁)的操作 可利用单例模式
方法
- 定义:
[修饰符] 返回值类型 方法名(参数数据类型 形参名){方法体}
[修饰符] abstract 返回值类型 方法名(参数数据类型 形参名)(抽象方法)
返回值类型写 void 表示无返回值, 返回值在函数体中用return返回 - 特点: Java函数的变量无法设置默认值, 只能通过重载来实现类似默认值的效果
- 可变参数(JDK>=1.5): 在指定参数类型后加一个省略号(...)
限制: 一个方法中只能指定一个可变参数,且它必须是方法的最后一个参数
特点: 可变参数意味着调用该方法时可传入符合数据类型 零个或多个实参, 而形参会变为储存所有实参值的数组
接口
- 声明:
[修饰符] interface 接口名{接口体} - 特点:
接口与抽象类 类似, 接口内也能定义方法, 接口是抽象的, 不能实例化对象, 并且也没有构造方法
接口是 隐式 抽象的, 无需使用 abstract 关键字
接口没有构造函数 - 方法:
接口内的方法 都会被 隐式地 指定为 public abstract
不能显示地指定 public abstract 以外的方法
所以重写接口方法不能使用除public以外修饰符(java<8)
java>8 后, 可以使用 default 显式地定义非抽象的方法 - 成员变量(字段):
接口内的变量 都会被 隐式地 指定为 public static final
不能显示地指定 public static final 以外的变量
所以接口的成员变量一般被定义为常量, 或用于存储配置信息 - 接口的实现:
接口由类来实现, 类通过implements关键字继承的方式来实现接口
类实现接口时, 必须实现接口中的所有方法 或者 声明为抽象类 - 继承:
[修饰符] interface 接口名 [extends 其它接口名,...]{接口体}
接口可以同时继承多个接口 (接口继承接口用extends, 类实现接口用implements) - 特点
类在实现接口的方法时, 不能抛出强制性异常, 只能在接口中, 或者继承接口的抽象类中抛出该强制性异常
实现类可以抛出异常, 但不能抛出比接口方法声明的异常更宽泛的受检查异常
一个类可以同时实现多个接口, 但只能继承一个类
包装类
- 作用: 为方便, 有时我们需要使用对象, 而不是内置数据类型, 而Java 语言为每一个内置数据类型提供了对应的包装类(引用型类型), 使得可以将基础数据类型的值转化为对象
- 使用(装箱): 将基础数据类型的值转化为对象
包装类 变量 = new 包装类(基本数据类型的值)基础操作
var 变量 = new 包装类(基本数据类型的值)会自动判断数据类型
包装类 变量 = 基本数据类型的值会自动转化为对象 - 使用(拆箱): 将对象转化为基础数据类型的值
基础数据类型 变量 = 对象基础操作
包装类 与对应 基础数据类型
Byte-byte Short-short Integer-int Long-long
Float-float Double-double Boolean-boolean Character-char
- 包装类 Integer Long Byte Double Float Short 是抽象类 Number 的子类, Number 类属于 java.lang 包
- Number类及子类使用方法是直接 类.方法() 无需加入参数, 而Math类使用方法是 Math.方法(数值)
包
- 包名(全限定名): 包名通常使用小写字母, 并使用点号分隔, 包名通常与目录结构对应(包括内部包和外部包)
- package 语句: 声明类所在的包, 若使用, 它应该是 Java 源文件中的第一个语句(除了注释)
package 包名;添加到包中 (注: 该行语句同时带有类似于import 包名.*;的效果) - import 语句: 导入其他包中的类, 使得可以在当前文件中使用这些类而不需要写出它们的完全限定名
import 包名.类名,...;导入类import 包名.*;导入所有类
import 语句应该放在 package 和类定义之间, 若没有 package, 则import 应该在最前面
注: 只能引入编译后的 .class 文件 - 系统包
java.lang - 基础的类(只有java.lang包会自动引入)
java.io - 包含输入输出功能的函数 - 路径: 类目录的绝对路径叫做 class path, 设置在系统变量CLASSPATH中
编译器和 java 虚拟机通过将 package 名字加到 class path 后来构造 .class 文件的路径
注: 若无CLASSPATH系统变量, 则默认为.和JDK的lib路径 - 注意: import和package对源文件中定义的所有类都有效, 同一源文件中,不能给不同的类不同的包声明
泛型
- 概念: 相当于参数化类型, 即为将数据类型当作一个参数
注: 泛型只能代表 引用数据类型, 而不能代表基础数据类型(得用对应的包装类) - 泛型格式:
<泛型标记符 [上/下通配符]> - 泛型标记符(约定命名):
E - Element 集合
T - Type Java类
K - Key 键
V - Value 值
N - Number 数值类型
? - 不确定的类型 - 通配符
上界通配符:extends 类/接口/标记符T表示泛型类型是 T 或 其子类 (只能读, 不能写)
下界通配符:super 类/接口/标记符T表示泛型类型是 T 或 其父类 (只能写, 读时只能当作Object) - 泛型方法声明:
[修饰符] <泛型,...> 返回值类型 方法名(参数数据类型 形参名){方法体}
泛型类声明:[修饰符] class 类名<泛型,...> {类体}
使用: 声明后即可在 返回值类型 参数数据类型 和 方法体 / 类的字段 与 方法 中使用
使用范围: 泛型类定义的泛型是 供给实例来使用的, 所以泛型类定义的泛型 不能在静态字段与静态方法中使用, 但静态方法可以定义为泛型方法, 从而使用自己定义的泛型 而非 类定义的泛型
声明: 若类声明了, 则其中的方法无需再声明
注: 若声明多个泛型, 则用逗号隔开, 但标记符名字不能相同 - 引用泛型方法: 与引用普通方法相同, 系统会自动判断传入的数据类型
引用泛型类:
创建实例:类名<具体数据类型> 变量名 = new 类名<具体数据类型>(...)
创建实例(>java7可用):类名<具体数据类型> 变量名 = new 类名<>(...)
注:类名<?>相当于类名<具体数据类型>的父类, 具体数据类型不能是基础数据类型, 要使用对应的引用数据类型
使用静态字段/方法: 直接使用类名.字段/方法
系统属性
- 介绍: 用于存储JVM运行环境相关信息, 会影响Java程序行为(类似于系统配置)
- 更改方式:
- 代码中
System.setProperty(String key, String value)方法设置 - 用java指令运行时, 使用 -D 选项设置
- 代码中
枚举
- 简介: 用来表示一组常量, 枚举类本质是一种特殊的类(继承了java.lang.Enum的类)
其中的枚举常量相当于其实例,
由于是类, 所以可以定义在内部类中, 其内也可定义类与方法 - 定义
// 定义
[修饰符] enum Color
{
RED, GREEN, BLUE;
}
// 赋值
Color test = Color.RED // 注:此时该变量会被隐式定义为 public static final, 作为枚举类的常量
switch(test){
case RED: // 在case语句中,类似Color.RED等可以直接简写为RED
break;
case GREEN:
break;
case BLUE:
break;
}
注解Annotation
- 简介: 写给程序看的注释, 用于传递元数据, 类 方法 变量 等多种元素都可被标注, 且能通过反射获取标注内容
注: 注解都继承自java.lang.annotation.Annotation - annotation包定义:
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
public enum ElementType {
TYPE, /* 用于类、接口(包括注释类型)或枚举声明 */
FIELD, /* 用于字段声明(包括枚举常量) */
METHOD, /* 用于方法声明 */
PARAMETER, /* 用于参数声明 */
CONSTRUCTOR, /* 用于构造方法声明 */
LOCAL_VARIABLE, /* 用于局部变量声明 */
ANNOTATION_TYPE, /* 用于注释类型声明 */
PACKAGE /* 用于包声明 */
}
public enum RetentionPolicy {
SOURCE, /* 注解仅存在于源代码中,编译时会被编译器丢弃,运行时不可见,用于定义标记注解 */
CLASS, /* 注解会被保留到.class文件中,但JVM在运行时不会加载注解信息,无法通过反射访问,默认行为 */
RUNTIME /* 注解不仅存在于.class文件中,JVM加载类后仍可通过反射获取 */
}
- 标记注解(没有成员变量的注解, 仅起到标记作用)
@Override - 检查该方法是否是重写方法, 如果发现其父类, 或者是引用的接口中并没有该方法时, 会报编译错误
@SafeVarargs (>=java7) - 忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
@FunctionalInterface (>=java8) - 标识一个匿名函数或函数式接口 - 功能型注解(通过定义特定成员变量, 为编译器或工具提供具体行为指令的注解)
@Deprecated - 标记过时方法, 如果使用该方法, 会报编译警告
@SuppressWarnings - 指示编译器去忽略注解中声明的警告 - 元注解(作用于其它注解的注解):
@Target(ElementType type[])或@Target(ElementType type)- 标记这个注解应该用于哪(见ElementType定义, 默认用于所有)
@Retention(RetentionPolicy policy)- 标识这个注解怎么保存与生命周期(见RetentionPolicy定义, 默认为RetentionPolicy.CLASS)
@Inherited- 标记这个注解在用于类声明时, 会被该类的子类继承 (默认 注解不会继承给子类)
@Documented- 标记这些注解是否包含在用户文档中 (待定)
@Repeatable(>=java8) - 标识某注解可以在同一个声明上使用多次 (待定) - 自定义注解
[修饰符] @interface <注解名> {
<数据类型> <成员名>() [default <默认值>];
// 数据类型只支持 基本数据类型/String/Class/enum/其它注解 及这些类型的数组
...
}
使用注解时,实参会赋值给成员,然后通过反射取出来执行相关逻辑
JavaBean
- Bean: JavaBean是特殊的Java类, 遵守JavaBean API规范
- 条件
需为公共类, 需拥有一个无参构造函数
需可序列化(实现Serializable接口)
所有属性需为私有属性(假设属性名为test), 若想读取属性, 需定义getTest()方法来读; 若想写入, 需用setTest()方法来写
(属性可只读/只写, 只定义getTes()为只读, 只定义setTest()为只写)