java基础复习篇
周瑜 Lv2

Java基础复习篇

1.Java的特性和优势

  • 简单性
  • 面向对象
  • 可移植性
  • 高性能
  • 分布式
  • 动态性
  • 多线程
  • 安全性
  • 健壮性

2.JDK、JRE、JVM

3.IDEA优化

4.Java基础语法

4.1.注释

  • // 单行注释
  • /* */ 多行注释
  • /** */ 文档注释

4.2.数据类型

  • 强类型语言 :要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用
  • 弱类型语言:跟强类型相反,比较随意

  • Java的数据类型分为两大类

    • 基本类型
      • 基本类型包括数值类型和boolean类型
      • 数值类型又包括整数类型、浮点类型和字符类型
      • 整数类型又包括以下几个
        • byte –占1个字节 范围(-128~127)
        • short –占2个字节 范围(-32768~32767)
        • int –占4个字节 范围(-2147483648~2147483647)
        • long –占8个字节 范围(-9223372036854775808~9223372036854775807)
      • 浮点类型包括
        • float –占4个字节
        • double –占8个字节
      • 字符类型有char –占2个字节
      • 而boolean类型只有true和false两个,各占一个字节
    • 引用类型
      • 接口
      • 数组
  • 最好避免使用浮点数进行比较,因为浮点数的精度会丢失,如果有这个场景,使用BigDecimal工具类来比较

  • 所有的字符本质还是数字(97 = a,65 = A)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Project {
    public static void main(String[] args) {

    //字符类型
    char a = 'a';
    char b = '张';

    System.out.println(a);
    System.out.println("a转为int:"+(int)a);
    System.out.println(b);
    System.out.println("张转为int:"+(int)b);
    }
    }

    image-20210330173630434

  • 布尔值知识扩展

    1
    2
    3
    4
    boolean flag = true;
    if(flag==true){} //新手
    if(flag){} //老手
    //less is More! 代码要精简易读

4.3.类型转换

image-20210330175514482

  • 强制转换 (类型)变量名 高–低

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class project1 {
    public static void main(String[] args) {
    int i = 150;
    byte b = (byte) i; //内存溢出

    System.out.println(i);
    System.out.println(b);
    }
    }

    image-20210330175552009

    ps:我们可以看到byte b打印的值为-106这是为什么呢?

    答:我们从底层源码可以看到byte最大值为127,我们的int i 为150,超出了byte的最大内存,造成内存溢出,byte值就会重新循环

    Byte的底层源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * A constant holding the minimum value a {@code byte} can
    * have, -2<sup>7</sup>.
    */
    public static final byte MIN_VALUE = -128;

    /**
    * A constant holding the maximum value a {@code byte} can
    * have, 2<sup>7</sup>-1.
    */
    public static final byte MAX_VALUE = 127;
  • 自动转换 低–高

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class project1 {
    public static void main(String[] args) {
    int i = 150;
    byte b = (byte) i;
    //我们可以看到int i转为double类型不需要加(类型)变量名也不会报错,这就是低到高的自动转换
    double d = i;
    System.out.println(i);
    System.out.println(b);
    }
    }

注意点:

  1. 不能对布尔值进行转换

  2. 不能把对象类型转换为不相干的类型

  3. 在把高容量转换到低容量的时候,强制转换

  4. 转换的时候可能存在内存溢出,或者精度问题

    1
    2
    System.out.println((int)27.96); //27
    System.out.println((int)56.48f); //56

    image-20210330181127325

    ps:我们的double类型和浮点类型转成int并不会四舍五入,而会丢失精度,直接舍弃小数点后面的值

  5. char 跟 int 之间的转换

    1
    2
    3
    4
    char c = 97;
    int x = c+1;
    System.out.println(x);
    System.out.println((char)x);

    image-20210330194234786

    ps:我们可以看到char转换成int是可以做运算的,但是当我们把运算后的x值强转为char的时候x的值就变成了b,这是因为在char字符中97对应的a,加一之后就会变成b,字符的本质就是数字,字符和数字的对应也是有顺序的。

  6. 操作比较大的数的时候,注意溢出问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class project2 {
    public static void main(String[] args) {
    //jdk7的新特性,数字之间可以用下划线分割
    int money = 10_0000_0000;
    int years = 30;
    int total = money*years; //-64771072,计算的时候超出了int的最大内存,导致内存溢出
    long total1 = money*years; //-64771072,计算后默认是int类型,在转换之前就已经溢出了
    long total2 = money*(long)years; //30000000000,先将一个值转换,计算后会将值转换为long类型
    System.out.println(total);
    System.out.println(total1);
    System.out.println(total2);
    }
    }

