Java foundation
从0开始的Java学习之路。
一、入门
1、JVM
JVM:Java Virtual Machine Java 虚拟机
Java 虚拟机作用:字节码翻译成计算机可以读懂的代码
2、JVM与跨平台原理
3、编写、编译、执行
①编写程序,后缀名为.java
②使用javac命令编译,后缀为.class
③使用通过java命令执行(直接输入文件名执行,不用写后缀)
4、架构
字节码文件:
字节码文件只有Java虚拟机可以读懂(.class)
5、JavaSE和JavaEE
Java 里面有一些核心技术。分成两大类: JavaSE(普通的桌面应用,控制台)和 JavaEE(开发网站)。
6、JDK和JRE
JDK(Java Developer Kit : Java 开发工具包)和JRE(Java Runtime Environment : Java 运行时环境),如果我们安装了 JDK,默认JRE也被安装了。
JDK 里面包含的内容要多于JRE。JRE只用提供运行环境就可以了,JDK 既要提供开发编译环境,也要提供运行环境。
### 7、快捷键
1
2
3
4
psvm
public static void main(String[] args){}
sout
System.out.println();
二、基础
1、变量概念
变量类型的不同,决定了在内存中占用空间大小的不同。
变量三要素:
1
2
3
4
5
类型: 决定了占用空间的大小
名称: 如何提取数据
变量值: 可以改变的。
2、命名规范:
1)标识符不能和系统里的关键字同名
2)标识符只能包括字母、数字和下划线”_”,并且开头只能是字母或下划线
3)标识符必须先定义、后使用
4)在同一作用域内,标识符不能重复定义
5)标识符是区分大小写的,如sum 和 Sum 是不同的标识符
6)标识符要尽量做到“见名知义”,增强程序的可读性。
3、数据类型
变量:
整型int 、双精度浮点型double、字符型char、字符串String、boolean类型(true or false)
注意:
1
2
3
字符串"":标识字符串
字符串用双引号:"a"(单个字符的字符串)
字符用单引号,字符串用双引号
常量:
- 在程序运行中,值不能改变的量
- final double PI = 3.14;
- 优点:比较安全,后续代码不允许更改其值
注意事项
①常量名通常大写
②只能被赋值一次,通常定义时即对其进行初始化
4、运算符
赋值运算符
1
变量名 = 表达式;
算术运算符
1
2
3
+、-、*、/、%
自增++
自减--
5、类型转换
- 自动化类型转换
①类型相容
②目标类型 > 源类型
1
2
3
double num1 = 1.2;
int num2 = 2;
double result = num1 + num2;
- 强制类型转换
①(类型名)表达式
1
2
double a = 5.2;
int b = (int)a;
6、Scanner接收用户输入
①接收类型
1
2
3
4
5
6
Scanner input = new Scanner(System.in);
int num = input.nextInt();//接收整数
double BoyAverage = input.nextDouble();//接收小数
String name = input.next();//接收字符串
char a = input.next().charAt(0); // 获取输入字符串的第一个字符
注意:
1
import java.util.Scanner; //Scanner类在util包中
②通过 Scanner 类的 next() 与 nextLine()方法获取输入的字符串,在读取前我们一般需要使用 hasNext() 与 hasNextLine() 判断是否还有输入的数据。
- next():
- 一定要读取到有效字符后才可以结束输入
- 对输入有效字符之前的空白,next()方法会自动将其去掉
- 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
- next()不能得到带有空格的字符串
- nextLine():
- 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之后的所有字符
- 可以获得空白
小练习:
①next方式接收用户输入的字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class T08 {
public static void main(String[] args) {
//创建一个扫描器对象
Scanner scanner = new Scanner(System.in);
System.out.println("使用next方式接收:");
//判断用户有没有输入
if (scanner.hasNext()){
//使用next方法接收
String str = scanner.next(); //程序会等待用户输入完毕
System.out.println("输出的内容为:"+str);
}
//凡是属于IO流的类,如果不关闭会一直占用资源,要养成良好的习惯用完就关掉
scanner.close();
}
}
②nextLine方式接收用户输入的字符串
1
2
3
4
5
6
7
8
9
public class T09 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("使用nextline方式接收:");
String str = scanner.nextLine(); //程序会等待用户输入完毕
System.out.println(str);
scanner.close();
}
}
③把输入字符串的首字母转换为大写
1
2
3
4
5
6
7
8
9
public class T07 {
public static void main(String[] args) {
//把输入字符串的首字母转换为大写
Scanner input = new Scanner(System.in);
char a = input.next().charAt(0); //charAt(0)选择接收字符串的第一个
char Big_a = (char)(a-32);
System.out.println(Big_a);
}
}
④输入多个数字,并计算个数和总和,每输入一个数字用回车确认,通过输入非数字来结束输入并执行结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class T10 {
public static void main(String[] args) {
int n = 0;
double sum = 0;
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
sum+=x;
n++;
System.out.println("这是你输入的第"+n+"个数字");
}
System.out.println(n+"个数字的和为:"+sum+",平均值为:"+(sum/n));
scanner.close();
}
}
7、保留小数位
三、流程控制
1、关系运算符
2、if
3、switch
①switch语句中的变量类型可以为:
- byte、short、int或者char
- 从Java SE 7开始,switch支持字符串String类型
- 同时case标签必须为字符串常量或字面量
②.class文件可以用IDEA反编译
③小练习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class T12 {
public static void main(String[] args) {
String name = "喜羊羊";
switch(name){
case "喜羊羊":
System.out.println("聪明");
break;
case "懒羊羊":
System.out.println("懒");
break;
case "沸羊羊":
System.out.println("小丑");
default:
System.out.println("不是羊村的!!!");
}
}
}
4、while
5、for
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
for循环执行的次数是在执行前就确定的。
语法:
1
2
3
for(初始化;布尔表达式;更新){
//代码语句
}
快捷键:
1
2
100.for
fori
6、增强for循环
Java5引入了一种主要用于数组和集合的增强型for循环
语法:
1
2
3
for (声明语句:表达式){
//代码句子
}
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
实例:
1
2
3
4
5
6
7
8
public class T13 {
public static void main(String[] args) {
int[] numbers={1,3,5,7,9,11};
for (int x:numbers){
System.out.println(x);
}
}
}
7、break & coutinue
break在任何循环语句的主体部分,均可用break制衡环的流程;break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)
continue 语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接者进行下一次是否执行循环的判定。
8、练习
打印五行的三角形(采用分割法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class T14 {
public static void main(String[] args) {
for (int i=1 ; i <= 5; i++){
for (int j = 5; j > i; j--){
System.out.print(' ');
}
for (int j = 0; j < i; j++) {
System.out.print('*');
}
for (int j = 1; j < i; j++) {
System.out.print('*');
}
System.out.println("");
}
}
}
四、方法
1、什么是方法
Java方法是语句的集合,它们在一起执行一个功能
方法是解决一类问题的步骤的有序组合
方法包含于类或对象中
方法在程序中被创建,在其他地方被引用
设计方法的原则:
方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成1个功能,这样利于我们后期的扩展。
2、方法的定义
Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义个方法包含以下语法:
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
方法名:是方法的实际名称。方法名和参数表共同构成方法签名
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实参:调用方法时实际传给方法的数据。
- 方法体:方法体包含具体的语句,定义该方法的功能。
1
2
3
4
5
6
修饰符 返回值类型 方法名(参数类型 参数名){
...
方法体
...
return 返回值;
}
3、方法调用
调用方法:对象名方法名(实参列表)
Java 支持两种调用方法的方式,根据方法是否返回值来选择
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
1
int larger = max(30,40);
- 如果方法返回值是void,方法调用一定是一条语句.
1
System.out.printLn("Hello!");
例子:
return 0;
具有终止功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static int compere(int num1,int num2){
int res = 0;
if (num1 == num2){
System.out.println("两个数字一样大!!!");
return 0; //return 0; 具有终止功能
}
if (num1 > num2){
res = num1;
return res;
}else{
res = num2;
return res;
}
}
4、方法的重载
重载就是在一个类中,有相同的函数名称,但形参不同的函数
(方法可以有无限个重名的,但要确保参数类型不同)
方法的重载的规则:
方法名称必须相同
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)
方法的返回类型可以相同也可以不相同
仅仅返回类型不同不足以成为方法的重载
实现理论:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
小练习:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class T21 {
public static void main(String[] args) {
int res = 0;
res = Add(1.2,3);
System.out.println(res);
res = Add(1,5,100000);
System.out.println(res);
}
public static int Add(int a, int b){
return a+b;
}
public static int Add(double a, int b){
return (int)a+b;
}
public static int Add(int a, int b, int c){
return a+b;
}
}
5、命令行传参
IDEA左下角有Terminal
1
2
3
4
5
6
7
8
9
10
11
//T21.java 的绝对路径为\untitled3\src\happy\cn\method>
javac T21.java //编译为T21.class
java T21 //提示找不到或无法加载主类T21
返回到src目录,执行:
java happy.cn.method.T21
java happy.cn.method.T21 this is a param //传参
6、可变参数
- JDK 1.5开始,Java支持传递同类型的可变参数给一个方法
在方法声明中,在指定参数类型后加一个省略号(…)
- 注意:
- 一个方法中只能指定一个可变参数
- 它必须是方法的最后一个参数,任何普通的参数必须在它之前声明。
1
public static void proMax(double... numbers){}
7、递归
递归结构包括两个部分
递归头: 什么时候不调用自身方法。如果没有头,将陷入死循环
递归体: 什么时候需要调用自身方法
注意:
要有 边界条件(边界)、前阶段、返回阶段(n*(n-1))、
小计算可以用递归,大计算GG
五、数组
1、定义
数组是相同类型数据的有序集合
数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们
2、声明创建
语法:
1
2
3
dataType[] arrayRefVar; //首选的方法
或
dataType arrayRefVar[]; //效果相同,但不是首选方法
Java语言使用new操作符来创建数组,语法如下:
1
2
3
dataType[] arrayRefVar = new dataType[arraySize];
int[] nums = new int[20];
获取数组长度
1
2
3
4
array.length
int[] nums = new int[20];
len = nums.length
赋值
1
2
nums[0] = 1;
nums[1] = 2;
3、内存分析
①声明数组时,栈中压入一个array
,堆中没有东西
1
int[] nums = null;
②创建数组时,会在堆中开辟一块空间
1
nums = new int[10];
③给数组赋值时,会在堆开辟的空间中,填入相应的值
4、三种初始化
- 静态初始化:创建+赋值
1
2
int[] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
- 动态初始化:包含默认初始化
1
2
3
int[] a = new int[2];
a[0] = 1;
a[1] = 2;
数组的每个元素有默认值。
- 数组的默认初始化
- 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化。
5、四个基本变量
- 其长度是确定的。数组一旦被创建,它的大小就是不可以改变的
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型
- 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量
- 数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的
6、数组边界
下标的合法区间:[0,length - 1],如果越界就会报错
7、小结:
数组是相同数据类型(数据类型可以为任意类型)的有序集合
数组也是对象。数组元素相当于对象的成员变量
数组长度的确定的,不可变的。如果越界,则报: ArraylndexOutofBounds
8、数组使用
- 普通的For循环
- For-Each 循环
- 数组作方法入参
- 数组作返回值
9、多维数组
多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
1
2
int a[][] = new int[2][5];
//二维数组a可以看成一个两行五列的数组。
10、Array类
数组的工具类java.util.Arrays,此类包含用于操作数组的各种方法(如排序和搜索)
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
查看JDK帮助文档
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而”不用“使用对象来调用
(注意:是”不用”而不是“不能”)
具有以下常用功能:
给数组赋值:通过 fill 方法
对数组排序:通过 sort 方法按升序
比较数组:通过equals 方法比较数组中元素值是否相等
- 查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作
- ………
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package happy.cn.array;
import java.util.Arrays;
public class T32 {
public static void main(String[] args) {
int[] a = {1,2,3,4,324,6547,757,645,31};
//打印数组元素Arrays.toString
System.out.println(Arrays.toString(a));
//对数组进行排序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
//数组填充:把数组的每一项都填乘1
Arrays.fill(a,2);
System.out.println(Arrays.toString(a));
}
}
11、冒泡排序
冒泡排序无疑是最为出名的排序算法之一,总共有八大排序
冒泡的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人人尽皆知.
我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度为O(n2)。
练习:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package happy.cn.array;
import java.util.Arrays;
public class T33 {
public static void main(String[] args) {
int[] nums = {12,35,21,11,34,22,35,5474,325,36,457,232,5345,42,24,1};
int c = 0;
//从小到大 冒泡排序
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - 1 -i; j++){
if (nums[j] > nums[j+1]){
c = nums[j];
nums[j] = nums[j+1];
nums[j+1] = c;
}
}
}
System.out.println(Arrays.toString(nums));
}
}
优化:减少了冒泡的次数,加快运行时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package happy.cn.array;
import java.util.Arrays;
public class T33 {
public static void main(String[] args) {
int[] nums = {1,2,3,5,6,7,8,9};
int s = 0; //冒泡次数
int c = 0;
//从小到大 冒泡排序
for (int i = 0; i < nums.length - 1; i++) {
boolean flag = false; //优化:这里弄一个标识位
for (int j = 0; j < nums.length - 1 -i; j++){
if (nums[j] > nums[j+1]){
c = nums[j];
nums[j] = nums[j+1];
nums[j+1] = c;
s++;
flag = true; //如果有数字交换的话,flag为true标准着还要继续循环冒泡/
}
}
if (flag == false){
System.out.println("okk,到这里就不需要继续冒泡了,因为已经从小到大排序了!");
break;
}
}
System.out.println(Arrays.toString(nums));
System.out.println("一共冒泡了"+s+"次");
}
}
12、稀疏数组
当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组
- 稀疏数组的处理方式是:
- 记录数组一共有几行几列,有多少个不同值
- 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
- 稀疏数组就是记录原始数组的坐标、值
如图:
练习:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package happy.cn.array;
import java.sql.Array;
public class T34 {
public static void main(String[] args) {
//1、先造一个二维数组
int[][] array1 = new int[11][11];
array1[1][2] = 1;
array1[2][3] = 2;
//2、打印出来
for (int[] nums : array1){
for (int num : nums){
System.out.print(num+"\t");
}
System.out.println();
}
System.out.println("========================================");
//3、转换为稀疏数组
//①先统计有效值
int amount = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0){
amount++;
}
}
}
System.out.println("有效值的个数为:"+amount);
//②根据有效值的个数,创建稀疏数组的大小
int[][] array2 = new int[amount+1][3]; //行数为:有效值个数 + 1,因为第一行分别为原数组的行数、列数、有效值个数(为真实行数、列数)
array2[0][0] = 11;
array2[0][1] = 11;
array2[0][2] = amount;
//③遍历原数组,把有效值的坐标行数、坐标列数、值填入稀疏数组中(这里的行数、列数是有效值在原数组中的坐标)
int row = 1; //稀疏数组的坐标行数,因为坐标行数0,已经填了原数组的信息
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1[i].length; j++) {
if (array1[i][j] != 0){
array2[row][2] = array1[i][j]; //值
array2[row][0] = i; //坐标行数
array2[row][1] = j; //坐标列数
row++;
}
}
}
//4、打印完成后的稀疏数组
for (int[] nums : array2){
for (int num : nums){
System.out.print(num+"\t");
}
System.out.println();
}
System.out.println("========================================");
//5、还原为原数组
int[][] array3 = new int[array2[0][0]][array2[0][1]]; //还原原数组的大小
for (int i = 1; i < array2.length; i++) {
for (int j = 0; j < 3; j++) {
array3[array2[i][0]][array2[i][1]] = array2[i][2];
}
}
//6、打印处还原后的数组
for (int[] nums : array3){
for (int num : nums){
System.out.print(num+"\t");
}
System.out.println();
}
}
}
六、面向对象
属性+方法 = 类
1、面向过程&面向对象
- 面向过程思想
- 步骤清晰简单,第一步做什么,第二步做什么…
- 面对过程适合处理一些较为简单的问题
- 面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
- 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
- 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路区处理。
2、面向对象
面向对象编程(Object-Oriented Programming,OOP)
- 面向对象编程的本质就是: 以类的方式组织代码,以对象的形式组织(封装)数据
- 抽象
- 三大特性:封装、继承、多态
- 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
- 从代码运行角度考虑是先有类后有对象。类是对象的模板。
3、方法回顾
没有返回类型,也要return;
1
2
3
public void hello(){
return;
}
方法的定义
- 修饰符
- 返回类型
- break:跳出switch,结束循环 和 return的区别
- 方法名:注意规范就OK 见名知意
- 参数列表:(参数类型,参数名)…
- 异常抛出:疑问,后面讲解
①
static:静态方法。类名.方法名
可以直接调用
非静态方法:不能这样(类名.方法名
)调用。用new
这里的对象值变为实例化对象
②
都没有statc,a可以调用b;
都有static,a可以调用b;
a有static,b没有,a不能调用b
1
2
3
4
5
6
7
8
9
//和类一起加载的
public static void a(){
b();
}
//类实例化之后才存在
public void b(){
}
//已经存在的东西,调用不存在的东西会报错。所以a有static,b没有时,a不能调用b
这个例子就是实例化一个类之后,用方法给类的属性赋值
4、类与对象的创建
规范:一个项目应该只存在一个main方法
类里面有 属性 和 方法
5、构造器详解
- 使用new关键字创建对象
- 使用new关键字创建的时候,除了分配内存空间之外。还会给创建好的对象进行默认的初始化,以及对类中构造器的调用
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 1、必须和类的名字相同
- 2、必须没有返回类型,也不能写void
- 构造器必须要掌握
一个类即使什么也不写,它也会存在一个方法
显示的定义构造器:
1
2
3
public class Person{
public Person(){}
}
作用:
①实例化初始值
②使用new关键字,本质是在调用构造器
定义了有参构造之后,如果想使用无参构造,需要显式的定义一个无参构造。
这里是绿色小tips的内容。
6、创建对象内存分析
static:和类一起加载
左边是栈,右边是堆
7、简单小结类与对象
4、默认初始化:
- 数字:0 0.0
- char:u0000
- boolean:false
- 引用:null
8、封装详解
作用:
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 系统的可维护增加了
9、继承
- 继承的本质是对某一批类的抽象,从而时间对现实世界更好的建模
- extends的意思是“扩展”。子类是父类的扩展
- Java中类只有单继承,没有多继承。(一个父亲可以有多个儿子,一个儿子只能有一个父亲)
- 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
- 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键词extends来表示。
- 子类和父类之间,从意义上讲应该具有“is a”的关系
- 在Java中,所有类,都默认之间或者间接继承Object类
Ctrl+H
可以打开 “Type Hierarchy”(类型层次结构)窗口。在这个窗口中,可以看到当前选定类的层次结构,包括它的父类、子类以及实现的接口。
10、Super详解
私有的东西无法被继承 调用父类的构造器,必须要在子类构造器的第一行
父类是有参构造那就调用有参构造
总结:
- super注意点:
- super调用父类的构造方法,必须在构造方法的第一个
- super必须只能出现在子类的方法或者构造方法中
- super和this不能同时调用构造方法
- super和this对比:
- 代表的对象不同:
- this:本身调用者这个对象
- super:代表父类对象的应用
- 前提
- this:没有继承也可以使用
- super:只能在继承条件里才可以使用
- 构造方法
- this();本类的构造
- super():父类的构造
- 代表的对象不同:
11、方法重写
重写演示:
非静态方法才能重写 重写关键词只能是public
需要有继承关系,子类才能重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小:public > protected > default > private
- 抛出的异常:范围,可以被缩小,但不能扩大:ClassNotFoundException –> Exception(大)
重写,子类的方法和父类必须一致:方法体不同
为什么要重写:
- 父类的功能,子类不一定需要,或者不一定满足
Alt + Insert ; override;
12、什么是多态
即一个方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用指向子类对象
多态是方法的多态,属性没有多态性
父类型,可以指向子类,但是不能调用子类独有的方法 对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
强制类型转换(高转低)
13、instanceof
测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
1、父类引用指向之类的对象
2、把子类转换成父类,向上转型(可能会丢失自己本来的一些方法)
3、把父类转换成子类,向下转型(强制转换)
4、方便方法的调用,减少重复的代码(简洁)
14、static关键词详解
匿名代码块
静态代码块
static代码块只执行一次
静态导入包
15、抽象类
继承了抽象类的子类,要实现抽象类的所有方法,除非子类也是抽象类
接口可以多继承
类是单继承的
1、不能new这个抽象类,只能靠子类去实现它:约束
2、抽象类种可以写普通的方法
3、抽象方法必须在抽象类中(有抽象方法的一定是抽象类)
16、接口
声明类的关键字是class。声明接口的关键字是interface
智能的IDEA:
- Action为抽象类
- A为正常类
- UserService为接口
接口中的所有定义其实都是抽象的public abstract
1
2
3
4
public abstract void run(String name);
可以写成
void run(String name);
接口的实现用implements,需要重写接口中的方法
接口可以实现多继承
1、约束
2、定义一些方法,让不同的人实现
3、接口中定义的方法,都是public abstract
4、接口中定义常量:public static final
5、接口不能被实例化,接口中没有构造方法
6、implements可以实现多个接口
7、必须要重写接口中的方法
17、N种内部类
类套类
内部类可以获得外部类的私有属性、私有方法
静态内部类
一个Java类里面只能有一个public class ,但可以有多个class
方法里面也可以写类
匿名对象的使用
七、异常
1、Error和Exception
简单分类
检查性异常、运行时异常、错误ERROR
异常体系结构
2、捕获和抛出异常
五个关键字:
try、catch、finally、throw、throws
finally可以不写
如果要捕获多个异常,异常的范围应该从小到大写
选中,trl Alt T
打印错误栈信息
1
e.printStackTrace();
主动抛出异常
- 一般在方法中使用
用了try catch,不会停止,程序会继续运行下去
上抛出异常后,被catch
3、自定义异常
test()上抛之后在main()里面被catch
实际应用中的经验总结
八、JavaSE总结
#### JavaDoc
1
Javadoc -encoding UTF-8 -charset UTF-8 HelloWorld.java