01 Java 基础

01.1 准备

JDK (Java Development Kit):Java开发者工具包

javac.exe // 编译工具
java.exe // 执行工具

cmd常用命令

作用

盘符:

D:

dir

查看当前路径下的文件信息

cd

进入单级目录:cd Java

进入多级目录:cd D:\Software\Java

回退到上一级目录:cd …

回退到盘符根目录:cd \

cls

清屏

cmd中,cd时按Tab可自动补全

01.2 入门程序

编写一个HelloWorld

public class HelloWorld {
	public static void main(String[] args) {
		System.out.println("Hello World");
	}
}
  • 在cmd中编译
javac HelloWorld.java
  • 在cmd中运行
java HelloWorld // 不加后缀

文件名与类名需要保持一致

JDK11开始支持java直接运行

java HelloWorld.java

01.3 小知识
  • 高级语言会被编译到机器语言再进行执行
  • Debug指解决问题
01.4 JDK的组成

JRE(Java Runtime Environment):Java的运行环境

  • JVM(Java Virtual Machine):Java虚拟机,真正运行Java程序的地方
  • 核心类库:Java自己写好的程序,给程序员自己的程序调用的

开发工具:java;javac;…

以上并称为JDK(Java Development Kit):Java开发者工具包

只要在各平台上安装对应的JVM,就都可以运行Java程序

02 IDEA开发工具

02.1 简介

集成开发环境(IDE,Integrated Development Environment)

常用:IntelliJ IDEA,一般简称IDEA

在地址栏输入控制面板可直接打开

02.2 项目结构
project(项目、工程)
|--module(模块)
   |--package(包) // 一般命名为公司域名倒写.功能
      |--class(类)

Ctrl+D 复制这一行代码到下一行

02.3 常用快捷键

快捷键

功能效果

main/psvm、sout、_

快速输入相关代码

Ctrl + D

复制当前行数据到下一行

Ctrl + Y

删除所在行,建议用Ctrl + X

Ctrl + Alt + L

格式化代码

Alt + Shift + ↑,Alt + Shift + ↓

上下移动当前代码

Ctrl + /,Ctrl + Shift + /

对代码进行注释

"".sout // 快捷生成输出语句

03 基础语法

03.1 注释
  • 单行注释
// 只能写一行
  • 多行注释
/*
	内容1
	内容2
*/
  • 文档注释
// 文档注释可以提取到一个说明文档中
/**
	内容
	内容
*/

快捷键进行注释

功能效果

Ctrl + /

单行注释(对当前行进行注释)

Ctrl + Shift + /

对选中的代码进行多行注释

03.2 字面量
package com.itheima.literal;

public class LiteralDemo {
    public static void main(String[] args) {
//        目标:掌握常见数据在程序中的写法
//        1.整数
        System.out.println(666);

//        2.小数
        System.out.println(99.5);

//        3.字符:必须用单引号围起来,有且只有一个字符
        System.out.println('a');
        System.out.println('中');
        System.out.println(' ');
//        特殊字符: \n 表示换行  \t 表示一个Tab
        System.out.println('\n');
        System.out.println('国');
        System.out.println('\t');

//        4.字符串,必须用双引号,里面的内容可以随意
        System.out.println("HWS Howe");

//        5.布尔值:只有2个值 true false
        System.out.println(true);
        System.out.println(false);
    }
}
03.3 变量

变量定义的格式:

数据类型 变量名称 = 初始值;

// 变量名称建议小写,有意义

package com.itheima.variable;

public class VariableDemo2 {
    public static void main(String[] args) {
//        1.变量要先声明再使用
        int a = 10;
        System.out.println(a);

//        2.变量声明后,不能赋其他类型的值
//        a = 1.5;

//        3.变量的有效范围从定义到"}"截止,且在同一范围内部不能定义2个同名变量
        {
            int b = 15;
            System.out.println(b);
//            int b = 100;
        }
//        System.out.println(b);
        System.out.println(a);

//        4.变量定义可以没有初始值,使用时需要使用初始值
        int b;
        b = 10;
        System.out.println(b);
    }
}

04 运算符

04.1 算数运算符

符号

作用

+


-


*


/


%

取模、取余

整数参与运算,结果只有整数

小数参与计算,有可能不精确

04.2 隐式转换