4.4.变量和常量

变量:就是可以变化的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Project3 {
static double money = 2500; //类变量 使用static修饰
//实例变量,属于对象,想调用这个变量,需要先实例对象
//布尔值 默认是false
//除了基本数据类型,其他的类型默认值都是null
String name; //如果不进行初始化,默认值是null
int age; //默认值是0

public static void main(String[] args) {
int i = 1; //局部变量,只在当前{}里面有效,而且必须声明和初始化值
System.out.println(i);
//实例变量
Project3 project3 = new Project3();
System.out.println(project3.age);
System.out.println(project3.name);
//类变量
System.out.println(money);
}
public void add(){
// System.out.println(i); //由于这个i是局部变量,只在声明他的{}里面有效,所有在其他方法中取不到
}
}

image-20210331101228910

变量的命名规范:

  • 所有变量,方法,类名:都要求见名知意
  • 类成员变量:首字母小写和驼峰原则:monthSalary,除了第一个单词以外,后面的单词首字母大写
  • 局部变量:首字母小写和驼峰原则
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun()

常量:初始化后不能再改变值!不会动的值,常量名一般使用大写字符和下划线:MAX_VALUE

1
2
3
4
5
6
7
8
9
10
11
public class Project4 {
//常量:使用final修饰,被final修饰过的值就不能再修改
//static也是修饰符,修饰符不分先后
final static double PI = 3.14;
static final String NAME = "zhangsan";

public static void main(String[] args) {
System.out.println(PI);
System.out.println(NAME);
}
}

image-20210331101653067

ps:常量不能被修改,初始化之后值就给定死了

image-20210331101946262

4.5.运算符

  • 算术运算符:+,-,*,/,%,++,–
  • 赋值运算符:=
  • 关系运算符:>,<,>=,<=,==,!=,instanceof
  • 逻辑运算符:&&,||,!
  • 位运算符:&,|,^,~,>>,<<,>>>(了解)
  • 条件运算符:?,:
  • 扩展赋值运算符:+=,-=,*=,/=

一元运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Project5 {
public static void main(String[] args) {
// ++ -- 自增,自减,一元运算符

int a = 2;
int b = a++; //执行完这行代码后,先给b赋值,再自增,相当于在它下面添加了一行 int a=a+1;
int c = ++a; //执行完这行代码后,先自增,再给c赋值,相当于在它上面添加了一行 int a=a+1;
System.out.println(a);
System.out.println(b);
System.out.println(c);

}
}

image-20210331105559346

短路运算

  • &&:如果前面一个为假就不会再往后面执行

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Project6 {
    public static void main(String[] args) {
    int a = 4;
    boolean b = (a<4) && (a++<4);

    System.out.println(a);
    System.out.println(b);
    }
    }

    image-20210331110355787

    ps:我们可以看到a打印的还是4,如果往&&后面去执行了a++就会是5

    三元运算符:

1
2
3
4
5
6
7
public class Project7 {
public static void main(String[] args) {
//三元运算符:x ? y : z 如果x为true就是y 如果x为false就是z
int score = 80; //成绩
System.out.println(score<60 ? "不及格" : "及格");
}
}

4.5.JavaDoc生成文档

5.Java流程控制

5.1.Scanner的使用

