Java学习日志
2026.4.28
图书馆借书系统
public class Book {
// 属性
private String title;
private String author;
private boolean isBorrowed; // 是否被借走
// 构造方法
public Book(String title, String author) {
this.title = title;
this.author = author;
this.isBorrowed = false;
}
//getter setter
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public void setTitle(String title) {
this.title = title;
}
public boolean isBorrowed() {
return isBorrowed;
}
public void setBorrowed(boolean borrowed) {
isBorrowed = borrowed;
}
}
public class Library {
// 属性
private static Book[] books; //静态
static {
books = new Book[10];
for (int i = 0; i < books.length; i++) {
books[i] = new Book("图书" + (i + 1), "作者" + (i + 1));
}
}
// 行为
// 陈列
public void displayBooks() {
System.out.println("编号\t图书名称\t作者\t状态\t");
for (int i = 0; i < books.length; i++) {
Book book = books[i];
System.out.println((i + 1) + "\t" + book.getTitle() + "\t" + book.getAuthor() +
"\t" + (book.isBorrowed() ? "已借" : "未借"));
}
}
Scanner scanner = new Scanner(System.in);
public void borrowBook() {
System.out.print("请输入你的图书名称:");
String name = scanner.next();
for (int i = 0; i < books.length ; i++) {
if (name.equals(books[i].getTitle()) && !books[i].isBorrowed()){ // 这里使用&&是的代码简洁一点,少写一个for循环
System.out.println("成功借阅图书:" + books[i].getTitle());
books[i].setBorrowed(true); // 注意借书了之后要设置为true
break;
} else {
System.out.println("该书已借出"); // 当被借出之后,如果用户要借就需提醒改书以被借出
break;
}
}
}
public void returnBook(){
System.out.print("请输入你的图书名称:");
String name = scanner.next(); // 这是让用户输入字符串的
for (int i = 0; i < books.length; i++) {
if (name.equals(books[i].getTitle()) && books[i].isBorrowed()) { // 注意,字符串之间尽量不要使用 == 来比较 要使用equals来比较,因为string为引用型字符串,数字可以用==,因为他们是基本数据类型
System.out.println("成功归还:" + books[i].getTitle());
books[i].setBorrowed(false);
break;
} else {
System.out.println("该书已归还");
break;
}
}
}
}
public class Main {
public static void main(String[] args) {
// 创建图书馆对
Library library = new Library();
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("系统的功能如下:");
System.out.println("1.陈列所有图书");
System.out.println("2.借阅图书");
System.out.println("3.归还图书");
System.out.println("4.退出系统");
System.out.println("请输入你的需求:");
int num = sc.nextInt();
switch (num) {
case 1:
library.displayBooks();
break;
case 2:
library.borrowBook();
break;
case 3:
library.returnBook();
break;
case 4:
System.exit(0); // 这是一个退出程序的语句
break;
default:
System.out.println("输入错误,请重新输入");
}
}
}
}
打怪兽
public class Hero {
private int maxHp = 500; // 血量
// 构造方法
public Hero() {
}
public Hero(int maxHp) {
this.maxHp = maxHp;
}
// 行为
public void attack(Monster monster,int hurtHp) {
// 怪兽掉血
int currentHp = monster.getMaxHp();
int remainHp = currentHp - hurtHp;
monster.setMaxHp(remainHp); // 这里是我的错误,没有实际的改变怪兽的血量
}
// getter setter
public int getMaxHp() {
return maxHp;
}
public void setMaxHp(int maxHp) {
// 这里需要判断,如果血量为负数,那就直接让血量为零
if (maxHp < 0) {
this.maxHp = 0;
} else {
this.maxHp = maxHp;
}
}
}
public class Monster {
private int maxHp = 300;
public Monster(int maxHp) {
this.maxHp = maxHp;
}
public int getMaxHp() {
return maxHp;
}
public void setMaxHp(int maxHp) {
if (maxHp < 0) {
this.maxHp = 0;
} else {
this.maxHp = maxHp;
}
}
public void attack(Hero hero, int hurtHp) {
// 英雄掉血
int currentHP = hero.getMaxHp();
int remainHp = currentHP - hurtHp;
hero.setMaxHp(remainHp); // 这里也是一样,要设置更新血量
}
}
public class FightGame {
public static void main(String[] args) {
Random random = new Random();
System.out.println("这是一场回合制战斗!!!");
Monster monster = new Monster(300);
Hero hero = new Hero();
while (true) {
System.out.println("英雄攻击怪兽");
System.out.println("怪兽攻击前的血量:" + monster.getMaxHp());
hero.attack(monster, random.nextInt(161));
System.out.println("怪兽被攻击后的血量:" + monster.getMaxHp());
if (monster.getMaxHp() <= 0) {
System.out.println("英雄获胜,怪兽消灭");
break;
}
System.out.println("怪兽攻击英雄");
System.out.println("英雄攻击前的血量:" + monster.getMaxHp());
monster.attack(hero, random.nextInt(101));
System.out.println("英雄攻击前的血量:" + monster.getMaxHp());
if (hero.getMaxHp() <= 0) {
System.out.println("怪兽获胜,英雄消灭");
break;
}
}
}
}
2026.4.29
什么是对象?
一个生活中的比喻:现实生活,要把零零散散的苹果给收集起来就需要用到背包
在面向对象中,把零散的数据组合成一个整体,而且如果要传递给方法的话,也是把这个整体给传入进去就可以了,而这个整体就是对象
所以,什么是对象?
把相关的数据和方法组织为一个整体来看待
面向对象:
利用对象进行软件开发,更像是一个思想
类和对象
定义一个类去描述一类事物(注意:类中所有的属性只定义不赋值)
创建对象,单独记录个体的所有信息
面向对象思想的小细节
描述一类事物的类叫javabean类
带有main方法的类叫测试类
javabean类可以写属性和行为
面向对象中的数据安全问题
私有化成员变量
get/set 方法
this关键词
1. 默认就近原则:
1. 在方法中直接使用变量查找顺序
2. 先找局部变量,再找成员变量
2. 直接使用成员变量加this前缀
3. this的作用是:
1. 可以区别局部变量和和成员变量
2. sout(age) // 触发就近原则
3. sout(this.age) // 使用成员变量