范围小=>范围大

byte->short->int->long->float->double

byte short char三种类型的数据在运算时,都会直接提升到int,再进行计算

04.3 强制转换

范围大=>范围小

目标数据类型 变量名 = (目标数据类型) 被强转的数据
04.4 字符串与字符操作

当"+"操作中有字符串时,运算为字符串拼接

连续"+"时,从左往右逐个执行

字符相加会转换成码表中的数值再计算

04.5 自增自减运算符
++ // 自增
-- // 自减
int a = 10;
int b = a++; // 10

int a = 10;
int b = ++a; // 11
04.6 赋值运算符 关系运算符
+= -= *= /= 底层都隐藏了一个强制类型转换

符号

说明

==

判断相等

!=

判断不相等

>

判断大于

>=

判断大于等于

<

判断小于

<=

判断小于等于

04.7 逻辑运算符

符号

作用

说明

&

逻辑与


|

逻辑或


^

逻辑异或

相同为false,不同为true

!

逻辑非

取反

04.8 短路运算符

符号

作用

说明

&&

短路与

与&相同,不过有短路作用

||

短路或

与|相同,不过有短路作用

04.9 三元运算符
关系表达式?表达式1:表达式2
// 判断关系表达式,为真运行表达式1,为假运行表达式2

两种用法:赋值给一个变量 直接打印

关系表达式不用加括号

04.10 运算符优先级

小括号优先所有

05 流程控制语句

05.1 顺序结构
05.2 分支结构
if (关系表达式) {
	语句体;
}
  1. 大括号的开头可以另起一行,但建议写在第一行末尾
  2. 在语句体中,如果只有一行代码,大括号可以省略不写
  3. 如果对一个布尔类型变量进行判断,不要写==号,直接写入变量;如果用=则为直接赋值
if (关系表达式) {
	语句体1;
} else {
	语句体2;
}
if (关系表达式) {
	语句体1;
} else if {
	语句体2;
}
...
} else {
	语句体n+1;
}
05.3 switch语句
switch (表达式) {
	case 值1:
		语句体1;
		break;
	case 值2:
		语句体2;
		break;
	...
	default:
		语句体n+1;
		break;
}
  1. 表达式:(将要匹配的值)取值为byte、short、int、char;JDK5以后可以枚举,JDK7后可以String
  2. case:后面跟的是可以和表达式相比较的值
  3. break:表示中断,结束,用来结束switch语句
  4. default:表示默认执行
  5. case后面的值只能是字面量
  6. case给出的值不允许重复
05.4 switch语句拓展知识
  1. default语句可忽略,位置不要求
  2. 如果没有写break,会发生case穿透
  3. JDK新特性
case 值1 -> {
	语句体1;
}
case 值2 -> {
	语句体2;
}
case 值3 -> {
	语句体3;
}

单语句体不用加{}

  1. switch和if第三种格式使用场景
    if的第三种格式:一般用于范围的判断
    switch:把有限个数据列举出来,任选其一
05.5 循环结构
for (初始语句;条件判断语句;条件控制语句) {
	循环体语句;
}
初始化语句;
while (条件判断语句) {
	循环体语句;
	条件控制语句;
}

区别:

  • for循环中,控制循环的变量,循环结束后无法访问
  • 知道循环次数和范围
  • while循环中,因为这个变量在结构外,所以还可以继续使用
  • 不知道次数和范围,只知道结束条件

do…while用的少,主要掌握for和while即可

06 循环高级

06.1 无限循环
for (;;) {};
while (true) {}; // 用的最多
do {} while (true);
06.2 跳转控制语句

continue 结束本次循环,开始下次循环

break 结束整个循环

06.3 练习小知识——生成随机数
import java.util.Random;

Random r = new Random();
int i = r.nextInt (100) // 0~99

范围一定是0开始,到这个数-1结束

06.4 数组的概述和静态初始化
数据类型 [] 数组名 // 用的更多
int [] array

数据类型 数组名 []
int array []
int [] array = new int [] {11,22,33};
简化为:
int [] array = {..,..,..};
06.5 数组的地址值和元素访问
  • 数组的地址值
int [] array = {1,2,3};
System.out.println(array); // [I@776ec8df

