无论你是一名Java初学者还是有一定编程基础的开发者,了解JavaSE的知识都是非常有必要的,因为JavaSE是Java编程的基础,掌握好JavaSE的各种知识点对于后续的Java开发非常重要。在此博客中,我们将介绍JavaSE的各种知识点,帮助你建立深厚的Java编程基础。
一、初识Java
1.1Java发展史
Java 语言源于 1991 年 4 月,Sun 公司 James Gosling博士 领导的绿色计划(Green Project) 开始启动,此计划最初的目标是开发一种能够在各种消费性电子产品(如机顶盒、冰箱、收音机等)上运行的程序架构。这个就是Java的前身:Oak (得名与Java创始人James Gosling办公室外的一棵橡树),但由于这些智能化家电的市场需求没有预期 的高,Sun公司放弃了该项计划。随着1995年代互联网的发展,Sun公司看见Oak在互联网上应用的前景,于是改 造了Oak,于1995年5月以Java的名称正式发布,并提出“Write once, Run anywhere" 的口号。
。附赠图片一张
吐槽一下:害,本来最开始是狠狠赚一笔的,结果现在行情越来越难,应届普通本科毕业生工资三千左右,还要哪儿哪儿哪儿都会,指哪儿打哪儿,我亲戚他们公司现状:除非名校毕业,不然工作经验至少得三年。
1.2、类
class
定义一个类,每个类都有构造方法,构造方法有且仅调用一次,构造方法可以自己重写。
1.3、main()
方法
一个程序只有一个main()
方法,程序开始执行就是首先就找main()
方法,从main()
方法开始执行。
1.4、注释
注释是为了让代码更容易被读懂而附加的描述信息. 不参与编译运行, 但是却非常重要,时刻牢记!代码写出来是为了给人看的, 更是为了给三个月后的你自己看的。注释的表示方法为:
public class Main {
public static void main(String[] args) {
int a = 10;//把10赋值给a -> 这就是注释
}
}
注释分三种:
- 单行注释:// 注释内容(用的最多)
- 多行注释:/* 注释内容*/(不推荐)
- 文档注释: /** 文档注释 */(常见于方法和类之上描述方法和类的作用),可以被javadoc工具解析,生成一套以网页文件形式体现的程序说明文档
1.5、标识符
标识符是在程序中由用户给类名、方法名或者变量所取的名字。
1.5.1、硬性要求
标识符中可以包含:字母、数字以及 下划线和 $ 符号等等。
注意:标识符不能以数字开头,也不能是关键字,且严格区分大小写。
1.5.2、软性要求
- 类名:每个单词的首字母大写(大驼峰)
- 方法名:首字母小写,后面每个单词的首字母大写(小驼峰)
- 变量名:与方法名规则相同
1.6、关键字
关键字分为定义访问权限,定义类、函数的类型,定义类和类之间关系······等。
二、数据类型和变量
2.1、字面常量
表示一赋值好就不能修改的量,例如10就等于10,不能修改
2.2、数据类型
数据类型分为四类八种
四类是指:整型、浮点型、字符型以及布尔型
八种如下:
数据类型 | 关键字 | 内存占用 | 数值范围 |
字符型 | byte | 1个字节 | -128 ~ 127 |
短整型 | short | 2个字节 | -32768 ~ 32767 |
整形 | int | 4个字节 | -231 ~(231-1) |
长整型 | long | 8个字节 | -263 ~(263-1) |
单精度浮点数 | float | 4个字节 | 有范围,不关注 |
双精度浮点数 | double | 8个字节 | 有范围,不关注 |
字符型 | char | 2个字节 | 0 ~ 65535 |
布尔类型 | boolean | 没有明确规定 | true和false |
2.3、变量
这个没什么好讲的,定义变量格式如下:
数据类型 变量名 = 初始值;
唯一有区别的就是long
类型的变量和float
类型的变量,他们的格式如下:
数据类型 变量名 = 初始值L;//long类型,大小写都可以,但是小写l和1不好区分,所以大写更好
数据类型 变量名 = 初始值F;//float类型,为了和long类型统一,所以大写
三、运算符
3.1、运算符的分类
- 算数运算符:
'+' '-' '*' '/' '%' '+=' '-=' '=' '%=' '++' '--'
- 关系运算符:
'==' '!=' '<' '>' '<=' '>='
,计算结果是true
或者false
- 逻辑运算符(重点):
'&&' '&' '||' '|' '!'
,运算结果都是boolean
类型 - 位运算符:
'&' '|' '~' '^'
- 位移运算符(了解就行):
'<<' '>>' '>>>'
- 条件运算符:
表达式1 ? 表达式2 : 表达式3;
3.2、运算符的优先级
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 | |
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | ||
() | 圆括号 | (表达式) | ||||
. | 成员选择 (对象) | 对象.成员名 | ||||
-> | 成员选择 (指针) | 对象指针->成员名 | ||||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 | |
(类型) | 强制类型转换 | (数据类型)表达式 | ||||
++ | 自增运算符 | ++变量名 | 单目运算符 | |||
-- | 自减运算符 | --变量名 | 单目运算符 | |||
* | 取值运算符 | *指针变量 | 单目运算符 | |||
& | 取地址运算符 | &变量名 | 单目运算符 | |||
! | 逻辑非运算符 | !表达式 | 单目运算符 | |||
~ | 按位取反运算符 | ~表达式 | 单目运算符 | |||
sizeof | 长度运算符 | sizeof(表达式) | ||||
3 | / | 除 | 表达式 / 表达式 | 左到右 | 双目运算符 | |
* | 乘 | 表达式*表达式 | 双目运算符 | |||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 | |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 | |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 | |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 | |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 | |
13 | ?: | 条件运算符 | 表达式1 ? 表达式2 : 表达式3 | 右到左 | 三目运算符 | |
14 | = | 赋值运算符 | 变量 = 表达式 | 右到左 | ||
15 | /= | 除后赋值 | 变量 /= 表达式 | |||
16 | *= | 乘后赋值 | 变量 *= 表达式 | |||
17 | %= | 取模后赋值 | 变量 %= 表达式 | |||
18 | += | 加后赋值 | 变量 += 表达式 | |||
19 | -= | 减后赋值 | 变量 -=表达式 | |||
20 | <<= | 左移后赋值 | 变量 <<= 表达式 | |||
21 | >>= | 右移后赋值 | 变量 >>= 表达式 | |||
22 | &= | 按位与后赋值 | 变量 &= 表达式 | |||
23 | ^= | 按位异或后赋值 | 变量 ^= 表达式 |
四、逻辑控制
不出意外的话,一行一行代码往下执行,除非中间有意外,比如if、switch
4.1、顺序结构
按照代码书写的顺序一行一行执行。
4.2、分支结构
4.2.1、if语句
有三种格式,如下:
//第一种
if (布尔表达式) {
// 语句
}
//第二种
if (布尔表达式1) {
// 语句1
} else (布尔表达式2) {
// 语句2
}
//第三种
if (布尔表达式1) {
// 语句1
} else if (布尔表达式2) {
// 语句2
} else {
// 语句3
}
上面代码表示,如果if
括号中的布尔表达式位true
就执行,否则就执行下一个,最近的else
只能和最近的if
匹配。
4.3、switch 语句
示例代码:
int day = 1;
switch(day) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("输入有误");
break;
}
4.4、循环结构
4.4.1 while 循环
基本语法格式:
while (循环条件) {
循环语句;
}
循环条件只要满足,就会一直循环下去。
4.4.2、for 循环
基本语法格式:
for (表达式1;布尔表达式2;表达式3) {
表达式4;
}
- 表达式1: 用于初始化循环变量初始值设置,在循环最开始时执行,且只执行一次
- 表达式2: 循环条件,满则循环继续,否则循环结束
- 表达式3: 循环变量更新方式
4.4.3、do while 循环
基本语法格式:
do{
循环语句;
} while (循环条件);
先执行循环语句, 再判定循环条件,循环条件成立则继续执行,否则循环结束。
4.4.4、break
break
的功能是让循环提前结束,通俗点就是跳出循环。
4.4.5、continue
continue
的功能是跳过这次循环, 立即进入下次循环。和break
不一样,break
是直接跳出去,不执行循环内部了,而continue
还是执行,只不过这一次循环的下面代码不执行了。
4.5、输入输出
4.5.1 输出到控制台
格式如下:
System.out.println(msg); // 输出一个字符串, 带换行
System.out.print(msg); // 输出一个字符串, 不带换行
System.out.printf(format, msg); // 格式化输出
转换符 | 类型 | 举例 | |
d | 十进制整数 | ("%d", 100) | 100 |
x | 十六进制整数 | ("%x", 100) | 64 |
o | 八进制整数 | ("%o", 100) | 144 |
f | 定点浮点数 | ("%f", 100) | 100.000000 |
e | 指数浮点数 | ("%e", 100f) | 1.000000e+02 |
g | 通用浮点数 | ("%g", 100f) | 100.000 |
a | 十六进制浮点数 | ("%a", 100) | 0x1.9p6 |
s | 字符串 | ("%s", 100) | 100 |
c | 字符 | ("%c", 1) | 1 |
b | 布尔值 | ("%b", 100) | true |
h | 散列码 | ("%h", 100) | 64 |
% | 百分号 | ("%.2f%%", 2/7f) | 0.29% |
4.5.2、从键盘输入
使用 Scanner 读取字符串/整数/浮点数。
五、方法的使用
5.1、方法的概念
方法就是一个代码片段. 类似于 C 语言中的 "函数"。
5.2、方法的定义
定义在类的内部,比如main()
就是一个方法。
【注意事项】
- 修饰符:现阶段直接使用
public static
固定搭配 - 返回值类型:如果方法有返回值,返回值类型必须要与返回的实体类型一致,如果没有返回值,必须写成
void
- 方法名字:采用小驼峰命名
- 参数列表:如果方法没有参数,
()
中什么都不写,如果有参数,需指定参数类型,多个参数之间使用逗号隔开 - 方法体:方法内部要执行的语句
- 在java当中,方法必须写在类当中
- 在java当中,方法不能嵌套定义
- 在java当中,没有方法声明一说
5.3、方法调用的执行过程
①调用方法 ---> ②传递参数 ---> ③找到方法地址 ---> ④执行被调方法的方法体 ---> ⑤被调方法结束返回 ---> ⑥回到主调方法继续往下执行
5.4、实参和形参的关系(重要)
在Java中,实参的值永远都是拷贝到形参中,形参和实参本质是两个实体。如下代码:
public static void test(int b) {
b = 6;
}
public static void main(System[] args) {
int a = 9;
test(a);
System.out.println(a);
}
如上代码,这个b
就是形参,a
是实参,形参是重开开辟的一个空间,它的改变不会影响到实参。如下:
5.5、方法重载
在Java中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了。
【注意事项】
- 方法名必须相同
- 参数列表必须不同(参数的个数不同、参数的类型不同、类型的次序必须不同)
- 与返回值类型是否相同无关
5.6、方法的重写
在Java中,如果有个方法的名字、参数列表、返回值全部相同,则称该方法重写了另一个方法。
5.7、递归
5.7.1递归的概念
一个方法在执行过程中调用自身, 就称为 "递归"。递归相当于数学上的 "数学归纳法", 有一个起始条件, 然后有一个递推公式.
5.7.2、递归的必要条件
- 将原问题划分成其子问题,注意:子问题必须要与原问题的解法相同
- 递归出口
5.7.3、递归执行过程分析
递归的程序的执行过程不太容易理解,要想理解清楚递归,必须先理解清楚 "方法的执行过程",尤其是 "方法执行结束之后,回到调用位置继续往下执行" 。
六、数组的定义与使用
6.1、数组的基本概念
数组可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。
6.2、数组的创建及初始化
6.2.1、数组的创建
如下:
数据类型[] 数组名 = new 数据类型[数组长度];
6.2.2、数组的初始化
数组的初始化主要分为动态初始化以及静态初始化。
- 动态初始化:在创建数组时,直接指定数组中元素的个数
如下:
int[] array = new int[10];
- 静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定
如下:
int[] array1 = new int[]{0,1,2,3,4,5,6,7,8,9};
double[] array2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};
String[] array3 = new String[]{"hell", "Java", "!!!"};
【注意事项】
- 静态初始化虽然没有指定数组的长度,编译器在编译时会根据
{}
中元素个数来确定数组的长度。 - 静态初始化时,
{}
中数据类型必须与[]前数据类型一致。 - 静态初始化可以简写,省去后面的
new 数据类型[]
。如下:
// 注意:虽然省去了new T[], 但是编译器编译代码时还是会还原
int[] array1 = {0,1,2,3,4,5,6,7,8,9};
double[] array2 = {1.0, 2.0, 3.0, 4.0, 5.0};
String[] array3 = {"hell", "Java", "!!!"};
- 数组也可以按照如下C语言个数创建(不推荐)。如下:
/*
该种定义方式不太友好,容易造成数组的类型就是int的误解
[]如果在类型之后,就表示数组类型,因此int[]结合在一块写意思更清晰
*/
int arr[] = {1, 2, 3};
- 静态和动态初始化也可以分为两步,但是省略格式不可以。如下:
int[] array1;
array1 = new int[10];
int[] array2;
array2 = new int[]{10, 20, 30};
// 注意省略格式不可以拆分, 否则编译失败
// int[] array3;
// array3 = {1, 2, 3};
- 如果没有对数组进行初始化,数组中元素有其默认值
6.3、数组的使用
数组在内存中是一段连续的空间,空间的编号都是从0开始的,依次递增,该编号称为数组的下标,数组可以通过下标访问其任意位置的元素。
【注意事项】
- 数组是一段连续的内存空间,因此支持随机访问,即通过下标访问快速访问数组中任意位置的元素
- 下标从0开始,介于[0, N)之间不包含N,N为元素个数,不能越界,否则会报出下标越界异常。
七、类和对象
Java是一门纯面向对象的语言,在面向对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物的认知,对于大型程序的设计、扩展以及维护都非常友好。
7.1、类的定义
在java中定义类时需要用到class关键字,具体语法如下:
// 创建类
class 类名{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}
class
为定义类的关键字,{}
中为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成员属性或者类成员变量。方法主要说明类具有哪些功能,称为类的成员方法。
【注意事项】
- 类名注意采用大驼峰定义
- 成员前写法统一为
public
,后面会详细解释 - 此处写的方法不带
static
关键字. 后面会详细解释。
7.2、类的使用
一般情况下,使用一个类就必须要实例化一个类,用类的类型创建对象的过程,称为类的实例化,在java中采用new
关键字,配合类名来实例化对象。
7.3、类和对象的说明
- 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员。
- 类是一种自定义的类型,可以用来定义变量。
- 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
7.4、this的引用
7.4.1、this引用存在的意义
形参名不小心与成员变量名相同时,那函数体中到底是谁给谁赋值?成员变量给成员变量?参数给参数?参数给成员变量?成员变量参数?估计自己都搞不清楚了。
7.4.2、什么是this引用
this
引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
7.4.3、this引用的特性
this
的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型this
只能在"成员方法"中使用- 在"成员方法"中,
this
只能引用当前对象,不能再引用其他对象 -
this
是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法 - 对象的引用传递给该成员方法,this负责来接收
7.5、对象的构造及初始化
7.5.1、初始化对象
- 就地初始化
- 通过该类的构造方法进行初始化
7.5.2、构造方法
- 概念:构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
【注意事项】
- 构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间。
- 特性:
- 名字必须与类名相同
- 没有返回值类型,设置为
void
也不行 - 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
- 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
【注意事项】
- 一旦用户定义,编译器则不再生成。
this(...)
必须是构造方法中第一条语句。- 构造方法不能形成环。
7.6、封装
7.6.1、封装的概念
面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节。
7.6.2、访问限定符
范围 | private | default | protected | public |
同一包中的同一类 | √ | √ | √ | √ |
同一包中的不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
不同包中的非子类 | √ |
【说明】
protected
主要是用在继承中,继承部分详细介绍default
权限指:什么都不写时的默认权限- 访问权限除了可以限定类中成员的可见性,也可以控制类的可见性
7.7、static成员
7.7.1、static修饰的成员变量
static
修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
【静态成员变量特性】
- 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
- 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
- 类变量存储在方法区当中
- 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
7.7.2、static修饰成员方法
Java中,被static
修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的。
【静态方法特性】
- 不属于某个具体的对象,是类方法
- 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者
- 不能在静态方法中访问任何非静态成员变量
7.7.3、static成员变量初始化
静态成员变量的初始化分为两种:就地初始化和静态代码块初始化。
- 就地初始化:在定义时直接给出初始值
- 静态代码块初始化:利用静态代码块进行初始化
7.8、内部类
7.8.1、内部类的概念
在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。
【注意事项】
- 定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类
- 内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件
7.8.2、内部类的分类
- 成员内部类(普通内部类:未被
static
修饰的成员内部类和静态内部类:被static
修饰的成员内部类) - 局部内部类(不谈修饰符)、匿名内部类
【注意事项】
- 内部类其实日常开发中使用并不是非常多,大家在看一些库中的代码时候可能会遇到的比较多,日常开始中使用最多的是匿名内部类。
- 【实例内部类注意事项】
- 外部类中的任何成员都可以在实例内部类方法中直接访问
- 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
- 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名 称.this.同名成员 来访问
- 实例内部类对象必须在先有外部类对象前提下才能创建
- 实例内部类的非静态方法中包含了一个指向外部类对象的引用
- 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
- 【静态内部类注意事项】
- 在静态内部类中只能访问外部类中的静态成员
- 创建静态内部类对象时,不需要先创建外部类对象
- 【局部内部类注意事项】
- 局部内部类只能在所定义的方法体内部使用
- 不能被
public
、static
等修饰符修饰 - 编译器也有自己独立的字节码文件,命名格式:外部类名字 $ 数字内部类名字 .class
- 几乎不会使用
八、继承和多态
8.1、继承
8.1.1、继承的概念
继承机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。
8.1.2、继承的语法
在Java中如果要表示类之间的继承关系,用extends
关键字继承父类。
【注意事项】
- 子类会将父类中的成员变量或者成员方法继承到子类中了
- 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
8.1.3、父类成员访问
- 子类中访问父类的成员变量:
- 在子类方法中或者通过子类对象访问成员时:
- 如果访问的成员变量子类中有,优先访问自己的成员变量。
- 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
- 如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
- 总结:成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找。
- 子类中访问父类的成员方法:
- 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
- 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错。
8.1.4、super关键字
Java提供了super
关键字,该关键字主要作用:在子类方法中访问父类的成员。
【注意事项】
- 只能在非静态方法中使用
- 在子类方法中,访问父类的成员变量和方法
8.1.5、子类构造方法
子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整 ,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。
【注意事项】
- 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的
super()
调用,即调用基类构造方法 - 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败
- 在子类构造方法中,
super(...)
调用父类构造时,必须是子类构造函数中第一条语句 super(...)
只能在子类构造方法中出现一次,并且不能和this
同时出现
8.1.6、super和this
【相同点】
- 都是Java中的关键字
- 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
- 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
【不同点】
this
是当前对象的引用,当前对象即调用实例方法的对象,super
相当于是子类对象中从父类继承下来部分成员的引用- 在非静态成员方法中,
this
用来访问本类的方法和属性,super
用来访问父类继承下来的方法和属性 - 在构造方法中:
this(...)
用于调用本类构造方法,super(...)
用于调用父类构造方法,两种调用不能同时在构造方法中出现 - 构造方法中一定会存在
super(...)
的调用,用户没有写编译器也会增加,但是this(...)
用户不写则没有
8.1.7、继承方式
通过extends
来继承。
【注意事项】
Java中不支持多继承。
时刻牢记,我们写的类是现实事物的抽象。而我们真正在公司中所遇到的项目往往业务比较复杂,可能会涉及到一系列复杂的概念,都需要我们使用代码来表示,所以我们真实项目中所写的类也会有很多,类之间的关系也会更加复杂。但是即使如此, 我们并不希望类之间的继承层次太复杂。一般我们不希望出现超过三层的继承关系。如果继承层次太多,就需要考虑对代码进行重构了。如果想从语法上进行限制继承,就可以使用final
关键字。
8.2、多态
8.2.1、多态的概念
通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
8.2.2、多态实现条件
- 必须在继承体系下
- 子类必须要对父类中方法进行重写
- 通过父类的引用调用重写的方法
8.2.3、重写
重写:也称为覆盖。重写是子类对父类非静态、非private
修饰,非final
修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定
于自己的行为。 也就是说子类能够根据需要实现父类的方法。
【方法重写的规则】
- 子类在重写父类的方法时,一般必须与父类方法原型一致:返回值类型 方法名 (参数列表) 要完全一致。
- 被重写的方法返回值类型可以不同,但是必须是具有父子关系的。
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为
protected
。 - 父类被
static
、private
修饰的方法、构造方法都不能被重写。 - 重写的方法, 可以使用
@Override
注解来显式指定。有了这个注解能帮我们进行一些合法性校验。例如不小心将方法名字拼写错了 (比如写成aet
),那么此时编译器就会发现父类中没有aet
方法,就会编译报错,提示无法构成重写。
【重写和重载的区别】
区别点 | 重写 | 重载 |
参数列表 | 一定不能修改 | 必须修改 |
返回类型 | 一定不能修改(除非可以构成父子类关系) | 可以修改 |
访问限定符 | 一定不能做更严格的限制(可以降低限制) | 可以修改 |
即:方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
8.2.4、转型
- 向上转型
实际就是创建一个子类对象,将其当成父类对象来使用。
语法格式:
父类类型 对象名 = new 子类类型()
【使用场景】
- 直接赋值
- 方法传参
- 方法返回
- 向下转型
将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
8.2.5、多态的优缺点
【使用多态的好处】
- 能够降低代码的 "圈复杂度", 避免使用大量的
if-else
。 - 可扩展能力更强。
【使用多态的缺陷】
- 代码的运行效率降低。
- 属性没有多态性。
- 当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
- 构造方法没有多态性。
九、抽象类和接口
9.1、抽象类
9.1.1抽象类的概念
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
9.1.2、抽象类的语法
在Java中,一个类如果被abstract
修饰称为抽象类,抽象类中被abstract
修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
【注意】
抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。
9.1.3、抽象类的特性
- 抽象类不能直接实例化对象
- 抽象方法不能是
private
的 - 抽象方法不能被
final
和static
修饰,因为抽象方法要被子类重写 - 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用
abstract
修饰 - 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
- 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量
9.1.4、抽象类的作用
提醒程序猿写抽象类里面的方法,使用抽象类相当于多了一重编译器的校验。预防出错。
9.2 接口
9.2.1、接口的概念
接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。
9.2.2、接口的语法
将class
关键字换成interface
关键字,就定义了一个接口。
9.2.3、接口的使用
利用implements
关键字,和extends
的位置一样,但是意义不一样,子类和父类之间是extends
继承关系,类与接口之间是implements
实现关系。而且接口可以多继承。
9.2.4、接口特性
- 接口类型是一种引用类型,但是不能直接
new
接口的对象 - .接口中每一个方法都是
public
的抽象方法, 即接口中的方法会被隐式的指定为public abstract
只能是public abstract
,其他修饰符都会报错) - 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现
- 重写接口中方法时,不能使用默认的访问权限
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为
public static final
变量 - 接口中不能有静态代码块和构造方法
- 接口虽然不是类,但是接口编译完成后字节码文件的后缀格式也是 .class
- 如果类没有实现接口中的所有的抽象方法,则类必须设置为抽象类
- jdk8中:接口中还可以包含
default
方法。
注意:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。
9.3、抽象类和接口的区别
抽象类中可以包含普通方法和普通字段,这样的普通方法和字段可以被子类直接使用(不必重写),而接口中不能包含普通方法,子类必须重写所有的抽象方法。
十、String 类
10.1、String 类的常用方法
- 字符串构造
String
对象的比较- 字符串查找
- 大小写,字符串数组之间的转化
- 字符串的替换
- 字符串的拆分
- 字符串的删除
- 字符串的修改
【注】:这只是简写,具体内容可以看博主的往期博客《Java中String类的详解》
十一、认识异常
JavaSE中的异常是指程序在运行时发生的错误或异常事件。JavaSE提供了强大的异常处理机制,使程序员能够在出现异常时进行处理,从而使程序更加健壮、可靠。
11.1、异常的概念
JavaSE的异常处理包括两个重要的概念:抛出异常和捕获异常。当JavaSE程序运行时发生了异常,就会抛出异常,即程序会终止并打印异常信息。程序员可以使用try-catch
语句来捕获异常,再进行特定的处理。
11.2、检查异常和运行时异常
11.2.1、检查异常
检查异常通常是指程序在运行时发现了错误,需要在编译期间进行处理,否则编译器将无法通过。比如IOException
、SQLException
等。
11.2.2、运行时异常
运行时异常是指程序在运行时发生的意外错误,通常是由程序逻辑错误或者不合理的数据输入造成的。比如NullPointerException
、ArrayIndexOutOfBoundsException
等。
11.3、异常的处理
当JavaSE程序抛出了异常,它会根据异常类的继承关系,从下到上依次查找到第一个匹配的catch
子句,并执行相应的逻辑代码。如果程序没有找到合适的catch
子句,则程序将终止并打印异常信息。在异常处理中,JavaSE中的finally
子句可用于添加必须执行的代码块,无论异常是否发生,都会执行。
11.3.1自定义异常
JavaSE还支持自定义异常。自定义异常可以根据业务需求进行设计,提高程序的灵活性和可读性。自定义异常需要继承Throwable
或Exception
类,并重载构造方法。
11.4、总结:
JavaSE中的异常处理机制是JavaSE的重要特性之一,可以帮助程序员有效地处理异常,提高程序的健壮性和可靠性。JavaSE的异常分为检查异常和运行时异常两种,都需要在程序中进行合适的处理。通过try-catch
语句可以捕获异常,并进行特定的处理。如果程序没有找到合适的catch
子句,则会终止程序并打印异常信息。在编写JavaSE程序时,合理使用异常处理机制将使程序更加稳定和健壮。
十二、JavaSE大汇总总结
JavaSE大总汇是一个全面的 JavaSE 教程,涵盖了 JavaSE 的各种知识点。在这里,我们将对 JavaSE 大总汇进行最后总结,以帮助你进一步理解 JavaSE 的知识点。
- 首先,JavaSE 大总汇的最基础的内容包括:Java 程序的基础语法、变量、数据类型、运算符等等。
- 其次,JavaSE 大总汇还介绍了 Java 的控制语句,如
if-else
、while
、for
等等。这些控制语句可以帮助你控制程序的逻辑和流程。 - 除此之外,JavaSE 大总汇还介绍了面向对象编程的概念和实践,包括了Java的类、对象、继承、封装和多态等等。
- JavaSE 大总汇还介绍了常用的抽象类和接口,如IO流、集合、异常处理等等。通过本次JavaSE大总汇学习,你可以掌握Java编程的核心知识点,并能够独立编写简单Java程序。
- 总之,JavaSE大总汇是一个非常有用的Java入门教程,它可以帮助你快速掌握Java编程知识,为日后的Java开发打下坚实的基础。希望你在学习JavaSE大总汇过程中有所收获,能够在日后的学习和工作中成功应用Java技术。
十三、心灵鸡汤
在JavaSE大总汇的学习过程中,你也许会遭遇挫折和困难,但这并不意味着你应该放弃。学习编程需要坚持和耐心,每一次的尝试都是一次进步,每一个错误都是一次学习经验。请保持学习的热情,不断提高自己的技能和知识水平,勇敢地迎接未来的挑战。无论你在编程的道路上遇到什么困难,都要相信自己的能力,勇往直前,最终你会发现,所有的努力都是值得的。
标签:构造方法,子类,成员,运算符,总汇,呕心沥血,JavaSE,父类,方法 From: https://blog.51cto.com/bitzmbdp/6232128