构造方法

构造方法注意细节
1. 如果没有定义构造方法,系统将给出一个默认的无参构造方法
2. 所以,有一个人习惯:无论使不使用,都写无参的构造方法
小节
如何写出一个正确的JavaBean类
如何根据JavaBean类去创建一个对象
public class 类名{
私有化成员变量
无参构造
带全部参数的构造
get/set方法
}
类名 对象名 = new 类名(); // 来管理零零散散的数据
然后get/set方法对这里的每一个属性进行赋值
package com.itheima.ooptest10;
import java.util.Set;
public class Student {
private String name;
private int age;
// 创建无参构造
public Student() {
System.out.println("这是一个无参构造方法");
}
// 创建有参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("这是有参构造");
}
// set/get
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 eat() {
System.out.println(name + "在干饭");
}
public void sleep() {
System.out.println(name + "学生在睡觉");
}
public void study() {
System.out.println(name + "学生在学习");
}
}
package com.itheima.ooptest10;
public class Test {
static void main() {
Student s = new Student();
s.setName("李四");
s.setAge(20);
System.out.println(s.getName());
System.out.println(s.getAge());
s.eat();
s.sleep();
s.study();
Student ss = new Student("张三", 18);
System.out.println(ss.getName());
System.out.println(ss.getAge());
ss.eat();
ss.sleep();
ss.study();
}
}
2026.4.30
java中对象的内存分配

创建对象的七步

方法出栈后,方法里面的变量全部消失
如果没有任何地方使用堆里面的对象,那么此对象也会从堆里消失
方法区里面的字节码一般不会消失,除非关闭虚拟机
对象在方法中的传递
把一个对象传递给方法,实际传递的对象的内存地址
当多个变量指向同一个变量的时候:只要有一个变量修改了对象中的属性,其他变量再次访问就是修改之后的结果了
this关键字的本质
内存:所在方法调用者的地址值
2026.5.1
static关键词(修饰成员变量)
背景:
如果创建了一个班的学生对象,有一个老师要转走,那么要把这个老师的名字从每个学生对象中去修改,这样很麻烦,所以就引入了一个static关键词,去修饰每个对象都有的一个变量
static :
表示静态,是java的修饰符,用来修饰(成员变量/成员方法)
特点:叫做静态变量,被该类的所有对象共享(相当于一个班共享一个老师)
调用方式:
方法一:类名 调用 (推荐)
方法二:对象名调用
示例代码:
public class Student {
// 创建学生类
String name;
int age;
// 一个学生共享一个老师
static String teachName;
// 创建方法
public void show() {
System.out.println(name + ", " + age + ", " + teachName);
}
}
public class Test {
static void main() {
Student.teachName = "小文老师";
// 创建第一个对象
Student s1 = new Student();
s1.name = "小诗诗";
s1.age = 18;
// 创建第二个对象
Student s2 = new Student();
s2.name = "小丹丹";
s2.age = 20;
Student.teachName = "阿伟老师";
// 调用方法
s1.show();
s2.show();
}
}
static关键词的内存理解
当定义了一个static修饰的变量的时候,会在堆内存中开辟一个空间来储存变量,而当创建对象的时候也会在堆内存中开辟一个空间,所以对象与statc所创建的对象是无关的
特点:
该变量叫静态变量,被该类所有对象共享, 这个共享很重要(这个意味着,所有对象都可以使用,当一个对象修改了这个变量,那么后面对象访问静态变量的时候访问的就是修改之后的变量
不属于对象,属于类
随着类的加载而加载,优先于对象而存在
调用方式:
方式一:类名调用(推荐)
方式二:对象名调用(不推荐,因为静态变量不属于对象,用对象名调用不是很合适)
static关键字(修饰成员方法)
代码示例:
public class ArrayUtil {
// 私有化构造方法,目的,不让外界创造对象
private ArrayUtil() {
}
// 定义方法(静态)
/* 1. 提供一个方法printArr,用于遍历数组。
格式如下:[10,20,50,34,100](只考虑整数数组)*/
public static String printArr(int arr[]) {
/*System.out.print("[");
for (int i = 0; i < arr.length; i++) { if (i == arr.length - 1) { System.out.println(arr[i] + "]"); } else { System.out.print(arr[i] + ", "); } }*/ // 带有返回值
String result = "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
result = result + arr[i] + "]";
} else {
result = result + arr[i] + ", ";
}
}
return result;
}
// 2. 提供一个方法getAverage,用于返回平均分。(只考虑整数数组)*/
public static void getAverage(int arr[]) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
double average = (double) sum / arr.length;
System.out.println("平均分:" + average);
}
}
public class Test {
/*需求:
在实际开发中,经常会遇到一些数组使用的工具类。
请按照如下要求编写一个数组的工具类完成以下需求:
1. 提供一个方法printArr,用于遍历数组。
格式如下:[10,20,50,34,100](只考虑整数数组)
2. 提供一个方法getAverage,用于返回平均分。(只考虑整数数组)*/
static void main() {
// 创建一个数组
int[] arr = new int[]{10, 20, 50, 34, 100};
// 遍历
String res = ArrayUtil.printArr(arr);
System.out.println(res);
// 取平均值
ArrayUtil.getAverage(arr);
}
}
2026.5.2
静态的注意事项
静态方法只能访问静态变量和其他的静态方法
非静态变量可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
静态方法中没有this关键词
总结:静态只能调用静态,非静态可以调用所有,静态没有this
为什么?
因为静态方法随着类的加载而加载,==优先于对象而存在
而非静态是和对象有关的,要先有对象才有非静态的成员变量
2025.5.3
final关键字
被其修饰的变量的叫做常量
特点:
1.只能被赋值一次,一旦赋值,无法再次修改
2.常量名大写,多个单词之间用下划线隔开
细节:
基本数据类型:
1.变量里面记录的是真实的数据
2. final int a = 10; 此时变量里面记录的数据无法发生改变
引用数据类型:
1.int[] Student Teacher...
2.stu里面的记录对象内存地址,不可改变的是stu记录的内存地址
3.而对象里面的属性值,是可以发生改变
4.final Student stu = new Student();
总结:
final修饰那个变量,这个变量里面记录的内容就无法再次发生改变
代码示例:
public class Circle {
private final double PI = 3.14;
private double round;
public Circle() {}
public Circle(double round) {
this.round = round;
}
public double getPI() {
return PI;
}
public double getRound() {
return round;
}
public void setRound(double round) {
this.round = round;
}
// 行为:
public double getArea() {
return PI * round * round;
}
public double getCircle() {
return 2 * PI * round;
}
}
public class FinalTest2 {
/*定义一个Javabean类描述圆
属性:半径和圆周率
行为:计算圆的面积和周长*/
static void main() {
Circle c = new Circle();
c.setRound(6);
System.out.println("面积为:" + c.getArea());
System.out.println("周长为:" + c.getCircle());
}
}继承
什么是继承?
面向对象三大特征之一,可以使类与类之间产生父子关系
继承的作用是什么?
操作:多个子类共有的的代码抽取到父类,子类可以直接调用
好处:可以减少代码冗余,提高代码可读性
继承格式?
public class 子类 extends 父类 ( ){ }
继承子类的好处?
好处一:子类可以得到父类的属性和行为,子类可以使用
好处二:子类可以在父类的基础上新增其他功能,子类更强大
代码示例:
public class Person {
String name;
int age;
public void eat() {
System.out.println("在吃饭");
}
}
public class Student extends Person{
String grade;
public void study() {
System.out.println("在学习");
}
}
public class Teacher extends Person{
String subject;
public void teach() {
System.out.println("在教书");
}
}
public class Test {
static void main() {
// 创建对象
Student s = new Student();
s.name = "张三";
s.age = 19;
s.grade = "大一";
s.study();
s.eat();
System.out.println(s.name);
System.out.println(s.age);
System.out.println(s.grade);
Teacher t = new Teacher();
t.name = "小文";
t.age = 30;
t.subject = "计算机";
t.eat();
t.teach();
System.out.println(t.name);
System.out.println(t.age);
System.out.println(t.subject);
}
}
2026.5.4
如何设计一个复杂的继承结构
利用画图法解决
分类
抽取共性的内容不断往上抽取(从下往上画)
写代码(从上往下写)