[表示一个数组

I:表示数据类型

@:间隔符

776ec8df:真正的地址值

  • 元素访问
数组名[索引]
  • 数组写入
数组名[索引] = 具体数据/变量
06.6 数组的遍历
// 获取数组长度
数组名.length
06.7 数组的动态初始化
数据类型[] 数组名 = new 数据类型[数组长度];

数组默认初始化值的规律

  1. 整数类型:默认初始化值0
  2. 小数类型:默认初始化值0.0
  3. 字符类型:默认初始化值’/u0000’ 空格
  4. 布尔类型:默认初始化值 false
  5. 引用数据类型:默认初始化值 null
06.8 数组常见问题

当访问数组中不存在的索引,就会引发索引越界异常

06.9 数组的内存图
  • 栈内存存放函数与变量
  • 堆内存中存放数组

两个数组指向同一个空间,则会同时改变

07 方法

07.1 简单的方法定义和调用
public static void 方法名 () { // 方法名小驼峰
    方法体(就是打包起来的代码);
}
方法名();

方法必须先定义后调用,否则程序将报错

07.2 带参数的方法定义和调用
public static void 方法名 (int num1, int num2, ...) {
    方法体;
}

调用时,数据类型必须一致

  • 形参:全称形式参数,是指方法定义中的参数
  • 实参:全称实际参数,方法调用中的参数
  1. 我要干什么==>方法体
  2. 干这件事需要什么才能完成==>形参
07.3 带返回值方法定义和调用
public static 返回值类型 方法名(参数) {
    方法体;
    return 返回值;
}
  1. 直接调用
方法名(实参);
  1. 赋值调用
整数类型 变量名 = 方法名(实参);
  1. 输出调用
System.out.println(方法名(实参));
07.4 方法小结
  • 方法不调用就不执行
  • 方法之间是平级关系,不能互相嵌套定义
  • 编写顺序和执行顺序无关
  • 返回值为void,表示没有返回值;可忽略return;如果一定要写,后面不能加数据
  • return下面执行不到
07.5 方法的重载
  • 同个类中,定义了同名的方法,这些方法具有同种功能
  • 每个方法具有不同的数据类型或个数即可

和return的数据类型无关

07.6 方法的基本内存原理
  • 栈 方法运行时使用的内存,方法进栈运行,运行完毕就出栈
  • 堆 new出来的,都在堆内存中开辟了一个部分

08 面向对象

08.1 类和对象
  • 类(设计图):对象共同特征的描述
  • 对象:真实存在的具体东西

在Java中,必须先设计类,才能获得对象

定义类

public class 类名 {
    1.成员变量(代表属性,一般是名词)
    2.成员方法(代表行为,一般是动词)
	3.构造器
	4.代码块
	5.内容类
}
public class Phone {
    // 属性(成员变量)
    String brand;
    double price;
    
    // 行为(方法)
    public void call() {
        
    }
    public void playGame() {
        
    }
}

得到类的对象

类名 对象名 = new 类名();
Phone p = new Phone();

如何使用对象

  • 访问属性:对象名.成员变量
  • 访问行为:对象名.方法名(…)

定义类的补充注意事项

  • 用来描述一类事物的类,专业叫做:Javabean类
  • 在Javabean类中,是不写main方法的
  • 在以前,编写main方法的类,叫做测试类
  • 我们可以在测试类中创建Javabean类的对象并赋值调用

  • 类名建议大驼峰
  • 建议一个文件定义一个class类
  • 成员变量完整定义
  • 修饰符 数据类型 变量名称 = 初始化值
  • 一般不需要定义初始化值,存在默认值

数据类型

明细

默认值

byte、short、int、long

0

基本类型

float、double

0.0

boolean

false

引用类型

类、接口、数组、String

null

08.2 封装

面向对象三大特征:封装 继承 多态

对象代表什么,就得封装对应的数据,并提供数据对应的行为

  1. private关键字是一个权限修饰符
  2. 可以修饰成员(成员变量和成员方法)
  3. 被private修饰的成员只能在本类中才能访问
  4. 针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
  5. 提供"setXxx(参数)"用于赋值,用public修饰
  6. 提供"getXxx(参数)"用于获取值,用public修饰
08.3 就近原则和this关键字
  1. 就近原则
  2. this的作用:区分成员变量和局部变量
08.4 构造方法

在编写代码时一般有参和无参都要写

  • 任何类默认无参
  • 如果定义了有参,那么无参就没有了
  • 所以需要同时加上
08.5 标准的JavaBean类
  1. 类名需要见名知意
  2. 成员变量使用private修饰
  3. 提供至少两个构造方法
  • 无参构造方法
  • 带全部参数的构造方法
  1. 成员方法
  • 提供每一个成员变量对应的setXxx()/getXxx()
  • 如果还有其他行为,也需要写上
08.6 对象内存图(待复习)
08.7 this的内存原理

this的本质:所在方法调用者的地址值

08.8 练习备注
// 对于int数据求带小数的均值
int sum;
int num;
double avg = sum * 1.0 / num;

09 字符串

09.1 API

Ctrl+Alt+V 自动生成变量

在帮助文档中寻找API的功能与类型

09.2 String构造方法

构造方法

说明

public String()

创建空白字符串,不含任何内容

public String(String original)

根据传入的字符串,创建字符串对象

public String(char[] chs)

根据字符数组,创建字符串对象

public String(bytr[] chs)

根据字节数组,创建字符串对象

09.3 练习

字符进行比较时用’ ',不是" "

String substring(int beginIndex, int endIndex) // 截取
/* 包头不包尾,包左不包右*/
String substring(int beginIndex) // 从该数起截取到末尾
String replace(target,replacement) // 替换
09.4 StringBuilder

StringBuilder可以看成一个容器,创建之后里面的内容是可变的

方法名

说明

public StringBuilder()

创建一个空白可变字符串对象,不含任何内容

public StringBuilder(String str)

根据字符串的内容,创建可变字符串对象

public StringBuilder append(任意类型)

添加数据,并返回对象本身

public StringBuilder reverse()

反转容器中的内容

public StringBuilder length()

返回符号长度

public StringBuilder toString()

将StringBuilder转换为String

连续的api可以写在同一行中

09.5 Stringjoiner

也可以看作一个容器,内容可变

用以拼接字符串

方法名

说明

public StringJoiner(间隔符号)

创建一个对象,指定拼接时的符号

public StringJoiner(间隔符号,开始符号,结束符号)

增加了指定开始与结束

public StringJoiner add(添加的内容)

添加数据,返回对象本身

public int length()

返回长度(字符出现的个数)

public String toString()

返回一个字符串

10 集合

  • 长度可变
  • 可以存放引用数据类型
  • 基本数据类型需要变成包装类

方法名

说明

boolean add(E e)

添加元素,返回值表示是否添加成功

boolean remove(E e)

删除指定元素,返回值表示是否删除成功

E remove(int index)

删除指定索引的元素,返回被删除的元素

E set(int index,E e)

修改指定索引下的元素,返回原来的元素

E get(int index)

获取指定索引的元素

int size()

集合的长度,也就是集合中元素的个数

11 static

11.1 静态变量

static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量

  • 被修饰的变量叫静态变量
  • 类名调用(推荐)
  • 对象名调用
  • 被修饰的方法叫静态方法

一般通过该事物是否需要共享来判断是否使用静态

不属于对象,属于类

随着类的加载而加载,优先于对象存在

12 面向对象进阶

Javabean类 用来描述一类事物的类。
测试类 用来检查其他类是否书写正确,带有main方法的类,是程序的入口
工具类 不是用来描述一类事物的,而是帮我们做一些事情的类
12.1 工具类
  • 类名见名知意
  • 私有化构造方法
  • 方法定义为静态
12.2 继承

类与类之间的继承关系

  • Java只支持单继承,不支持多继承,但支持多层继承
  • 每一个类都直接或间接继承于Object

绘制时从下向上,写代码时从上向下

  • 子类只能访问父类中非私有的成员

类型

非私有

私有

构造方法

不能

不能

成员变量



成员方法

虚方法表 能

否则 不能



name:从局部位置开始往上找

this.name:从本类成员位置开始往上找

super.name:从父类成员位置开始往上找

当父类的方法不能满足子类现在的需求时,需要进行方法重写

@override
  1. 重写方法的名称、形参列表必须与父类中一致
  2. 子类重写父类,访问权限子类必须大于父类
  3. 子类重写父类,返回值类型必须小于等于父类
  4. 建议:重写方法尽量与父类保持一致
  5. 只有被添加到虚方法表中的方法才能被重写

重写时直接输入函数名回车即可,IDEA自动补全

12.3 多态
12.3.1 什么是多态

同类型的对象,表现不同的形态

表现形式:

父类类型 对象名称 = 子类对象;

多态的前提:

  • 有继承关系
  • 有父类引用指向子类对象 Fu f = new Zi();
  • 有方法重写

**多态的好处:**使用父类作为参数,可以接收所有子类对象

对象

public class Person {
    public String name;
    public int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void show() {
        System.out.println(name+" "+age);
    }
}
public class Student extends Person{
    @Override
    public void show() {
        System.out.println("学生信息:"+getName()+" "+getAge());
    }
}

Teacher与Administrator构建方法同Student

测试

public class Test {
    public static void main(String[] args) {
        Person s = new Student();
        s.setName("student");
        s.setAge(15);
        register(s);

        Person t = new Teacher();
        t.setName("teacher");
        t.setAge(40);
        register(t);

        Person a = new Administrator();
        a.setName("administrator");
        a.setAge(30);
        register(a);
    }

    public static void register(Person p) {
        p.show();
    }
}
12.3.2 多态中调用成员的特点
  • 调用成员变量:编译看左边,运行看左边
  • 编译看左边:javac编译代码时,会看左边的父类有没有这个变量,如果没有,则编译失败
  • 运行看左边:java运行代码时,实际获取的是左边父类中的成员变量
  • 调用成员方法:编译看左边,运行看右边
  • 编译看左边:javac编译代码时,会看左边的父类有没有这个方法,如果没有,则编译失败
  • 运行看右边:java运行代码时,实际获取的是右边子类中的成员方法
12.3.3 多态的优劣

多态的优势:

  • 右边对象可以解耦合,便于扩展和维护
  • 定义方法时,使用父类型作为参数,可以接收所有子类对象

多态的劣势:

如果子类中有父类没有的方法,则无法调用

劣势的解决方案:

将多态的子类变回子类

public class Test {
    public static void main(String[] args) {
        Animal d = new Dog();
        d.eat();
        // 简单版本
        // Dog dog = (Dog) d; // 将Animal d转换为Dog d
        // dog.lookHome();
        // 严谨版本
        // 如果多态的子类d满足Dog子类,则创建Dog dog
        if (d instanceof Dog dog) {
            dog.lookHome();
        } else if (d instanceof Cat cat) {
            cat.catchMouse();
        } else {
            System.out.println("没有这个类型,无法转换");
        }
    }
}

class Animal {
    public void eat() {
        System.out.println("吃饭");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("吃骨头");
    }
    public void lookHome() {
        System.out.println("看家");
    }
}

class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("吃小鱼干");
    }
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}
12.3.4 多态综合练习