5.2.顺序结构

  • Java的基本结构就是顺序结构,除非特别指明,否则按照顺序一句一句执行。
  • 顺序结构是最简单的算法结构,他是任何一个算法都离不开的一种基本算法结构

5.3.选择结构

  • if单选择结构
  • if双选择结构
  • if多选择结构
  • 嵌套的if结构
  • switch多选择结构
    • 从JavaSE 7开始 switch就支持字符串类型了
    • case穿透 ,为了防止case穿透,尽量在每个case后面都加上break;

拓展:反编译 java — class(字节码文件) —反编译(IDEA)

image-20210331120620494

ps:哈希通过特定算法,给每个对象一个唯一的值

5.4.循环结构

while循环

  • 只要布尔表达式为true,循环就会一直执行下去

  • 我们大部分情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环

  • 少部分情况需要循环一直执行,比如服务器的请求响应监听等。

  • 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或者造成程序卡死崩溃!

  • 实例:计算1+2+3+……+100=?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    public class Project8 {
    public static void main(String[] args) {
    int i = 1;
    int sum = 0;
    while (i<=100){
    sum+=i;
    i++;
    }
    System.out.println(sum);
    }
    }

    image-20210331123101291

do while循环:

​ 和while循环的区别:

  • while是先判断后执行,do while是先执行后判断
  • do while 总是保证循环体至少会被执行一次!这是他们的主要差别

for循环:

  • for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构

  • 实例1:计算0到100之间的奇数和偶数和

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Project9 {
    public static void main(String[] args) {
    int oddSum = 0;
    int evenSum = 0;
    for (int i = 0; i <=100; i++) {
    if(i%2!=0){
    evenSum+=i;
    }else{
    oddSum+=i;
    }
    }
    System.out.println("奇数和:"+evenSum);
    System.out.println("偶数和:"+oddSum);
    }
    }

结果:image-20210331142039220

  • 实例2:用for循环输出1-1000之间能被5整除的数,并且每行输出3个

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package demo2;

    public class Demo1 {

    public static void main(String[] args) {
    int l = 0;
    for (int i = 1; i <= 1000; i++) {
    if (i % 5 == 0) {
    System.out.print(i + "\t");
    l++;
    }
    if (l == 3) {
    System.out.println();
    l=0;
    }
    }
    }
    }

    image-20210331143433012

  • 实例3:打印九九乘法表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package demo2;

    public class Demo2 {
    public static void main(String[] args) {
    for (int i = 1; i <=9; i++) {
    for (int j = 1; j <=i; j++) {
    System.out.print(i+"*"+j+"="+(i*j)+"\t");
    }
    System.out.println();
    }
    }
    }

    image-20210331144429983

增强for循环:

  • Java5引入了一种主要用于数组或集合的增强型for循环

  • 实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package demo2;

    public class Demo3 {
    public static void main(String[] args) {
    int[] a = {1,2,3,4,5};
    for (int i : a) {
    System.out.println(i);
    }
    }
    }

    image-20210331145249723

break continue goto关键字(了解):

  • break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(break也可以在switch语句中使用)

  • continue语句用在循环句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定

总结实例:打印三角形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package demo2;

public class Demo4 {

public static void main(String[] args) {
for (int i = 0; i <5; i++) {
for (int j = 5; j >=i; j--) {
System.out.print(" ");
}
for (int x = 1; x <=(i*2+1); x++) {
System.out.print("*");
}
System.out.println();
}
}
}

image-20210331152318232

6.Java方法

何为方法:

  • Java方法是语句的集合,他们在一起执行一个功能
  • 方法就是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用
  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合,我们设计方法的时候,最好保持方法的原子性,就是一个方法只实现1个功能,这样利于我们后期的扩展。

方法的定义:

  • Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

  • 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

    • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
    • 返回值类型︰方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void。
    • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
    • 参数类型:参数像是一气占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
      • 形式参数:在方法被调用时用于接收外界输入的数据。
      • 实参:调用方法时实际传给方法的数据。
    • 方法体:方法体包含具体的语句,定义该方法的功能。
  • 语法:

1
2
3
4
修饰符 返回值类型 方法名 (参数类型 参数名){
方法体
return 返回值;
}

方法的重载:

  • 重载就是在一个类中,有相同的函数名称,但形参不同的函数

  • 方法的重载规则:

    • 方法名称必须相同
    • 参数列表不许不同(个数不同,类型不同,参数排列顺序不同)
    • 方法的返回类型可以相同也可以不同
    • 仅仅返回类型不同不足以成为方法的重载
  • 实现理论:方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,已选择对应的方法,如果匹配失败,则编译器报错。

命令行传参:

可变参数:

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后面加一个省略号(…)
  • 一个方法中只能定义一个可变参数,他必须是方法的最后一个参数。任何普通的参数必须在它之前声明
1
2
3
4
5
6
7
8
9
10
11
12
13
package demo2;

public class Demo5 {
public static void main(String[] args) {
Demo5 demo5 = new Demo5();
demo5.add(1,2,3);
}
public void add(int ... a){
for (int i : a) {
System.out.println(i);
}
}
}

image-20210331161854877

ps:可变参数的本质上就是数组

递归:

  • 递归就是A方法调用A方法,就是自己调自己

  • 递归结构包括两个部分

    • 递归头:什么时候不调用自身方法,如果没有头,将陷入死循环,就是结束递归的方法
    • 递归体:什么时候需要调用自身方法
  • 实例:阶乘

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package demo2;

    public class Demo6 {

    public static void main(String[] args) {
    Demo6 demo6 = new Demo6();
    System.out.println(demo6.f(5));
    }
    public int f(int num){
    if(num == 1){
    return 1;
    }
    if(num>1){
    num = num*f(num -1);
    }
    return num;
    }
    }

    image-20210331163737684

    ps:不要用递归做大的运算,不然很容易就内存溢出了

实例:编写一个计算器

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
package demo2;

import java.util.Scanner;

public class Demo7 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean flag = true;
while (flag){
System.out.println("请输入第一个数:");
double num1 = scanner.nextDouble();
System.out.println("请输入运算符:");
String n = scanner.next();
System.out.println("请输入第二个数:");
double num2 = scanner.nextDouble();
Demo7 demo7 = new Demo7();
double result = 0;
switch (n){
case "+":
result = demo7.add(num1,num2);
System.out.println(result);
break;
case "-":
result = demo7.minus(num1,num2);
System.out.println(result);
break;
case "*":
result = demo7.times(num1,num2);
System.out.println(result);
break;
case "/":
result = demo7.into(num1,num2);
System.out.println(result);
break;
}
System.out.println("y/n:继续/退出");
String y = scanner.next();
if (y.equals("n")){
flag = false;
}

}

}

//加法
public double add(double num1,double num2){
return num1+num2;
}
//减法
public double minus(double num1,double num2){
return num1-num2;
}
//乘法
public double times(double num1,double num2){
return num1*num2;
}
//除法
public double into(double num1,double num2){
return num1/num2;
}
}

image-20210331171108007

7.数组

数组的定义:

  • 数组是相同类型数据的有序集合
  • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
  • 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问他们,数组的下标是从0开始的

数组声明创建的几种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package demo2;

public class Demo8 {
public static void main(String[] args) {
int[] a = new int[5]; //创建一个长度为5的数组
String[] b = {"张三","李四","王五","赵六"}; //直接创建数组并赋值
//给数组赋值,数组的下标是从0开始的
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
//使用增强for循环遍历数组
for (int i : a) {
System.out.println(i);
}
for (String s : b) {
System.out.println(s);
}

}
}

image-20210331173313379

数组的四个特点:

  • 数组的长度是确定的,数组一旦被创建,它的大小就是不可改变的。
  • 数组的元素必须是相同类型,不允许出现混合类型
  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型
  • 数组变量属引用类型,数组也可以看出是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的

总结:

  • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
  • 数组也是对象。数组元素相当于对象的成员变量
  • 数组长度是确定的,不可变的。如果越界,则报:ArrayIndexOutoBounds

