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 (关系表达式) {
语句体;
}
- 大括号的开头可以另起一行,但建议写在第一行末尾
- 在语句体中,如果只有一行代码,大括号可以省略不写
- 如果对一个布尔类型变量进行判断,不要写==号,直接写入变量;如果用=则为直接赋值
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;
}
- 表达式:(将要匹配的值)取值为byte、short、int、char;JDK5以后可以枚举,JDK7后可以String
- case:后面跟的是可以和表达式相比较的值
- break:表示中断,结束,用来结束switch语句
- default:表示默认执行
- case后面的值只能是字面量
- case给出的值不允许重复
05.4 switch语句拓展知识
- default语句可忽略,位置不要求
- 如果没有写break,会发生case穿透
- JDK新特性
case 值1 -> {
语句体1;
}
case 值2 -> {
语句体2;
}
case 值3 -> {
语句体3;
}
单语句体不用加{}
- 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 数据类型[数组长度];
数组默认初始化值的规律
- 整数类型:默认初始化值0
- 小数类型:默认初始化值0.0
- 字符类型:默认初始化值’/u0000’ 空格
- 布尔类型:默认初始化值 false
- 引用数据类型:默认初始化值 null
06.8 数组常见问题
当访问数组中不存在的索引,就会引发索引越界异常
06.9 数组的内存图
- 栈内存存放函数与变量
- 堆内存中存放数组
两个数组指向同一个空间,则会同时改变
07 方法
07.1 简单的方法定义和调用
public static void 方法名 () { // 方法名小驼峰
方法体(就是打包起来的代码);
}
方法名();
方法必须先定义后调用,否则程序将报错
07.2 带参数的方法定义和调用
public static void 方法名 (int num1, int num2, ...) {
方法体;
}
调用时,数据类型必须一致
- 形参:全称形式参数,是指方法定义中的参数
- 实参:全称实际参数,方法调用中的参数
- 我要干什么==>方法体
- 干这件事需要什么才能完成==>形参
07.3 带返回值方法定义和调用
public static 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
- 直接调用
方法名(实参);
- 赋值调用
整数类型 变量名 = 方法名(实参);
- 输出调用
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 封装
面向对象三大特征:封装 继承 多态
对象代表什么,就得封装对应的数据,并提供数据对应的行为
- private关键字是一个权限修饰符
- 可以修饰成员(成员变量和成员方法)
- 被private修饰的成员只能在本类中才能访问
- 针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
- 提供"setXxx(参数)"用于赋值,用public修饰
- 提供"getXxx(参数)"用于获取值,用public修饰
08.3 就近原则和this关键字
- 就近原则
- this的作用:区分成员变量和局部变量
08.4 构造方法
在编写代码时一般有参和无参都要写
- 任何类默认无参
- 如果定义了有参,那么无参就没有了
- 所以需要同时加上
08.5 标准的JavaBean类
- 类名需要见名知意
- 成员变量使用private修饰
- 提供至少两个构造方法
- 无参构造方法
- 带全部参数的构造方法
- 成员方法
- 提供每一个成员变量对应的
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
- 重写方法的名称、形参列表必须与父类中一致
- 子类重写父类,访问权限子类必须大于父类
- 子类重写父类,返回值类型必须小于等于父类
- 建议:重写方法尽量与父类保持一致
- 只有被添加到虚方法表中的方法才能被重写
重写时直接输入函数名回车即可,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 返回值类型 方法名(参数列表) { }
接口的应用
- 让JavaBean拥有相应的功能
- 当一个方法的参数是接口时,可以传递接口所有的实现类的对象,称为接口多态
适配器设计模式
当抽象方法过多时简化代码
编写中间类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());
}
}