对象

Animal 父

public class Animal {
    public int age;
    public String color;

    public Animal() {
    }

    public Animal(int age, String color) {
        this.age = age;
        this.color = color;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void eat(String something) {
        System.out.println("吃东西");
    }
}

Dog 子

public class Dog extends Animal{
    @Override
    public void eat(String something) {
        System.out.println("两只前腿死死的抱住"+something+"猛吃");
    }
}

Person 父

public class Person {
    public String name;
    public int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void keepPet(Animal a, String something) {
        if (a instanceof Dog dog) {
            System.out.println("年龄为" + age + "岁的" + name + "养了一只" + dog.color + "颜色的" + dog.age + "岁的狗");
            System.out.print(dog.getAge() + "岁的" + dog.getColor() + "颜色的狗");
            dog.eat(something);
        } else if (a instanceof Cat cat) {
            System.out.println("年龄为"+age+"岁的"+name+"养了一只"+cat.color+"颜色的"+cat.age+"岁的猫");
            System.out.print(cat.getAge()+"岁的"+cat.getColor()+"颜色的猫");
            cat.eat(something);
        } else {
            System.out.println("无法转换");
        }
    }
}

测试

public class Test {
    public static void main(String[] args) {
        // Animal d = new Dog();
        // d.setAge(2);
        // d.setColor("黑");
        // System.out.print(d.getAge()+"岁的"+d.getColor()+"颜色的狗");
        // d.eat("骨头");
        // Animal c = new Cat();
        // c.setAge(3);
        // c.setColor("灰");
        // System.out.print(c.getAge()+"岁的"+c.getColor()+"颜色的猫");
        // c.eat("鱼");
        Animal dog = new Dog();
        dog.setAge(2);
        dog.setColor("黑");
        Person p1 = new Person("老王",30);
        p1.keepPet(dog,"骨头");
        Animal cat = new Cat();
        cat.setAge(3);
        cat.setColor("灰");
        Person p2 = new Person("老李",25);
        p2.keepPet(cat,"鱼");
    }
}
12.4 小知识点
12.4.1 包

包就是文件夹。用来管理不同功能的java类,方便后期维护。