实例:

  • 计算所有元素的和 和 查找最大的元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int maxNum = 0;
    int sum = 0;
    for (int i = 0; i < a.length; i++) {
    sum+=a[i]; //计算所有元素的和
    //查找最大的元素
    if(a[i]>maxNum){
    maxNum=a[i];
    }
    }
    System.out.println(sum);
    System.out.println(maxNum);

    }

    image-20210331180221474

  • 数组入参

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package demo2;

    public class Demo9 {
    public static void main(String[] args) {
    int[] array = {1,2,3,4,5};
    Demo9 demo9 = new Demo9();
    demo9.test(array);
    }

    public void test(int[] array){
    for (int i = 0; i < array.length; i++) {
    System.out.println(array[i]);
    }
    }
    }

    image-20210331183150627

  • 反转数组

    1
    2
    3
    4
    5
    public  void test1(int[] arrays){
    for (int i = arrays.length-1; i>=0; i--) {
    System.out.println(arrays[i]);
    }
    }

    image-20210331185135757

多维数组:

  • 多维数组可以看出是数组的数组,比如二维数组就是一个特殊的一维数组,其每个元素都是一个一维数组。

  • 二维数组的两种创建方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package demo3;

    public class Demo1 {
    public static void main(String[] args) {
    int[][] array = new int[3][5];
    array[0][1] = 1;
    array[0][4] = 5;
    System.out.println(array[0][4]);
    System.out.println("=========================");
    int[][] array1 = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};
    for (int i = 0; i < array1.length; i++) {
    for (int j = 0; j < array1[i].length; j++) {
    System.out.println(array1[i][j]);
    }
    }
    }
    }

    image-20210401095200749

Array类的常用方法:(详情查看jdk帮助文档)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package demo3;

import java.util.Arrays;

public class Demo2 {
public static void main(String[] args) {
int[] a = {5,4,9,1,4,3,6,7};
//打印数组
System.out.println(Arrays.toString(a));
//排序数组 ,升序
Arrays.sort(a);
System.out.println(Arrays.toString(a));
}
}

image-20210401100946883

冒泡排序法:

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
package demo3;

import java.util.Arrays;