***代码示例:
public class SmartDevice {
// 属性:品牌,价格
String brand;
int price;
}
public class Phone extends SmartDevice{
// 行为
public void call() {
System.out.println("打电话");
}
public void sendMessage() {
System.out.println("发短信");
}
}
public class Notebook extends SmartDevice{
// 行为
public void code() {
System.out.println("编程");
}
}
public class AnPhone extends Phone{
// 行为
public void nfc() {
System.out.println("NFC功能");
}
}
public class iPhone extends Phone{}
public class Test {
/*
现在有三个电子设备,请设计他们的继承结构
安卓手机:
属性:品牌,价格,
行为:打电话,发短信,nfc功能
苹果手机:
属性:品牌,价格
行为:打电话,发短信
笔记本电脑:
属性:品牌,价格
行为:编程
*/
static void main() {
AnPhone an = new AnPhone();
an.brand = "小米";
an.price = 1999;
an.sendMessage();
an.nfc();
an.call();
System.out.println(an.brand);
System.out.println(an.price);
System.out.println("------------------");
Notebook no = new Notebook();
no.brand = "MacBook";
no.price = 10000;
System.out.println(no.brand);
System.out.println(no.price);
System.out.println("---------------");
iPhone i = new iPhone();
i.brand = "iPhone17";
i.price = 10000;
System.out.println(i.brand);
System.out.println(i.price);
i.sendMessage();
i.call();
}
}2026.5.6
继承的特点
Java只能单继承,不支持多继承、但是支持多层继承
直接继承的父类叫做直接父类,间接继承的爷爷叫做间接父类
Java中所有的类都直接或者间接继承于Object类
继承中的成员特点
成员变量的特点:
继承中成员变量的书写规则:***抽取共性
继承中成员变量访问特点:***就近原则
先在局部位置找
本类成员位置找
父类成员位置找,逐级往上
如果出现了重名的成员变量怎么办?
sout( name ); // 从局部位置开始往上找
sout( this.name ); // 从本类成员位置开始往上找
sout( super.name ); // 从父类成员位置开始往上找
成员方法的特点:
继承中成员方法的特点:
书写规则:抽取子类中共性的行为
调用规则:就近原则
this调用:先访问本类,再访问父类
super调用:直接访问父类
什么是方法重写?
在继承中,子类出现了和父类中一模一样的方法声明
重写的方法就是需要加上@Override注解,校验重写语法是否正确
什么时候使用方法重写?
当父类的方法不能满足子类的要求的时候
重写方法有哪些基本要求?
子类重写的方法申明跟子类要求保持一致
private私有化方法、static静态方法、***final方法最终不能被重写
代码示例:
public class SmartDevice {
String name;
int price;
// 行为:
public double calculate() {
if (price >= 0 && price < 1000) {
return price;
} else if (price >= 1000 && price < 5000) {
return price * 0.9;
} else if (price >= 5000 && price < 10000) {
return price * 0.8;
} else if (price >= 10000) {
return price * 0.7;
} else {
return 0;
}
}
}
public class Phone extends SmartDevice{
// 方法重构
@Override
public double calculate() {
double calculate = super.calculate();
calculate *= 0.9;
return calculate;
}
}
public class iPad extends SmartDevice{}
public class MacBook extends SmartDevice{}
public class Test {
static void main() {
// 创建一个手机的对象
Phone phone = new Phone();
phone.name = "小米";
phone.price = 4999;
System.out.println(phone.calculate());
// 创建后面两个对象
MacBook macbook = new MacBook();
macbook.name = "苹果电脑";
macbook.price = 10000;
System.out.println(macbook.calculate());
iPad ipad = new iPad();
ipad.name = "平板电脑";
ipad.price = 6000;
System.out.println(ipad.calculate());
}
}
构造方法的特点
子类不能继承父类的构造方法,但是可以通过super调用
子类构造方法的第一行,有一个默认的super(),不写也有
如果想要访问父类有参构造,必须手动书写super(参数)
super()必须写在构造方法的第一行,先执行父类的构造,在执行子类的构造
代码示例:
public class Person {
String name;
int age;
// 构造方法:
public Person() {
System.out.println("父类调用了无参构造");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("父类调用了带参构造");
}
}
public class Student extends Person{
String grade;
// 构造方法
// 1.空参构造
public Student() {
System.out.println("子类调用了无参构造");
}
// 2.带全部参数的构造
// 父类中的属性:通过super(参数)的形式传递给父类的构造方法赋值
// 子类中的属性:自己赋值
public Student(String name, int age, String grade) {
super(name, age);
this.grade = grade;
System.out.println("子类调用了带参构造");
}
}
public class Teacher extends Person{
String subject;
// 构造函数
public Teacher() {
System.out.println("子类调用了空参构造");
}
public Teacher(String name, int age, String subject) {
super(name, age);
this.subject = subject;
System.out.println("子类调用了带参构造");
}
}
public class Test {
static void main() {
// 创建对象
Student stu = new Student("张三", 18, "大一");
System.out.println(stu.name + stu.age + stu.grade);
Teacher teach = new Teacher("小文", 30, "数据库");
System.out.println(teach.name + teach.age + teach.subject);
Student student = new Student();
}
}
this和super