  • 包的命名规则:公司域名反写+包的作用,需要全部小写。com.itheima.domain
  • com.itheima.domain.Student称为全类名,用于导包
import com.itheima.domain.Student;
public class Test {
	public static void main(String[] args) {
		Student s = new Student();
	}
}
  • 使用同一个类,不需导包
  • 使用java.lang包中的类时,不需要导包
  • 其他情况都需要导包
  • 如果使用两个包中的同名类,需要用全类名
12.4.2 final

使用final修饰后的方法、类、变量不能被改变;不能继承

一般用于修饰规则,只有变量较为常用

常量:

  • 单个单词:全部大写
  • 多个单词:全部大写,单词之间用下划线隔开

细节:

final修饰基本数据类型,数据值不可变

final修饰引用数据类型,地址值不可变,对象内部可变

12.4.3 权限修饰符

一般只用private和public

  • 成员变量私有
  • 方法公开

特例:如果方法中的代码时抽取其他方法中共性代码,这个方法一般也私有

12.4.4 代码块

在代码运行过程中用来单独运算语句

因为会自动提前的特征

静态代码块:数据的初始化

12.5 抽象类

如果一个类中存在抽象方法,那么该类就必须声明为抽象类

  • 抽象方法
public abstract 返回值类型 方法名(参数列表);
  • 抽象类
public abstract class 类名{}

注意事项:

  • 抽象类不能实例化
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 可以有构造方法
  • 抽象类的子类
  • 要么重写抽象类中所有抽象方法
  • 要么是抽象类

对象

Animal

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public abstract void action();
}

Frog

public class Frog extends Animal{
    @Override
    public void action() {
        System.out.println("吃虫子,喝水");
    }
}

测试

public class Test {
    public static void main(String[] args) {
        Animal f = new Frog();
        f.setName("a");
        f.setAge(1);
        System.out.println(f.getName()+" "+f.getAge());
        f.action();
        Animal d = new Dog();
        d.setName("b");
        d.setAge(1);
        System.out.println(d.getName()+" "+d.getAge());
        d.action();
        Animal s = new Sheep();
        s.setName("c");
        s.setAge(1);
        System.out.println(s.getName()+" "+s.getAge());
        s.action();
    }
}
12.6 接口
12.6.1 接口

行为的抽象

  • 接口用关键字interface来定义public interface 接口名 {}
  • 接口不能实例化
  • 接口与类之间是实现关系,通过implements关键字表示public class 类名 implements 接口名 {}
  • 接口的子类(实现类)
  • 要么重写接口中所有的抽象方法
  • 要么也是抽象类

一个类可以有多个接口

public class 类名 implements 接口名1,接口名2 {}

实现类可以在继承同时实现多个接口

public class 类名 extends 父类 implements 接口名1,接口名2 {}

接口

Swim

public interface Swim {
    public abstract void swim();
}

对象

Animal 父

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public abstract void eat();
}

Frog 子

public class Frog extends Animal implements Swim{
    public Frog() {
    }

    public Frog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("虫子");
    }

    @Override
    public void swim() {
        System.out.println("蛙泳");
    }
}

测试

public class Test {
    public static void main(String[] args) {
        Frog f = new Frog("frog",1);
        System.out.println(f.getName()+" "+f.getAge());
        f.eat();
        f.swim();
    }
}
12.6.2 成员特点和接口之间关系

接口中成员的特点:

  • 成员变量
  • 只能是常量
  • 默认修饰符:public static final
  • 构造方法
  • 没有
  • 成员方法
  • 只能是抽象方法
  • 默认修饰符:public abstract

