DAY 1
1. java 程序编写和执行过程(命令窗口版)
编写:将 java 代码编写在 .java 结尾的源文件中
编译:针对于 .java 结尾的源文件进行编译操作,语句为
javac 源文件名.java
运行:针对编译后生成的字节码文进行解释运行,语句为
java 字节码文件名
2. 基本语法
2.1 HelloWorld 程序
class HelloChina{
public static void main(String[] args){
System.out.println("hello,china");
}
}
① class:关键字,表示“类”,后面跟着类名。
② main() 方法的格式是固定的,表示程序的入口。
③从控制台输出语句的操作:
System.out.println("输出信息")
④每行执行语句(程序入口后的语句)需要以 分号 结束。
2.2 其他事项
① java 中严格区分大小写。
②一个 java 文件中可以声明多个类,但是只能由一个类使用 public,且声明 public 的类的类名需要与源文件名相同。
③若一个 java 文件中有多个类,则编译后会生成多个 class 文件。
DAY 2
1. 注释
1.1 单行注释
// 注释文字
1.2 多行注释
/*
注释文字
注释文字
注释文字
*/
多行注释不能嵌套使用
1.3 文档注释(java特有)
/**
@author 指定java程序的作者
@version 指定源文件的版本
*/
使用命令行语句
javadoc -d mydir -author -version 源文件名.java
在当前目录下生成名为 mydir 的文件夹。
2. 符号
2.1 \t
制表符
2.2 \n
换行符
3. 标识符
3.1 什么是标识符
标识符是 java 中变量、方法、类等要素命名时使用的字符序列
3.2 命名规则
① 由 26 个英文字母大小写,0-9,_,或 $ 组成;
② 数字不可以开头;
③ 不可以使用关键字和保留字,但能包含关键字和保留字;
④ 不能包含空格。
3.2 命名规范
包名:多单词组成时所有字母都小写。例如:java.long
类名、接口名:多单词组成时,所有单词的首字母大写。例如:HelloWorld,String
变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写。例如:age,bookName
常量名:所有字母大写,多单词时每个单词用下划线连接。例如:MAX_VALUE,PI
4. 变量
4.1 分类
4.1.1 基本数据类型
① 整型:byte,short,int,long
② 浮点型:float(赋值时需要以" f "或" F "作为后缀),double(精度更高,所以浮点型变量通常使用 double)
③ 字符型:char
④ 布尔型:boolean
4.1.2 引用数据类型
类(class),数组(array),接口(interface),枚举(enum),注解(annotation),记录(record)。其中记录是 jdk1x 之后引入的。
4.2 作用范围
变量只在作用域内起作用,同一个作用域内不能声明同名变量。
4.3 整型数据
byte:1 字节,等于 8bit 位
short:2 字节
int:4 字节
long:8 字节,赋值时需要以" l "或" L "作为后缀,若不加" l "或" L ",则自动转换为 int 类型变量
4.4 浮点类型数据
float:内存占用 4 字节,赋值时需要以" f "或" F "作为后缀,若不加,则自动转换为 double 类型变量进而报错
double:内存占用 8 字节,精度更高,所以浮点型变量通常使用 double
4.5 字符类型
char:内存占用 2 字节
4.5.1 表示形式
① 使用一对' '表示,内部有且仅有一个字符(字母、汉字、数字等)。
② (不常用)直接使用 Unicode 值来表示字符型常量。
③ 使用转义字符
4.6 布尔类型
boolean:内存占用 4 字节
DAY 3
1. 基本数据类型间的运算规则(不包含 boolean 类型)
1.1 自动类型提升
规则:当容量小的变量与容量大的变量做运算时(此处的容量并非指占用内存空间的大小,而是指表示数据的范围的大小),结果自动转换为容量大的数据类型。
byte、short —> int —> long —> float —> double(从做往右为自动类型提升,从右往左为强制类型转换)
特别的,当 byte、short 、char 类型的变量间做运算,结果为 int 类型。
1.2 强制类型转换
规则:① 若需要将容量大的变量的类型转换为容量小的变量的类型,则需要使用其重量限制
② 强制类型转换需要使用强转符 () ,在 () 内指明要转换为的数据类型
③ 强制类型转换过程中,可能导致精度损失(如 double 类型的值 12.9 转为 int 类型后变为 12)
2. String 类的使用
① String 类属于引用数据类型;
② String 类型的变量可以使用一对 " " 的方式进行赋值
③ String 声明的字符串内部,可以包含 0 个、1 个或多个字符
④ String 与基本数据类型变量间只能做连接运算(无其他运算),且运算结果仍为 String 类型,连接运算使用 + 表示,但是注意如下情况
boolean b1 = true;
int num1 = 10;
String str1 = "abc";
String str2 = b1 + num1 + str1;
第四行语句等号右边先执行 b1+num1,此处并非执行了连接运算,而是执行了加法操作,而布尔类型变量不参与该运算,因此编译不通过。
DAY 4
1. 运算符
1.1 算术运算符
+ - * / % (前)++ (后)++ (前)-- (后)--
++或--不会改变变量的数据类型
1.2 赋值运算符
= += -= *= /= %=
+=、-=、*=、/=、%=不会改变变量的数据类型
1.3 关系运算符
== != > < >= <= instanceof
说明: ① == != 适用于所有基本数据类型, > < >= <= 适用于除布尔类型的其他 7 种基本数据类型,且运算结果均为布尔类型
② == != 适用于引用数据类型
1.4 逻辑运算符(左右两侧位boolean)
& 和 &&:表示 "且" 关系,当符号左右两边布尔值均为 true 时,结果才为 true,否则为false,特别的,当符号 && 左侧变量为 false 时,不再执行右侧操作,直接返回 false
| 和 ||:表示 "或" 关系,当符号左右两边布尔值均为 false 时,结果为 false,否则为 true,特别的,当符号 || 左侧变量为 true 时,不再执行右侧操作,直接返回 true
!:表示 "非" 关系,当布尔值变量为 true 时,结果为 false,反之为 true
^:当符号左右两边布尔值不同时,结果为 true,两边布尔值相同时,结果为 false
说明:① 逻辑运算符针对的都是布尔类型的变量进行的操作,即符号左右两侧变量均为布尔类型
② 逻辑运算符的运算结果也为布尔类型
③ 逻辑运算符常使用条件判断结构、循环结构中
1.5 位运算符(左右两侧为数值)
针对数值类型的变量或常量进行运算,运算结果也是数值,运算时正数看原码,负数看补码
<<:左移,在一定范围内,每向左移动一位,结果就在原有的基础上 *2 ,正负数通用,低位补 0
>>:右移,在一定范围内,每向右移动一位,结果就在原有的基础上 /2 不能整除,向下取整,若正负数通用,正数高位补 0,负数高位补 1
>>>:无符号右移,无论正负数,高位均补 0(负数移动一位变为正数)
&:按位与,1&1=1,1&0=0,0&0=1
|:按位或,1|1=1,1|0=1,0|0=0
^:按位异或,1^1=0,1^0=1,0^0=0
~:按位取反,对应位为 1,则结果为 0,对应位为 0 则结果为 1
1.6 条件运算符
(条件表达式) ? 表达式1: 表达式2
说明:① 条件表达式的结果时布尔类型
② 如果条件表达式的结果是 true,则执行表达式1,否则执行表达式2
③ 凡是可以使用条件运算符的位置,都可以改写成 if-else 语句,反之不一定可以
DAY 4
1. 使用 Scanner 类从键盘获取数据
1.1 使用步骤及方法
步骤一:导包
import java.util.Scanner;
步骤二:创建一个 Scanner 类的实例
Scanner scan = new Scanner(System.in); //scan为自定义的实例名
步骤三:调用 Scanner 类中的 next 方法,获取指定类型的变量
Scanner 类中提供了获取 byte \ short \ int \ long \ float \ double \ boolean \ String 类型变量的方法,但是没有提供 char 类型变量的方法,若想要输入 char 类型数据,则需要使用 next().charAt(0) 从输入的 String 类型变量中取第一个字符。
输入值为 byte:实例名.nextByte();
输入值为 int:实例名.nextInt();
输入值为 long:实例名.nextIong();
输入值为 float:实例名.nextFIoat();
输入值为 double:实例名.nextDouble();
输入值为 String:实例名.nextLine();
输入值为 char:实例名.nextString().charAt(0);
输入值为 boolean:实例名.nextBoolean();
步骤四:关闭资源,调用 Scanner 类的close()
实例名.close();
2. 如何获取随机数
可以使用 Java 提供的 API:Math 类的 random() ,random() 调用后,会返回一个 [0.0,1.0) 范围内的 double 型的随机数。
如何获取一个 [1,100] 范围的随机整数:
使用 random() 后*101,然后强制类型转换
int num1 = (int)(Math.random()*101);
获取一个 [a,b] 范围内的随机整数的公式:
(int)(Math.random()*(b - a + 1)) + a;
3. 分支结构 switch-case 的使用
3.1 语句格式
switch(表达式){
case 常量1:
//执行语句1
break;
case 常量2:
//执行语句2
break;
case 常量3:
//执行语句3
break;
...
default:
//执行语句
break;
}
3.2 执行过程
根据表达式中的值,依次匹配 case 语句。一旦与某一个 case 中的常量相等,则执行此 case 中的执行语句,执行完此执行语句之后,若遇到 break,则执行 break 跳出当前 switch-case 结构;若没有遇到 break,则继续执行其后的 case 中的执行语句。
3.3 说明
① switch 中的表达式只能是特定的数据类型:byte \ short \ char \ int \ 枚举(JDK5.0新增) \ String(JDK7.0新增)
② case 后跟的都是常量,使用表达式与这些常量做相等的判断,不能进行范围的判断
③ break 可以使用在该结构中,一旦执行 break,则跳出当前 switch-case 结构
④ default 是可选的,而且位置是灵活的
DAY 5
5.1 循环结构
凡是循环结构。就一定会有 4 个要素:
① 初始化条件 ② 循环条件 ③ 循环体 ④ 迭代部分
5.1.1 for 循环
格式
for(① ;② ;④)
③
5.1.2 while 循环
格式
while(①){
③
④
}
5.1.3 do-while 循环
格式
①
do{
③
④
}while(②);
循环体至少循环一次
5.2 IDEA 项目结构
层级关系: project(工程) —> module(模块) —> package(包) —> class(类)
具体的:一个 project 中可以创建多个 module;
一个 module 中可以创建多个 package;
一个 package 中可以创建多个 class;
DAY 6
6.1 数组
6.1.1 定义
是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
6.1.2 特点
① 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型
② 创建数组对象会在内存中开辟一整块连续的空间。占据的空间的大小,取决于数组的长度和数组中元素的类型。数组中的元素在内存中是依次紧密排列的,有序的
③ 数组一旦初始化完成,其长度就是确定的,且长度不能修改
④ 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快
⑤ 数组名中引用的是这块连续空间的首地址
6.1.3 一维数组的使用
数组的声明
数据类型[] 数组名;
初始化
引用数据类型基本用 new 来创建,可通过静态或动态方式进行初始化
数组名 = new 数据类型[]{元素1,元素2,...} //方式一:静态初始化
数组名 = new 数据类型[数组大小] //方式二:动态初始化
数组元素的调用
通过角标的方式获取数组元素,角标的范围为 [0 , 数组长度-1]
数组的长度
用于描述数组容器的容量大小(和数组已存元素数无关),使用 .lenght 可查看
int length = 数组名.length;
数组的遍历
使用循环结构进行遍历
DAY 7
7.1 二维数组
7.1.1 二维数组的理解
可以看成是一维数组 array1 又作为另一个一维数组 array2 的元素而存在。从数组底层的运行机制来看,其实没有多维数组。
7.1.2 二维数组的使用
二维数组的声明与初始化
数据类型[][] 数组名 = new 数据类型[][]{{一维数组1},{一维数组2},...}; //静态初始化
数据类型[][] 数组名 = new 数据类型[外层元素数][内层元素数]; //动态初始化方式1
数据类型[][] 数组名 = new 数据类型[外层元素数][]; //动态初始化方式2
数组名[外层元素序号] = new 数据类型[内层元素数];
二维数组的调用
调用内层元素
数组名[外层元素序号][内层元素序号];
注意:无法直接调用外层元素的值,如:arr2[0] ,该操作返回的是第一个外层元素的存储地址
二维数组的长度
二维数组的长度指外层元素个数,查询方式与一维数组类似,同样的也可查询二维数组中一维数组的长度
DAY 8
8.1 数组的赋值
在两数组是相同类型的前提下,可以如下方式进行数组赋值
数组1 = 数组2
注意:① 若数组2的原始长度小于数组1长度,则会自动扩大长度为数组1的长度
② 此方式赋值,数组1和数组2是两个变量,但共同指向了堆空间中的同一个数据结构,即二者地址值相同(修改数组2中的值,数组1中对应值也发生变化)
8.2 数组的复制
使用循环结构进行复制
8.3 数组工具类的使用
使用数组工具类需要引入类:
import java.util.Arrays;
8.3.1 比较两个数组是否依次相等
语法:
boolean equals(int[] a,int[] b);
eg
int[] arr1 = new int[]{1,2,3};
int[] arr2 = new int[]{2,3,1};
boolean equals = Arrays.equals(arr1,arr2);
System.out.println(equals);
//输出 false
8.3.2 输出数组元素信息
语法:
String toString(int[] a);
eg
int[] arr1 = new int[]{1,2,3};
System.out.println(Arrays.toString(arr1));
//输出 [1, 2, 3]
8.3.3 将指定值填充到数组中(元素均为该值)
语法:
void fill(int[] a,int val);
eg
int[] arr1 = new int[]{1,2,3};
Arrays.fill(arr1,4);
System.out.println(Arrays.toString(arr1));
//输出 [4, 4, 4]
8.3.4 快速排序
语法:
void sort(int[] a);
eg
int[] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
Arrays.sort(arr3);
System.out.println(Arrays.toString(arr3));
//输出 [2, 3, 5, 7, 34, 34, 34, 54, 65, 67, 76]
8.3.5 二分查找(数组需要有序)
语法:
int binarySearch(int[] a,int key);
eg
int[] arr3 = new int[]{2, 3, 5, 7, 34, 34, 34, 54, 65, 67, 76};
int index = Arrays.binarySearch(arr3,3);
System.out.println(index);
//输出 1
//若返回负数,则表名查询的元素不存在数组中
DAY 9
9.1 面向对象思想的理解
面向对象,是软件开发中的一类编程风格、开发范式。
9.1.1 面向对象的程序设计思想
关注的焦点是类:在计算机程序设计过程中,参照现实中事物,将事物的属性特征、行为特征抽象出来,用类来表示。
代码结构:以类为组织单位。每种事物都具备自己的属性和行为/功能。
9.2 类
9.2.1 理解
类是具有相同特征的事物的抽象描述,是抽象的、概念上的定义。
9.2.2 类的构成
类是一组相关属性和行为的集合,这也是类最基本的两个成员
属性:该类事物的状态信息,对应类中的成员变量(成员变量<=>属性<=>field)
行为:该类事物要做什么操作,或基于事物的状态能做什么,对应类中的成员方法(方法<=>函数<=>method)
9.2.3 类的创建
类的创建使用关键字:class,格式为
[修饰符] class 类名{
属性声明;
方法声明;
}
eg
9.3 对象
9.3.1 理解
对象是实际存在的该类事物的每个个体,是具体的,因而也称为实例
9.3.2 对象的创建(类的实例化)
创建对象使用关键字:new,格式为
类名 对象名 = new 类名();
eg
9.4 面向对象完成具体功能的步骤
① 创建类,并设计类的内部成员(属性、方法)
② 创建类的对象
③ 通过对象,调用其内部声明的属性或方法,完成相关的功能
DAY 10
10.1 成员变量与局部变量
10.1.1 成员变量
定义:类中的属性
语法:
[修饰符 1] class 类名{
数据类型 成员变量名 [= 初始化值];
}
10.1.2 局部变量
在方法内定义的属性或者传入方法的参数(形参)
10.1.3 成员变量与局部变量的不同点
① 类中声明的位置不同:
成员变量(属性):声明在类内,方法外的变量;
局部变量:声明的方法、构造器内部的变量
② 在内存中分配的位置不同:
属性:随着对象的创建,存储在堆空间中
局部变量:存储在栈中
③ 生命周期:
属性:随着对象的创建而创建,随着对象的消亡而消亡
局部变量:随着方法对应的栈帧入栈,局部变量会在栈中分配;随着方法对应的栈帧出栈,局部变量消亡
④ 作用域:
属性:在整个类的内部都是有效的
局部变量:仅限于声明此局部变量所在的方法中
⑤ 是否可以有权限修饰符进行修饰
属性:可以
局部变量:不可以
⑥ 是否有默认值
属性:都有
局部变量:都没有,因此在使用局部变量之前,必须要显式的赋值,否则报错(形参比较特别,在调用含形参的方法时再赋值即可)
DAY 11
11.1 方法
注意点:① Java 里的方法不能独立存在,所有方法必须定义在类中
② Java 中的方法不调用,不执行。每调用一次,就执行一次
③ 方法内可以调用本类中的(其他)方法或属性
④ 方法内不能定义方法
DAY 12
12.1 方法的重载
12.1.1 定义
在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可。满足这样特征的多个方法,彼此间构成方法的重载。
12.1.2 特点
与修饰符、返回值类型无关,只看参数列表,且参数列表(参数个数或参数类型)必须不同。调用时,根据方法参数列表的不同来区别。
12.2 方法的可变个数形参
12.2.1 使用场景
在调用方法时,可能会出现方法形参的类型时确定的,但是参数的个数不确定,此时我们就可以使用可变个数的形参。
12.2.2 格式
(参数类型...参数名)
12.2.3 特点
① 可变个数形参的方法在调用时,针对于可变的形参赋的实参的个数可以为 0个、1个或多个
② 可变个数形参的方法与同一类中,同名的多个方法之间可以构成重载(特例:与可变个数形参的类型相同的数组参数不构成重构)
③ 可变个数的形参必须声明在形参列表的最后
④ 可变个数的形参在一个方法的形参列表中最多出现一次
⑤ 可变个数的形参可看作数组
12.3 方法的值传递机制(值传递)
12.3.1 对于方法内声明的局部变量出现赋值操作
① 基本数据类型变量:将变量保存的数据值传递
② 引用数据类型变量:将变量保存的地址值传递
12.3.2 实参给形参赋值
① 若形参是基本数据类型变量,则将实参保存的数据值赋给形参
② 若形参是引用数据类型变量,则将实参保存的地址值赋给形参
DAY 13
13.1 package 关键字
package 称为包,用于指明该文件中定义的类、接口等结构所在的包
13.1.1 语法格式
package 顶层包名.子包名 ;
13.1.2 说明
① 一个源文件只能有一个声明包的 package 语句
② package 语句作为 Java 源文件的第一条语句出现。若缺省该语句,则指定为无名包
③ 包名属于标识符,满足标识符命名的规则和规范(全部小写)
④ 取包名时不要使用"java.xx"包
⑤ 包对应于文件系统的目录,package 语句中用 “.” 来指明包(目录)的层次,每 . 一次就 表示一层文件目录
⑥ 同一个包下可以声明多个结构(类、接口),但是不能定义同名的结构(类、接口)。 不同的包下可以定义同名的结构(类、接口)
13.1.3 包的作用
① 包可以包含类和子包,划分项目层次,便于管理
② 帮助管理大型软件系统:将功能相近的类划分到同一个包中
③ 解决类命名冲突的问题
④ 控制访问权限
13.2 import 关键字
为了使用定义在其它包中的 Java 类,需用 import 语句来显式引入指定包下所需要的类。 import 语句相当于告诉编译器到哪里去寻找这个类。
13.2.1 语法格式
import 包名.类名;
13.2.2 说明
① import 语句声明在包的声明和类的声明之间
② 如果需要导入多个类或接口,那么就并列显式多个 import 语句即可
③ 如果使用 a.*导入结构,表示可以导入 a 包下的所有的结构
④ 如果导入的类或接口是 java.lang 包下的,或者是当前包下的,则可以省略此 import 语句
⑤ 如果已经导入 java.a 包下的类,那么如果需要使用 a 包的子包下的类的话,仍然需要导入
⑥ 如果在代码中使用不同包下的同名的类,那么就需要使用类的全类名的方式指明调用的是哪个类,例如:
java.包名.类名 对象名 = new java.包名.类名();
13.3 面向对象的特征:封装性
13.3.1 什么是封装
所谓封装,就是把客观事物封装成抽象概念的类,并且类可以把自己的数据和方法只向可信的类或者对象开放,向没必要开放的类或者对象隐藏信息。
13.3.2 如何实现封装
权限修饰符:public、protected、缺省、private
实现封装就是控制类或成员的可见性范围。这就需要依赖访问控制修饰符,也称为权限修饰符来控制。
13.3.3 四种权限的具体使用
修饰符 | 本类内部 | 本包内 | 其他包的子类 | 其他包非子类 |
private | √ | × | × | × |
缺省 | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
13.3.4 注意
类:只能使用 public、缺省修饰
类的内部成员:可以使用四种权限修饰符进行修饰
13.3.5 封装性的体现
① 私有化(private)类的属性,提供公共(public)的 get 和 set 方法,对此属性进行获取或修改
② 将类中不需要对外暴露的方法,设置为 private
③ 单例模式中构造器声明为 private,避免在类的外部创建实例
DAY 14
14.1 构造器
14.1.1 构造器的作用
① 搭配 new 关键字,创建类的对象
② 在创建对象的同时,可以给对象的相关属性赋值
14.1.2 构造器的使用说明
① 声明格式:
[修饰符] 构造器名(){
// 实例初始化代码
}
[修饰符] 构造器名(参数列表){
// 实例初始化代码
}
② 创建类以后,在没有显示提供任何构造器的情况下,系统会默认提供一个空参的构造器,且构造器的权限与类声明的权限相同
③ 一旦类中显示声明了构造器,则系统不再提供默认的空参构造器
④ 一个类中可以声明多个构造器,彼此间构成重载
14.2 this 关键字
14.2.1 this 可调用的结构
成员变量、方法和构造器
14.2.2 什么时候使用 this
在实例方法或构造器中,如果使用当前类的成员变量或成员方法可以在其前面添加 this,增强程序的可读性。但是,当形参与成员变量同名时,如果在方法内或构造器内需要使用成员变量,必须添加 this 来表明该变量是类的成员变量。即:我们可以用 this 来区分成员变量和局部变量。
使用 this 修饰的变量代表的是属性(在方法中代表当前对象,在构造器中代表当前正在创建的对象),没有使用 this 修饰的是形参。
14.2.3 this 调用构造器
使用方法
this():调用本类的无参构造器
this(实参列表):调用本类的有参构造器
注意
① 在类的构造器中,可以调用当前类中指定的其他构造器
② this(形参列表) 必须在当前构造器的首行
③ this(形参列表) 在构造器中最多声明一个
④ 如果一个类中声明了 n 个构造器,则最多有 n-1 个构造器可以声明有 this(形参列表) 的结构
eg
public class Student {
//属性
private String name;
private int age;
//构造器
// 无参构造
public Student() {
}
// 有参构造
public Student(String name) {
this();//调用本类无参构造器
this.name = name;
}
// 有参构造
public Student(String name,int age){
this(name);//调用本类中有一个 String 参数的构造器
this.age = age;
}
}
DAY 15
15.1 继承性
15.1.1 继承性的理解
① 自上而下:定义了一个类A,在定义另一个类B时,发现类B的功能与类A相似,考虑类B继承于类A
② 自下而上:定义了类B、C、D等,发现B、C、D有类似的属性和方法,则可以考虑将相同的属性和方法进行抽取,封装到类A中,让类B、C、D继承于类A,同时B、C、D中的相似的功能就可以删除了
15.1.2 继承性的好处
① 继承的出现减少了代码冗余,提高了代码的复用性
② 继承的出现,更有利于功能的扩展
③ 继承的出现让类与类之间产生了 is-a 的关系,为多态的使用提供了前提
15.1.3 继承中的基本概念
① 父类(superClass、超类、基类)
②子类(subClass、派生类)
15.1.4 继承的语法
通过 extends 关键字,可以声明一个类 B 继承另外一个类 A,定义格式如下:
//父类 A
[修饰符] class A {
...
}
//子类 B
[修饰符] class B extends A {
...
}
15.1.5 继承性的细节说明
① 子类会继承父类所有的实例变量和实例方法
② 子类不能直接访问父类中私有的(private)的成员变量和方法
子类虽会继承父类私有(private)的成员变量,但子类不能对继承的私有成员变量直接进行访问,可通过继承的 get/set 方法进行访问。
③ 在 Java 中,继承的关键字用的是“extends”,即子类不是父类的子集,而是对父类的“扩展
④ Java 支持多层继承(继承体系)
子类和父类是一种相对的概念。顶层父类是 Object 类。所有的类默认继承 Object,作为父类。
⑤ 一个父类可以同时拥有多个子类,但是一个子类只能有一个父类(单继承)
DAY 16
16.1 重写
16.1.1 重写的定义
子类可以对从父类中继承来的方法进行改造,我们称为方法的重写,也称为方法的重置、覆盖。
16.1.2 方法重写的规则
① 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
② 子类重写的方法的权限修饰符不能大于父类被重写的方法的权限修饰符(子类不能重写父类中声明被 private 权限修饰的方法)
③ 关于返回值:
> 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型必须是void;
> 父类被重写的方法的返回值类型是基本数据类型,则子类重写的方法的返回值类型必须与被重写的方法的返回值类型相同;
> 父类被重写的方法的返回值类型是引用数据类型(比如类),则子类重写的方法的返回值类型可以与被重写的方法的返回值类型相同或是被重写的方法的返回值类型的子类
16.1.3 方法的重载与重写
重载:方法名相同,形参列表不同
重写:方法名相同,形参列表相同
16.2 super 关键字
16.2.1 super 的作用
① 可用于访问父类中定义的属性
② 可用于调用父类中定义的成员方法
③ 可用于在子类构造器中调用父类的构造器
16.2.2 super 调用父类中同名的成员变量
① 如果实例变量与局部变量重名,可以在实例变量前面加 this. 进行区别;
② 如果子类实例变量和父类实例变量重名,并且父类的该实例变量在子类仍然可见,在子类中要访问父类声明的实例变量需要在父类实例变量前加 super.,否则默认访问的是子类自己声明的实例变量;
③ 如果父子类实例变量没有重名,只要权限修饰符允许,在子类中完全可以直接访问父类中声明的实例变量,也可以用 this. 实例访问,也可以用 super. 实例变量访问
16.2.3 super 调用父类被重写的方法
① 如果子类没有重写父类的方法,只要权限修饰符允许,在子类中完全可以直接调用父类的方法;
② 如果子类重写了父类的方法,在子类中需要通过 super. 才能调用父类被重写的方法,否则默认调用的子类重写的方法
16.2.4 super 调用父类构造器
① 子类继承父类时,不会继承父类的构造器。只能通过“super(形参列表)”的方式调用父类指定的构造器;
② 规定:“super(形参列表)”,必须声明在构造器的首行(在构造器的首行,"this(形参列表)" 和 "super(形参列表)"只能二选一);
③ 如果在子类构造器的首行既没有显式调用"this(形参列表)",也没有显式调用 "super(形参列表)", 则子类此构造器默认调用"super()",即调用父类中空参的构造器;
④ 子类的任何一个构造器中,要么会调用本类中重载的构造器,要么会调用父类的构造器。 只能是这两种情况之一(由③知,默认调用父类构造器,即使用super(形参列表))
⑤ 一个类中声明有 n 个构造器,最多有 n-1 个构造器中使用了 "this(形参列表)",则剩下的那个一定使用"super(形参列表)"
DAY 17
17.1 多态性
17.1.1 对象的多态性
父类的引用指向子类的对象
格式
父类类型 变量名 = 子类对象;
17.1.2 多态性的应用:虚拟方法调用
在多态场景下调用方法时:
① 编译时,认为方法是左边声明的父类的类型的方法(即被重写的方法) ② 执行时,实际执行的是子类重写父类的方法
简称为:编译看左边,运行看右边
17.1.3 多态性的使用前提
① 要有类的继承关系
② 要有方法的重写(无法直接调用子类特有的方法)
17.1.4 多态的适用性
适用于方法,不适用于属性
17.1.5 类型转换
为什么需要
因为多态,就一定会有把子类对象赋值给父类变量的时候,在编译期间,就会出现类型转换的现象。但是,使用父类变量接收了子类对象之后,就不能直接调用子类独有的方法了。
向下转型与向上转型
向上转型:当左边的变量的类型(父类) > 右边对象/变量的类型(子类),就称为向上转型。此时,编译时按照左边变量的类型处理,就只能调用父类中有的变量和方法,不能调用子类特有的变量和方法。
向下转型:当左边的变量的类型(子类)< 右边对象/变量的编译时类型(父类),就称为向下转型。此时,编译时按照左边变量的类型处理,可以调用子类特有的变量和方法。
注意:不是所有通过编译的向下转型都是正确的,可能会发生类型转换异常(ClassCastException) ,为了安全起见,在进行向下转型前,使用instanceof 关键字进行判断
17.1.6 instanceof 关键字
格式
a instanceof A; //判断对象a是否是类A的实例
如果返回 true,则下述代码也返回 true:
a instanceof superA; //superA 为 A 的父类
DAY 18
18.1 Object 类的说明
① 任何一个 Java 类(除 Object 类)都直接或间接的继承于 Object 类
② Object 类称为 Java 类的根父类
③ Object 类中声明的结构(属性、方法等)就具有通用性
18.2 equals()
18.2.1 适用性
任何引用数据类型都可以使用
18.2.2 格式
object1.equals(object2);
18.2.3 说明
① 自定义的类在没有重写 Object 中 equals() 方法的情况下,调用的就是 Object 类中声明的 equals() ,比较两个对象的引用地址是否相同
② 对于像String、File、Date和包装类等,它们都重写了Object
18.2.4 重写规则
① 对称性:如果 x.equals(y)返回是“true”,那么 y.equals(x)也应该返回是 “true”
② 自反性:x.equals(x)必须返回是“true”
③ 传递性:如果 x.equals(y)返回是“true”,而且 y.equals(z)返回是“true”,那么 z.equals(x)也应该返回是“true”
④ 一致性:如果 x.equals(y)返回是“true”,只要 x 和 y 内容一直不变,不管重复 x.equals(y)多少次,返回都是“true”
⑤ 任何情况下,x.equals(null),永远返回是“false”; x.equals(和 x 不同类型的对象)永远返回是“false”。