471
带有继承结构的标准javabean类
要求:书写一个完整的继承体系,要求私有化成员变量、get/set方法
构造方法、其他的成员方法
示例代码:
public class Person {
private String name;
private int age;
// 构造方法
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// get/set
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 eat() {
System.out.println("在吃饭");
}
public void sleep() {
System.out.println("在睡觉");
}
}
public class Student extends Person{
private String grade;
// 构造
public Student() {}
public Student(String grade) {
this.grade = grade;
}
public Student(String name, int age, String grade) {
super(name, age);
this.grade = grade;
}
// get/set
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
// 行为:
public void study() {
System.out.println("在学习");
}
}
public class Teacher extends Person{
private String subject;
// 构造
public Teacher() {}
public Teacher(String name, int age) {
super(name, age);
}
public Teacher(String subject) {
this.subject = subject;
}
public Teacher(String name, int age, String subject) {
super(name, age);
this.subject = subject;
}
// get/set
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
// 行为:
public void teach() {
System.out.println("在教书");
}
}
public class UnderGraduate extends Student{
// 构造
public UnderGraduate() {}
public UnderGraduate(String grade) {
super(grade);
}
public UnderGraduate(String name, int age, String grade) {
super(name, age, grade);
}
// 重写
@Override
public void study() {
System.out.println("本科生在攻读学士学位");
}
}
public class PostGraduate extends Student{
// 构造
public PostGraduate() {}
public PostGraduate(String grade) {
super(grade);
}
public PostGraduate(String name, int age, String grade) {
super(name, age, grade);
}
// 重写
@Override
public void study() {
System.out.println("硕士研究生在攻读硕士学位");
}
@Override
public void sleep() {
System.out.println("在豪华版公寓睡觉");
}
}
public class Professional extends Teacher{
// 构造
public Professional() {}
public Professional(String name, int age) {
super(name, age);
}
public Professional(String subject) {
super(subject);
}
public Professional(String name, int age, String subject) {
super(name, age, subject);
}
// 重写
@Override
public void teach() {
System.out.println("专业课老师在教授专业知识");
}
}
public class General extends Teacher{
// 构造
public General() {}
public General(String name, int age) {
super(name, age);
}
public General(String subject) {
super(subject);
}
public General(String name, int age, String subject) {
super(name, age, subject);
}
// 重写
@Override
public void teach() {
System.out.println("通识课老师在教授通识课知识");
}
}
2026.5.7
子类能继承父类哪些内容

java中的权限修饰符