接口和类之间的关系:

  • 类和类的关系
  • 继承关系,只能单继承,不能多继承,但是可以多层继承
  • 类和接口的关系
  • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系
  • 继承关系,可以单继承,也可以多继承
12.6.3 接口综合案例

接口

public interface EnglishStudy {
    void englishStudy();
}

对象

体育从业者

public class Sport {
    private String name;
    private int age;

    public Sport() {
    }

    public Sport(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

乒乓球从业者

public abstract class Table extends Sport{
    public Table() {
    }

    public Table(String name, int age) {
        super(name, age);
    }

    public abstract void tableTennis();
}

乒乓球运动员

public class TableSport extends Table implements EnglishStudy{
    public TableSport(String name, int age) {
        super(name, age);
    }

    @Override
    public void tableTennis() {
        System.out.println("学打乒乓");
    }

    @Override
    public void englishStudy() {
        System.out.println("说英语");
    }
}

乒乓球教练

public class TableTrainer extends Table implements EnglishStudy{
    public TableTrainer(String name, int age) {
        super(name, age);
    }

    @Override
    public void tableTennis() {
        System.out.println("教打乒乓");
    }

    @Override
    public void englishStudy() {
        System.out.println("说英语");
    }
}

篮球方面同理

测试类

public class Test {
    public static void main(String[] args) {
        Sport ts = new TableSport("乒乓球运动员",20);
        Sport tt = new TableTrainer("乒乓球教练",30);
        Sport bs = new BasketSport("篮球运动员",20);
        Sport bt = new BasketTrainer("篮球教练",30);
        show(ts);
        show(bs);
        show(tt);
        show(bt);
    }
    public static void show(Sport s) {
        System.out.print(s.getName()+" "+s.getAge()+" ");
        if (s instanceof TableSport ts) {
            ts.tableTennis();
            ts.englishStudy();
        } else if (s instanceof TableTrainer tt) {
            tt.tableTennis();
            tt.englishStudy();
        } else if (s instanceof Basket) {
            ((Basket) s).basketball();
        }
    }
}

按教案,根据运动员、教练进行分类效果更好,可以试试

12.6.4 多学三招

JDK8以后接口中新增的方法

  • 允许在接口定义默认方法,用default修饰
  • 作用:解决接口升级的问题
  • 默认方法的定义格式:
  • 格式:public default 返回值类型 方法名(参数列表) { }
  • 范例:public default void show() { }
  • 注意事项:
  • 默认方法不是抽象方法,不强制被重写。如果被重写,重写时去掉default关键字

JDK8以后接口中新增的方法

  • 允许在接口定义静态方法,用static修饰
  • 默认方法的定义格式:
  • 格式:public static 返回值类型 方法名(参数列表) { }
  • 范例:public static void show() { }
  • 注意事项:
  • 静态方法只能通过接口名调用,不能通过类名或者对象名调用
  • public可以省略,static不能省略
  • 接口
public interface Inter {
    static void show() {
        System.out.println("静态");
    }
}
  • 测试类
public class Test {
    public static void main(String[] args) {
        Inter.show();
    }
}

JDK9新增的方法

将接口中的方法提取共同的代码

  • private 返回值类型 方法名(参数列表) { }
  • private static 返回值类型 方法名(参数列表) { }

接口的应用

  1. 让JavaBean拥有相应的功能
  2. 当一个方法的参数是接口时,可以传递接口所有的实现类的对象,称为接口多态

适配器设计模式

当抽象方法过多时简化代码

编写中间类XXXAdapter,实现对应的接口

对接口中的抽象方法进行空实现

让真正的实现类继承中间类,并重写需要用的方法

为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

12.7 内部类
12.7.1 初识内部类

内部类的访问特点

  • 内部类可以直接访问外部类成员,包括私有
  • 外部类要访问内部类的成员,必须创建对象

外部类+内部类

public class Car {
    private String carName;
    private int carAge;
    private String carColor;

    public void show() {
        System.out.println(carName);
        Engine e = new Engine();
        System.out.println(e.engineName);
    }

    class Engine {
        String engineName;
        int engineAge;
        public void show() {
            System.out.println(engineName);
            System.out.println(carName);
        }
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        Car c = new Car();
    }
}
12.7.2 成员内部类 静态内部类 局部内部类

工作中不常用,源码中比较多

12.7.3 匿名内部类

匿名内部类本质上是隐藏了名字的内部类

  • 格式
new 类名或者接口名() {
	重写方法;
}; // ;必须加
  • 举例
new Inter() {
	public void show() {
	
	}
};

使用场景:如果实现类只使用一次,就可以用匿名内部类简化代码

接口

public interface Swim {
    public abstract void swim();
}

对象

public abstract class Animal {
    public abstract void eat();
}

测试类

public class Test {
    public static void main(String[] args) {
        Swim s = new Swim() {
            @Override
            public void swim() {
                System.out.println("重写swim方法");
            }
        };
        new Animal() {
            @Override
            public void eat() {
                System.out.println("重写eat方法");
            }
        };

        // 调用方法一
        s.swim();
        // 调用方法二
        new Swim() {
            @Override
            public void swim() {
                System.out.println("重写swim方法");
            }
        }.swim();
    }
}

13 阶段项目

13.1 项目分析

主界面分析

JFrame // 最外面的窗体
JMenuBar // 最上层的菜单
JLabel // 管理文字和图片的容器

界面搭建

src目录下创建App类作为启动器

public class App {
    public static void main(String[] args) {
        // 程序入口
        new LoginJFrame();
    }
}

ui程序包用于创建界面

登录

import javax.swing.*;

public class LoginJFrame extends JFrame {
    // 登录界面
    public LoginJFrame() {
        this.setSize(488,430);
        this.setVisible(true);
    }
}

注册

import javax.swing.*;

public class RegisterJFrame extends JFrame {
    // 注册界面
    public RegisterJFrame() {
        this.setSize(488,500);
        this.setVisible(true);
    }
}

游戏

import javax.swing.*;

public class GameJFrame extends JFrame {
    // 游戏主界面
    public GameJFrame() {
        this.setSize(603,680);
        this.setVisible(true);
    }
}

Tips:Ctrl + P可以显示参数提示

13.2 添加组件小结
|--JFrame(主窗体)
|--|--JMenuBar(菜单)
|--|--JLabel(图片或文字)

14 常用API

14.1 Math
14.2 System
14.3 Runtime
14.4 Object

Object

方法名

说明

public String toString()

返回对象的字符串表示形式

public boolean equals(Object obj)

比较两个对象是否相等

protected Object clone()

对象克隆

Objects

equals(对象1,对象2):先做非空判断,再比较两个对象
isNull(对象):判断对象是否为空
nonNull(对象):判断对象是否不是空
14.5 BigInteger和BigDecimal

方法名

说明

public BigInteger(int num, Random rnd)

获取随机大整数,范围:[0 ~ 2的num次方 - 1]

public BigInteger(String val)

获取指定的大整数

Random r = new Random();
BigInteger bi = new BigInteger(4,r);
System.out.println(bi);
BigInteger bi = new BigInteger("10000");
System.out.println(bi);

常用操作:

  • 加:add
  • 减:subtract
  • 乘:multiply
  • 除:divide、divideAndRemainder
  • 比较:equals、max、min
  • 次幂:pow
  • 转成整数:intValue、longValue

数字不大,可以使用BigInteger.valueOf

数字大,可以使用BigInteger

14.6 正则表达式

字符类(只匹配一个字符)

说明

[abc]

只能是a,b,c

[^abc]

除了a,b,c之外的任何字符

[a-zA-Z]

a到z,A到Z

[a-d[m-p]]

a到d,或m到p

预定义字符(只匹配一个字符)

说明

.

任何字符

\d

一个数字

\D

非数字

\s

一个空白字符

\S

非空白字符

\w

英文、数字、下划线

\W

一个非单词字符

\表示转义字符

\\表示转义了\字符,让它成为普通的字符

public static void main(String[] args) {
    String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
    /*
    ?理解为前面的数据Java
    =表示在Java后面要跟随的数据
    但是在获取时,只获取前半部分
    */
    String regex1 = "Java(?=8|11|17)";
    String regex2 = "Java(?:8|11|17)";
    String regex3 = "Java(?!8|11|17)";
    Pattern p = Pattern.compile(regex3);
    Matcher m = p.matcher(str);
    while (m.find()) {
        System.out.println(m.group());
    }
}