public class Demo3 {
public static void main(String[] args) {
int[] a = {5,8,2,3,6,7,9,1,3};
Demo3 demo3 = new Demo3();
demo3.sort(a);
System.out.println(Arrays.toString(a));
}
public int[] sort(int[] array){
for (int i = 0; i < array.length-1; i++) {
for (int j = 0; j < array.length-i-1; j++) {
if(array[j+1]>array[j]){
int temp;
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
}

image-20210401105849938

ps:排序后的结果

稀疏数组:

8.面向对象编程

面向过程思想:

  • 步骤清晰简单,面对过程适合处理一些较为简单的问题,面向过程是具体的

面向对象思想:

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
  • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题。

总结:对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理

什么是面向对象:

  • 面向对象编程的本质就是:以类的方式组织代码,以对象的方式封装数据
  • 三大特性:封装,继承,多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物,类是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板

构造方法:

  • 和类命相同

  • 没有返回值

  • 作用:

    • new 的本质是在调用构造器
    • 初始化对象的值
  • 注意:定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造

创建对象内存分析:

图片引用狂神说Java

image-20210401134819218

封装:

  • 该露的露,该藏得藏,我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉,低耦合:仅暴露少量的方法给外部使用

  • 封装(数据的隐藏):通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏

  • 属性私有,提供一些可操作属性的get/set方法,set方法中还能做一些判断

  • 封装的好处:

    • 提高程序的安全性,保护数据
    • 隐藏代码的实现细节
    • 统一接口
    • 可维护性

继承:

  • Java中只有单继承,没有多继承
  • 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的两个类,一个为子类,一个为父类。子类继承父类,使用关键字extends来表示,子类继承父类,就会拥有父类的全部方法,子类可以调用父类的方法
  • 所有的类,都默认直接或间接继承Object类

super注意点:

  • super调用父类的构造方法,必须在构造方法的第一个

  • super必须只能出现在子类的方法或构造方法中

  • super和this不能同上调用方法

  • vs this

    • 代表的对象不同

      • this : 本身调用者这个对象
      • super : 代表父类对象的应用
    • 前提

      • this: 没有继承也可以使用
      • super:只能在继承条件才可以使用
    • 构造方法 :

      • this():本类的构造
      • super():父类的构造

方法重写:

  • 需要有继承关系,子类重写父类的方法
  • 方法名必须相同,参数列表也必须相同
  • 修饰符:范围可以扩大,但不能缩小:public>Protected>Default>private
  • 抛出的异常:范围可以缩小,但不能扩大
  • 重写,子类的方法和父类必须一致,方法体不同
  • 为什么需要重写:
    • 父类的功能,子类不一定需要,或者不一定满足!

多态:

  • 即同一方法可以根据发送对象的不同而采用多种不同的行为方式

  • 多态存在的条件

    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:

    • 多态是方法的多态,属性没有多态性
    • 要有继承关系才能类型转换
    • static方法:属于类,它不属于实例,不能重写,也就没有多态
    • final修饰的方法不能被修改,所有无法重写,所有也没有多态
    • private方法修饰的方法也不能重写,没有多态

static关键字详解:

  • 静态变量和静态方法都可以直接调用

  • 静态代码块:类加载的时候就会执行,只执行一次

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package demo3;

    public class Demo4 {
    //2
    {
    System.out.println("匿名代码块");
    }
    //类加载的时候就会执行,只会执行一次
    //1
    static {
    System.out.println("静态代码块");
    }
    //3
    public Demo4(){
    System.out.println("构造方法");
    }

    public static void main(String[] args) {
    Demo4 demo4 = new Demo4();
    System.out.println("=====================");
    Demo4 demo41 = new Demo4();
    }
    }
    ![image-20210401155655719](image-20210401155655719.png)

    image-20210401155804425

    ps:执行顺序:静态>匿名>构造 但是static只会执行一次

  • 静态导入包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package demo3;
    import static java.lang.Math.random;
    import static java.lang.Math.PI;

    public class Demo5 {
    public static void main(String[] args) {
    System.out.println(random());
    System.out.println(PI);
    }
    }

    image-20210401160428916

抽象类:

  • 类添加abstract关键字,就变成了抽象类

  • 方法加abstract关键字,就变成了抽象方法

  • 抽象方法只有方法名字 没有方法的实现,让继承抽象类的类去帮我们实现

    1
    2
    3
    4
    5
    6
    package demo3;
    //抽象类
    public abstract class Demo6 {
    //抽象方法,继承抽象类的必须重写这个方法,我们不需要写具体实现,交给继承的类去帮我们实现
    public abstract void add();
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package demo3;
    //继承抽象类
    public class Demo7 extends Demo6{
    //重写抽象方法,并添加具体实现
    @Override
    public void add() {
    System.out.println("继承抽象类的抽象方法");
    }

    public static void main(String[] args) {
    Demo7 demo7 = new Demo7();
    demo7.add();
    }
    }

    image-20210401161824534

  • 总结:

    • 不能new这个抽象类,只能靠子类去实现它
    • 抽象类中可以写普通的方法
    • 抽象方法必须在抽象类中

接口:

  • 接口可以定义一些方法,让不同的类去实现
  • 接口不能被实例化,接口中没有构造方法
  • 使用implements可以实现多个接口,实现接口必须要重写接口中的方法

内部类:

异常机制:

  • 五个关键字:
    • try:监控异常
    • catch:捕获异常
    • finally:处理善后工作,总会执行
    • throw:主动抛出异常,一般在方法中使用
    • throws:主动抛出异常,一般在方法上使用
  • Post title:java基础复习篇
  • Post author:周瑜
  • Create time:2021-04-01 17:20:04
  • Post link:https://xinblog.github.io/2021/04/01/java-md/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
 Comments