多态
什么是多态?
事物的多种形态
表现形式:
父类类型 对象名称 = 子类对象;
多态的前提:
有继承/实现关系 (必要)
有父类引用子类对象 (必要)
有方法重写(可选)
代码示例:
public class Person {
private String name;
private String id;
private String key;
// 构造
public Person() {}
public Person(String name, String id, String key) {
this.name = name;
this.id = id;
this.key = key;
}
// get/set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
// 行为
public void work() {
System.out.println("在工作");
}
}
public class Student extends Person{
// 构造
public Student() {}
public Student(String name, String id, String key) {
super(name, id, key);
}
// 重写
@Override
public void work() {
System.out.println("学生的工作是学习");
}
}
public class Teacher extends Person{
// 构造
public Teacher() {}
public Teacher(String name, String id, String key) {
super(name, id, key);
}
// 重写
@Override
public void work() {
System.out.println("老师的工作是教书");
}
}
public class Admin extends Person{
// 构造
public Admin() {}
public Admin(String name, String id, String key) {
super(name, id, key);
}
// 重写
@Override
public void work() {
System.out.println("管理员的工作是管理网站");
}
}
public class StudentManger {
// 定义一个方法表示注册用户
// 参数person,此时可以传递person本身的对象,同时也可以传递person的子类对象
public void register(Person person) {
System.out.println(person.getName() + ", " + person.getId() + ", " + person.getKey());
person.work();
}
}
public class Test {
static void main() {
Student stu = new Student("zhnagsan", "Nebula", "123456");
Teacher teach = new Teacher("lisi", "lemi","35456");
Admin ad = new Admin("wwu", "wnagwu1","7895");
StudentManger sm = new StudentManger();
sm.register(stu);
sm.register(teach);
sm.register(ad);
}
}
多态调用成员方法的特点
代码示例:
public class Ye {}
public class Fu extends Ye{
String name = "Fu";
public void fuShow() {
System.out.println("父类的fuShow方法被调用了");
}
public void show() {
System.out.println("父类的show方法被调用了");
}
}
public class Zi extends Fu{
String name = "Zi";
public void ziShow() {
System.out.println("子类的ziShow方法被调用");
}
@Override
public void show() {
System.out.println("子类的show方法被调用了");
}
}
public class Test {
static void main() {
// 变量调用:
// 编译看左边,运行也看左边
// 方法调用:
// 编译看左边,运行看右边
// 利用多态方式创建对象
Fu fu = new Zi();
// 调用成员变量:编译看左边,运行也看左边
// 编译看左边:在把java文件编译成class文件的时候
// 看父类当中没有这个变量,如果有->编译成功,如果没有->失败
// 运行也看左边:在代码真正运行的时候,使用父类的变量
System.out.println(fu.name);
// 调用成员方法:
// 编译看左边,运行看右边
// 编译看左边:看父类中有没有这个方法,如果没有,代码会报错
// 运行看右边:在代码运行起来的时候,运行的是子类里面的方法
// 如果子类没有重写父类的放发,使用的还是父类的方法
fu.fuShow(); // 为什么不会报错?因为编译看左边,父类有这个方法,所以不会报错
fu.show();
// fu.ziShow(); 这个报错的原因就是父类没有这个方法,是子类特有的方法
// 弊端:不能调用子类的特有方法
// 解决多态的弊端:
// 把对象转回子类类型就可以了
Zi zi = (Zi) fu; // 强制转换
zi.ziShow();
// 注意:
Ye y = new Fu();
// 判断一下y是不是父类类型
if (y instanceof Fu) {
Fu ff = (Fu) y;
} else{
System.out.println("请确认你的转换类型是正确的");
}
/* Zi z = (Zi) y;
((Zi) y).show(); */// 这样会报错,在强制转换的时候,只能转到爸爸类型,不能转成儿子类型
}
}

一个代码练习:
public class Transport {
private String brand;
private int speed;
// 构造
public Transport() {}
public Transport(String brand, int speed) {
this.brand = brand;
this.speed = speed;
}
// get/set
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
// 行为:
public void move() {
System.out.println("行驶中");
}
}
public class Bicycle extends Transport{
// 构造
public Bicycle() {}
public Bicycle(String brand, int speed) {
super(brand, speed);
}
// 行为:
public void ringBell() {
System.out.println("自行车响铃");
}
// 方法重写
@Override
public void move() {
System.out.println("自行车在行驶");
}
}
public class Car extends Transport{
// 构造
public Car() {}
public Car(String brand, int speed) {
super(brand, speed);
}
// 行为:
public void honk() {
System.out.println("汽车鸣笛");
}
// 方法重写
@Override
public void move() {
System.out.println("汽车在行驶");
}
}
public class Person {
private String name;
private int age;
private String gender;
// 构造
public Person() {}
public Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
// get/set
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
// 行为:
public void useTransport(Transport transport) {
System.out.println(getName() + "在开" + transport.getBrand() + "以" + transport.getSpeed() + "的速度行驶");
transport.move();
// 判断一下传递过来的是不是自行车
if(transport instanceof Bicycle) {
Bicycle bi = (Bicycle) transport;
bi.ringBell();
}
}
}
public class Test {
static void main() {
// 创建对象
Bicycle bi = new Bicycle("小米自行车",30);
Car car = new Car("凯迪拉克",120);
Person person = new Person("晓云",18,"男");
person.useTransport(bi);
person.useTransport(car);
}
}
抽象类和抽象方法
使用背景:
只要觉得在父类创建方法体没有意义,那么就使用抽象方法

抽象类和抽象方法的主要事项
抽象类不能实例化
继承抽象类时。要么重写抽象类中所有抽象方法
要么子类也是一个抽象类
代码示例:
public abstract class Animal {
private int age;
private String color;
// 构造
public Animal() {}
public Animal(int age, String color) {
this.age = age;
this.color = color;
}
// get/set
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 abstract void eat(String something);
}
public class Cat extends Animal{
// 构造
public Cat() {}
public Cat(int age, String color) {
super(age, color);
}
// 行为:
public void catchMouse() {
System.out.println("猫咪在抓老鼠");
}
// 重写
@Override
public void eat(String something) {
System.out.println("猫咪在吃" + something);
}
}
public class Dog extends Animal{
// 构造
public Dog() {}
public Dog(int age, String color) {
super(age, color);
}
// 行为:
public void lookHome() {
System.out.println("狗子在看看家");
}
// 重写
@Override
public void eat(String something) {
System.out.println("狗子在吃" +something);
}
}
public class Person {
private String name;
private int age;
// 构造
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// get/set
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 animal,String something) {
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.eat("狗粮");
}
if(animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.eat("猫粮");
}
}
}
public class Test {
static void main() {
// 创建对象
Person person = new Person("zhangsan",19);
Dog dog = new Dog(2,"黑色");
Cat cat = new Cat(3,"黄色");
person.keepPet(dog,"狗粮");
person.keepPet(cat,"猫粮");
cat.catchMouse();
}
}
2026.5.8
接口

接口中的成员特点

接口和类的关系
类和类的关系:
继承关系:只能单继承,不能多继承,但是可以多层继承
类和接口的关系:
实现关系:可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
注意点:
1.如果父类Person也是一个抽象类的话,那么在子类当中,需要把所以的抽象方法进行重写,要么子类本身也是一个抽象方法
2.如果在重写的时候出现了重复的抽象方法,此时我们只要重写一次就可以了,就好比如多个干爹让你做同一件事,你只需要做一遍就可以了
接口和接口的关系:
继承关系,可以单继承,也可以多继承
注意点:
1.如果有一个接口A继承了多个接口,此时相当于是把多个接口中的抽象方法全部继承下来了,再此以后,实现类实现接口A的时候,就要把所有的抽象方法进行重写
代码示例:
public abstract class Person {
private String name;
private 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 abstract void aaa();
}
public interface inter1 {
public abstract void method1();
public abstract void method2();
public abstract void bbb();
}
public interface inter2 {
public abstract void function1();
public abstract void function2();
public abstract void bbb();
}
public interface MyInter extends inter1, inter2{
}
public class Interimpl extends Person implements inter1, inter2{
@Override
public void aaa() {
}
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void function1() {
}
@Override
public void function2() {
}
@Override
public void bbb() {
}
// 如果一个类实现了多个接口,那么就要重写多个接口中所有的方法
// 注意:
// 1.如果父类Person也是一个抽象类的话,那么子类当中,需要把所有的抽象方法进行重写,要么子类本省也是一个抽象类
// 2.如果多个接口当中出现了重复的抽象方法,此时我们只要重写一次就可以了
}
public class MyInterimpl implements MyInter{
// 接口和接口的关系
// 继承关,可以单继承,可以多继承
// 注意点:
// 1.如果有一个接口A继承了多个接口,此时想当于是把多个接口中的抽象方法全部继承下来了
// 在以后,实现类实现接口A的时候,就要把所有的抽象方法进行重写
@Override
public void method1() {
}
@Override
public void method2() {
}
@Override
public void bbb() {
}
@Override
public void function1() {
}
@Override
public void function2() {
}
}
接口和抽象类的综合案例
2026.5.9
接口的新特性
***jdk8以后接口中新增的方法
允许在接口中定义默认方法,需要使用关建词default修饰
作用:为了接口升级时,代码不报错
接口中默认方法定义格式:
格式:public default 返回值类型 方法名 (参数列表){}
范例:public default void show() {}
接口中默认方法的注意事项:
默认方法不是抽象方法,所以不强制被重写,但是如果被重写,重写的时候去掉default关键字
public 可以省略,default不能省略
如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
允许在接口中定义静态方法,需要用static修饰
接口中静态方法的定义格式:
格式:public static 返回值类型 方法名(参数列表){}
范例:public static void show() {}接口中静态方法的注意事项:
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public 可以省略,static不能省略
jdk9新增的私有方法
为了抽取默认方法和静态方法中重复代码而出现的
格式1:private 返回值类型 方法名(参数列表){}
范例1:private void show() {}
格式2:private static 返回值类型 方法名(参数列表){}
范例2:private static void method() {}
内部类
什么是内部类?
写在一个类里面的类就叫做内部类
什么时候用到内部类?
一个类表示的事物是另一个类的一部分,且单独存在没意义
比如:汽车的发动机、人的心脏等等
内部类的分类:
成员内部类(了解)
静态内部类(了解)
局部内部类(了解)
匿名内部类(重点)
成员内部类(了解):
写在成员位置的,属于外部类的成员
~可以被一写修饰符所修饰:private\默认\protected\public\static
在成员内部类里面,jdk16之前不能定义为静态变量,之后才可以定义为静态变量
书写成员内部类的代码
Outer.Inner io = new Outer().new Inner //类似于 Student s = new Student(); s.name; // 如果内部类被private修饰,那么可以提供方法进行访问 public Inner getInstance() { return new Inner(); }创建成员内部类的对象
成员内部类获取外部类的成员变量
class Outer{ private int a = 10; class Inner() { private int a = 20 public void show(){ int a = 30; sout(a) // 30 sout(this.a) // 20 sout(Outer.this.a) // 10 } } }
理解Outer.this.a
2026.5.10
静态内部类
什么是~?
~是一种特殊的成员内部类
直接创建静态内部类对象的方式?
Outer.Inner oi = new Outer.Inner();如何调用静态内部类中的方法?
非静态方法:先创建对象,用对象调用
class Outer { int a = 10; static int b = 20; // 静态内部类 static class Inner { public void show1() { Outer o = new Outer(); sout(o.a); sout(b) } } }静态方法:外部类名.内部类名.方法名();
局部内部类
将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量
外界是无法直接使用的,需要在方法内部创建对象使用
该类可以直接访问外部类的成员,也可以访问方法内的局部变量
匿名内部类
什么是匿名内部类?
隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置
匿名内部类的格式?
new 类名或者是接口名() { 重写方法; }; Swim swim = new Swim() { @Override pubilc void swim() { sout("学生在游泳"); }; goSwimming(swim); }匿名内部类等价于
没有名字的java类 + 实现接口/继承类 + 重写方法 + 创建对象
使用场景
如果实现类只要使用一次,就可以用匿名内部类简化代码
Lambda表达式的前置知识点
2025.5.11
字符串的概述
String概述
String类,定义在java.lang包下,无需导包
String的注意点:
字符串的内容是不可变的,他的对象在创建后不能被改变
获取字符串对象的两种方式:
直接赋值:代码简单 + 串池复用
new:每次都会创建一个新的字符串对象
代码示例
public class Test {
static void main() {
// String username = "zhangsan";
// String rightUsername = "Zhangsan";
// boolean b1 = username.equals(rightUsername);
// System.out.println(b1);
//
// boolean b2 = username.equalsIgnoreCase(rightUsername);
// System.out.println(b2);
String username = "张三";
String keywords = "123456";
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入用户名:");
String name = sc.next();
System.out.println("请输入密码:");
String key = sc.next();
if (name.equals(username) && key.equals(keywords)) {
System.out.println("登录成功");
break;
}
if (!name.equals(username)) {
System.out.println("用户名错误,请重新登录");
} else if (!key.equals(keywords)) {
System.out.println("密码错误,请重新登录");
}
}
}
}2026.5.12
字符串中的常见操作
字符串比较
boolean equals方法 (要比较的字符串) 结果完全一样才是True
boolean equalsIgnoreCase(要比较的字符串) 忽略大小写的比较
代码的示例
String username = "zhangsan";
String rightUsername = "Zhangsan";
boolean b1 = username.equals(rightUsername);
System.out.println(b1);
boolean b2 = username.equalsIgnoreCase(rightUsername);
System.out.println(b2);
```java
public class Test {
static void main() {
String name = "张三";
String key = "123456";
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
System.out.println("请输入用户名:");
String username = sc.next();
System.out.println("请输入密码:");
String keywords = sc.next();
if (username.equals(name) && keywords.equals(key)) {
System.out.println("登录成功!");
break;
} else {
System.out.println("输入错误,请重新输入");
System.out.println("你还剩余" + (2 - i) + "次机会");
}
}
}
}
遍历字符串
代码示例
1.charAt
String str = "你好你好123";
char c = str.charAt(3);
System.out.println(c);
2.length
int length = str.length();
System.out.println(length);
练习
public class Test {
static void main() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串");
String str = sc.next();
int length = str.length();
// 字符串遍历当中循环快速生成方式 str.length().fori for (int i = 0; i < length; i++) {
System.out.println(str.charAt(i));
}
}
}
2026.5.13
统计字符次数
统计大写和小写字母,还有数字各有多少个
public class Test2 {
static void main() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串");
String c = sc.next();
int count1 = 0;
int count2 = 0;
int count3 = 0;
for (int i = 0; i < c.length(); i++) {
char str = c.charAt(i);
// 判断大小写
if (str >= 'a' && str <= 'z') {
count1++;
} else if (str >= 'A' && str <= 'Z') {
count2++;
} else if (str >= '0' && str <= '9') {
count3++;
}
}
System.out.println("小写字母的个数为:" + count1);
System.out.println("大写字母的个数为:" + count2);
System.out.println("数字的个数为:" + count3);
}
}
拼接字符串
// 首先定义一个工具类方法,记得私有化
public class ArrayUtil {
private ArrayUtil() {}
public static String Print(int[] arr) {
String str = "[";
// 第一次循环: "[" + 1 + "," -> "[1,"
// 第二次循环: "{1," + 2 + "," -> "[1,2"
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.println(str += arr[i] + "]");
}else {
str += arr[i] + ",";
}
}
return str;
}
}
public class Test1 {
static void main() {
int[] arr = {1,2,3};
int[] arr1 = {1,3,4,57,89,23};
ArrayUtil.Print(arr);
ArrayUtil.Print(arr1);
}
}
2026.5.14
charAt(获取字符串的指定字符)
public class Test {
static void main() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串");
String str = sc.next();
int length = str.length();
// 字符串遍历当中循环快速生成方式 str.length().fori for (int i = 0; i < length; i++) {
System.out.println(str.charAt(i));
}
}
}
敏感词
public class Test {
static void main() {
// String str = "abcdefg";
// String s = str.substring(1, 5); // bcde
// System.out.println(s);
//
// String s1 = str.substring(1);
// System.out.println(s1);
// substring的方式
String str = "adfsgsrgs";
String s = str.substring(0,1);
String encryption = s + "***";
System.out.println(encryption);
//chatAt的方式
char c = str.charAt(0);
String encryption1 = c + "***";
System.out.println(encryption1);
}
}
2026.5.15
敏感词过滤
public class Test {
static void main() {
/*String str = "你是傻逼吗";
String s = str.replace("傻逼", "***");
System.out.println(s); */ String[] arr = {"他妈的", "妈的", "傻逼", "草泥马", "垃圾东西"};
Scanner sc = new Scanner(System.in);
System.out.println("请输入你想说的话");
String s = sc.next();
for (int i = 0; i < arr.length; i++) {
s = s.replace(arr[i], "***");
}
System.out.println(s);
}
}
常见的字符方法(可查看API)
public class Test1 {
static void main() {
// 是否包含 contains -- 敏感词过滤
String name = "zhangsan";
boolean ang = name.contains("ang");
System.out.println(ang);
boolean zs = name.contains("zs");
System.out.println(zs); // 一定要是连续的才可以,不是连续的话,即使里面包含,也会报错
// 判断开头、结尾 starsWith/endsWith String star = "lisi";
boolean li = star.startsWith("li",1);// 从索引为1字符的开始
System.out.println(li);
boolean i = star.endsWith("si");
System.out.println(i);
// 查找 indexOf(int ch) lastIndexOf(int ch) int index = name.indexOf(97); // int char 是ASCII码值 ,注意:这个是查找字符第一次出现的索引值
System.out.println(index);
int index1 = name.lastIndexOf(97);
System.out.println(index1); // 这个索引是正向数的,但是查找a是反过来数的
int index2 = name.indexOf("A");
System.out.println(index2); // 输出为-1,表示的是不存在
// 判断是否为空 isEmpty() 登录注册
boolean zhang = name.isEmpty();
System.out.println(zhang);
String empty = "";
System.out.println(empty.isEmpty());
// 转字符数组 toCharArray() String to = "sidatianwang";
char[] charArray = to.toCharArray();
// 可以改变字符串的内容,通过遍历
System.out.println(charArray[5]);
// 大小写转换 toUpperCase()、toLowerCase()
String upperCase = name.toUpperCase();
System.out.println(upperCase);
String lowerCase = upperCase.toLowerCase();
System.out.println(lowerCase);
// 去除头尾的空格 trim() 登录注册
String t = " a b c ";
String trim = t.trim();
System.out.println(trim);
}
}
2026.5.16
字符串练习
字符串拼接
j字符串反转
public class Test2 {
static void main() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请输入字符串:");
String s = sc.next();
if (s.equals("拜拜")) {
System.out.println("拜拜");
break;
} else {
String s1 = ArrayUtil.arrToString3(s);
System.out.println(s1);
}
}
}
}字符串分离
public class Test3 {
static void main() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入任意字符串");
String s = sc.next();
// for (int i = 0; i < s.length(); i++) {
// char c = s.charAt(i);
// System.out.print(c);
// if ((i + 1) % 8 == 0) {
// System.out.println();
// }
// }
// int lastCount = s.length() % 8;
// int count = 8 - lastCount;
// if (lastCount != 0) {
// for (int i = 0; i < count; i++) {
// System.out.print("0");
// }
// }
// 方法二: 直接在字符串后面补0
int lastCount = s.length() % 8;
int count = 8 - lastCount;
if (count != 0) {
String line = "00000000".substring(0, count);
s += line;
}
for (int i = 0; i < s.length(); i+= 8) {
String res = s.substring(i, i + 8);
System.out.println(res);
}
}
}打乱字符串内容
public class Test4 {
static void main() {
// 定义任意以一个字符串,打乱里面的内容
String s = "abcdefg";
char[] ch = s.toCharArray();
Random r = new Random();
for (int i = 0; i < s.length(); i++) {
int num = r.nextInt(s.length());
char temp = ch[i];
ch[i] = ch[num];
ch[num] = temp;
}
for (int i = 0; i < ch.length; i++) {
System.out.print(ch[i]);
}
}
}
2026.5.17
1. pytest
【测试框架】:
用例发现
用例筛选
用例执行
用例报告
第三发插件
pip install pytest
使用(创建用例、执行用例)
def test_abc:
assert 1 == 2
2026.5.18
要求:
创建test开头的py文件
创建 test_ 开头的函数
在函数中使用断言
pytest 启动框架执行用例
pytest -h 查询参数、配置、使用说明
参数
mark
fixture
hook
2026.5.19
2. requests
向接口发送请求
pip install requests
【向接口发送请求】和pytest结合起来 => 接口自动化
【控制浏览器】和pytest结合起来 -> Web自动化
【控制手机App】和pytest结合起来 -> App自动化
import requests
requests.request() #基本用法、统一用法
def test_baidu(): #基本用法,统一的用法
res = requests.request(
method='get', # HTTP的请求方法
url='https://www.baidu.com', # 接口地址
data={"a":1, "b": 2} # 接口参数,选填,类型有多种
)
print(res.status_code) # 整数
print(res.text) # 字符串
print(res.headers) # 字典
assert res.status_code == 200
assert 'baidu' in res.text
1. 表单参数
主要用在Web项目:
参数只能是字符串
请求头中包含form
requests技巧:
如果data参数是一个字典,则自动将其识别为表单,并自动添加请求头
user_info = {
"username":"sanum",
"password":"123456",
}
def test_api_form():
resp = requests.request(
method='post',
url='http://api.fbi.com:9225/rest-v1/login/with_form',
data=user_info
)
assert resp.status_code == 200
2. JSON参数
主要用在各类项目中:
参数类型很多:字符串、数字、布尔值、空值、数组
请求头中包含JSON
request技巧:
如果传递JSON参数,自动识别为JSON参数类型,自动添加请求头
def test_api_json():
resp = requests.request(
method='post',
url='http://api.fbi.com:9225/rest-v1/login/with_json',
json=user_info
)
assert resp.status_code == 200
3. 文件上传
主要用在各类项目中:
上传方式:
body直传
表单
请求头说明使用哪种方式
requests技巧:
如果传递files参数,自动识别为表单文件上传,自动添加请求头
def test_api_upload():
path = r"C:\Users\123\OneDrive\Desktop\新建 文本文档.txt"
f = open(path,'r') #文件对象
resp = requests.request(
method='post',
url='http://api.fbi.com:9225/rest-v1/upload/one_file',
files={"file":f} #表单上传文件的方式传参
)
assert resp.status_code == 200