JAVA_08_封装、继承和多态

JAVA_08_封装、继承和多态

01_继承是什么

02_举例子

03_继承的两个特点

JAVA中的继承有别于C++,不能多继承,只能单继承,但是可以多层继承

比如有三个类A和B和C:一个子类只能继承一个父类,如A继承B,不能同时继承多个父类,A不能同时继承B和C,但是可以A继承B,然后B继承C
第二个特点是,假如一个class没有设置父类,那么默认继承Object类

04_继承中成员变量的查找顺序

05_继承成员方法

关于子类中方法的重写:

父类如下:

子类call方法重写如下:

05_继承中的构造方法

06_JAVA中的权限修饰符

07_JAVA中的多态

1. Fu.java (父类)

package com.itheima.test2; public class Fu { String name = "Fu"; public void fuShow() { System.out.println("父类的fuShow方法被调用了~"); } public void show() { System.out.println("父类的show方法被调用了~"); } }

2. Zi.java (子类)

package com.itheima.test2; public class Zi extends Fu { String name = "Zi"; // 子类独有的方法 public void ziShow() { System.out.println("子类的ziShow方法被调用了~"); } // 子类重写父类的方法 @Override public void show() { System.out.println("子类重写的show方法被调用了~"); } }

3. Test.java (测试类)

package com.itheima.test2; public class Test { public static void main(String[] args) { // 多态:父类引用指向子类对象 Fu f = new Zi(); // 1. 访问成员变量 // 编译看左边(Fu),运行也看左边(Fu) -> 输出 Fu System.out.println(f.name); // 2. 访问成员方法 // 编译看左边(Fu),运行看右边(Zi) -> 输出 子类重写的show方法被调用了~ f.show(); // 3. 访问子类特有方法 // f.ziShow(); // ❌ 报错!因为编译时看左边(Fu),Fu类里没有ziShow方法 } }

代码运行结果:

Fu 子类重写的show方法被调用了~

核心知识点总结(看图中的注释):

  1. 成员变量:编译看左边,运行也看左边(编译期绑定)。
    • fFu类型,所以 f.name永远取 Fu里的值。
  2. 成员方法:编译看左边,运行看右边(运行期绑定/动态绑定)。
    • fFu类型,编译器允许调用 Fu里的方法。
    • 但运行时发现 f实际上是 Zi对象,所以执行的是 Zi里重写的方法。
  3. 子类特有方法:不能通过父类引用直接调用。
    • f.ziShow()会报错,因为父类 Fu不知道子类有这个方法。

因此多态是有弊端的,为了解决这个弊端可以使用类型转换

08_类型转换

09_抽象类和抽象方法

  • 抽象方法:只有方法声明,没有方法体的方法
  • 抽象类:包含抽象方法的类

(1)简单代码示例

Animal.java(抽象类)

// 抽象类:有抽象方法的类必须是抽象类 public abstract class Animal { String name; public Animal(String name) { this.name = name; } // 抽象方法:没有方法体,以分号结束 public abstract void makeSound(); // 普通方法:可以有具体实现 public void eat() { System.out.println(name + "正在吃东西"); } }

Dog.java(具体子类)

// 具体子类:必须实现父类的所有抽象方法 public class Dog extends Animal { public Dog(String name) { super(name); } // 必须实现抽象方法 @Override public void makeSound() { System.out.println(name + "汪汪叫!"); } }

Cat.java(具体子类)

public class Cat extends Animal { public Cat(String name) { super(name); } @Override public void makeSound() { System.out.println(name + "喵喵叫!"); } }

Test.java(测试类)

public class Test { public static void main(String[] args) { // ❌ 错误:抽象类不能直接创建对象 // Animal animal = new Animal("动物"); // ✅ 正确:创建具体子类的对象 Animal dog = new Dog("小狗"); Animal cat = new Cat("小猫"); dog.eat(); // ✅ 调用普通方法 dog.makeSound(); // ✅ 调用具体实现的抽象方法 // 输出:小狗正在吃东西 // 输出:小狗汪汪叫! cat.eat(); cat.makeSound(); // 输出:小猫正在吃东西 // 输出:小猫喵喵叫! } }

(2)核心规则总结

抽象方法:使用 abstract关键字没有方法体(没有 {})以分号结束抽象类:使用 abstract关键字可以有抽象方法(必须用 abstract)也可以有普通方法(可以有方法体)可以有属性可以有构造方法子类的责任:如果一个类继承了抽象类必须实现父类的所有抽象方法或者自己也声明为抽象类不能创建对象:抽象类不能直接 new只能通过子类来创建对象

(3)和普通类的区别

区别点

普通类

抽象类

创建对象

✅ 可以

❌ 不可以

抽象方法

❌ 不能有

✅ 可以有

abstract关键字

❌ 不需要

✅ 必须用

继承

可以选择

必须被子类实现

(4)为什么要用抽象类?

  • 强制规范:要求子类必须实现某些方法
  • 代码复用:抽象类中的普通方法可以被所有子类共享
  • 设计约束:比如“动物”都要会叫,但“狗”和“猫”叫的方式不同

(5)一句话理解抽象类:

"半成品"​ 或 "模板",它定义了一部分功能,剩下的让子类去完成。

10_接口

(1)接口 vs 抽象类主要区别总结

特性

抽象类

接口

关键字

abstract class

interface

继承

只能继承一个

可以实现多个

方法

可以有抽象方法和普通方法

主要是抽象方法(新版可以有默认方法)

变量

可以有各种变量

只能是常量(public static final)

构造方法

✅ 可以有

❌ 不能有

单继承

✅ 只能继承一个类

✅ 可以实现多个接口

(2)使用场景简单例子

一句话记住接口:接口就是"约定"或"协议",它说:"只要你实现了我的方法,你就具备了某种能力"

比如:USB接口约定好"连接"和"传输"两个方法,鼠标和键盘只要实现这两个方法,就能当USB设备用。

11_内部类

内部类:一个类定义在另一个类的内部

(1)例子

Outer.java(外部类)
public class Outer { private String outerField = "我是外部类"; // 成员内部类:像外部类的成员一样 class Inner { private String innerField = "我是内部类"; public void show() { // 内部类可以直接访问外部类的私有成员 System.out.println("访问外部类:" + outerField); System.out.println("访问内部类:" + innerField); } } public void test() { // 外部类创建内部类对象 Inner inner = new Inner(); inner.show(); } }
Test.java(测试类)
public class Test { public static void main(String[] args) { // 1. 先创建外部类对象 Outer outer = new Outer(); // 2. 通过外部类对象创建内部类对象 Outer.Inner inner = outer.new Inner(); inner.show(); // 或者直接调用外部类的方法 outer.test(); } }

(2)四种内部类

public class FourTypes { private String name = "外部类"; // 1. 成员内部类(最常用):普通类中的普通类 class MemberInner { void show() { System.out.println("成员内部类:" + name); } } // 2. 静态内部类:普通类中的静态类 static class StaticInner { void show() { // System.out.println(name); // ❌ 不能访问外部非静态成员 System.out.println("静态内部类"); } } public void test() { // 3. 局部内部类:方法里的类 class LocalInner { void show() { System.out.println("局部内部类:" + name); } } LocalInner li = new LocalInner(); li.show(); // 4. 匿名内部类:没有名字的类(常用) Runnable r = new Runnable() { @Override public void run() { System.out.println("匿名内部类:" + name); } }; r.run(); } }

(3)常用场景示例

情况1:成员内部类(标准写法)
// 外部类:汽车 class Car { private String brand = "奔驰"; // 内部类:发动机 class Engine { private String type = "V8"; public void start() { // 可以访问外部类的私有属性 System.out.println(brand + "汽车的" + type + "发动机启动了!"); } } } // 使用 public class Test1 { public static void main(String[] args) { Car car = new Car(); Car.Engine engine = car.new Engine(); engine.start(); // 奔驰汽车的V8发动机启动了! } }
情况2:静态内部类(独立性强)
// 外部类:学校 class School { private static String schoolName = "清华"; // 静态内部类:学生 static class Student { private String name; public Student(String name) { this.name = name; } public void study() { System.out.println(name + "在" + schoolName + "学习"); // 只能访问外部类的静态成员 } } } // 使用:不需要外部类对象 public class Test2 { public static void main(String[] args) { School.Student student = new School.Student("小明"); student.study(); // 小明在清华学习 } }
情况3:匿名内部类(最常用)
public class Test3 { public static void main(String[] args) { // 场景1:实现接口(比如按钮点击) Runnable task = new Runnable() { @Override public void run() { System.out.println("匿名内部类:执行任务"); } }; task.run(); // 场景2:继承抽象类 Animal cat = new Animal() { @Override void sound() { System.out.println("喵喵叫"); } }; cat.sound(); } } abstract class Animal { abstract void sound(); }
情况4:局部内部类(方法里使用)
public class Test4 { public void outerMethod() { final int localVar = 100; // 局部变量需要是final或事实上final // 局部内部类 class LocalClass { void show() { System.out.println("局部内部类,访问局部变量:" + localVar); } } LocalClass lc = new LocalClass(); lc.show(); } public static void main(String[] args) { Test4 test = new Test4(); test.outerMethod(); // 局部内部类,访问局部变量:100 } }

(4)实际应用场景

场景1:简化代码(事件监听器)

// 按钮类 class Button { // 内部接口 interface OnClickListener { void onClick(); } private OnClickListener listener; public void setOnClickListener(OnClickListener listener) { this.listener = listener; } public void click() { if (listener != null) { listener.onClick(); } } } // 使用(最常见) public class App { public static void main(String[] args) { Button button = new Button(); // 用匿名内部类设置点击监听器 button.setOnClickListener(new Button.OnClickListener() { @Override public void onClick() { System.out.println("按钮被点击了!"); } }); button.click(); // 按钮被点击了! } }

场景2:私有内部类(隐藏实现细节)

// 电脑类:对外只提供USB接口 class Computer { // 私有内部类:对外隐藏USB实现 private class USBImpl implements USB { @Override public void connect() { System.out.println("USB已连接"); } @Override public void transfer() { System.out.println("数据传输中..."); } } // 对外提供USB接口 public USB getUSB() { return new USBImpl(); } } interface USB { void connect(); void transfer(); } // 外部只能使用USB接口,看不到内部实现 public class User { public static void main(String[] args) { Computer computer = new Computer(); USB usb = computer.getUSB(); // 只能获得USB接口 usb.connect(); // USB已连接 usb.transfer(); // 数据传输中... } }

6. 注意事项

  1. 成员内部类:需要外部类对象才能创建
  2. 静态内部类:可以直接创建,不需要外部类对象
  3. 匿名内部类:必须继承一个类或实现一个接口
  4. 局部内部类:只能在方法内部使用

内部类就是"包在里面的小助手",可以直接访问主人的私有东西,但对外界是隐藏的。

Read more

【汉化中文版】OpenClaw(Clawdbot/Moltbot)第三方开源汉化中文发行版部署全指南:一键脚本/Docker/npm 三模式安装+Ubuntu 环境配置+中文汉化界面适配开源版

【汉化中文版】OpenClaw(Clawdbot/Moltbot)第三方开源汉化中文发行版部署全指南:一键脚本/Docker/npm 三模式安装+Ubuntu 环境配置+中文汉化界面适配开源版

OpenClaw这是什么? OpenClaw(曾用名 Clawdbot / Moltbot)是一个开源的个人 AI 助手平台(GitHub 120k+ Stars),可以通过 WhatsApp、Telegram、Discord 等聊天软件与 AI 交互。简单说就是:在你自己的机器上运行一个 AI 助手,通过常用聊天软件跟它对话。 forks项目仓库 :https://github.com/MaoTouHU/OpenClawChinese 文章目录 * OpenClaw这是什么? * 汉化效果预览 * 环境要求 * 安装方式 * 方式 A:一键脚本(推荐新手) * 方式 B:npm 手动安装 * 方式 C:Docker 部署(服务器推荐) * 首次配置 * 运行初始化向导 * 安装守护进程(

By Ne0inhk
copilot学生认证2026-github copilot学生认证(手把手教会)

copilot学生认证2026-github copilot学生认证(手把手教会)

1.前言 博主在24年的时候发过一篇copilot认证成功的帖子,当时也是领到了一年的pro 文章链接:github copilot学生认证(手把手一小时成功)-ZEEKLOG博客 如今26年了,copilot的申请增加了一年的时间,博主也进入了研究生生涯,前段时间也是再次进行了申请,现在已经用上了,Pro 版直接解锁无限制基础功能 + 海量高级模型,我的感受是:真香!:   既然官方的申请有变化,咱们教程也得与时俱进,下面就开始手把手教大家如何进行申请copilot学生会员。 2.完善 GitHub 账号基础配置 在Emails里面加入你对应学校的教育邮箱(以edu.cn结尾),打开教育邮箱点击GitHub发送的验证邮件链接,即可完成邮箱认证 3.Github学生认证 完成上述步骤后,打开学生认证申请链接,依旧还是在设置里面,这里也可以用手机操作,因为上传证明材料用手机拍照更方便: 选择身份为学生,下滑填写学校信息,输入学校的英文,最后选择自己的学校教育邮箱,点击continue(还得分享位置) 接下来就是上传证明材料: * 可以使用手机摄像头拍摄,证件

By Ne0inhk
第4章:开源模型全景图:如何选择你的技术底座

第4章:开源模型全景图:如何选择你的技术底座

第4章:开源模型全景图:如何选择你的技术底座 引言 开源大模型生态正在经历爆炸式增长。截至2024年6月,HuggingFace平台托管的模型数量已超过50万个,每月新增数千个模型。面对如此庞杂的选择,技术决策者往往陷入两难:是选择规模最大、性能最强的模型,还是选择更符合实际约束的务实方案?本章将建立一套系统的模型选型框架,通过参数规模-性能曲线分析、推理成本量化和许可证风险评估,为技术决策提供科学依据。 1. 开源模型生态现状分析 1.1 主流开源模型系列对比 当前开源大模型生态已形成多个技术流派,各具特色: Llama系列(Meta): * 技术特点:基于Transformer解码器架构,使用RoPE位置编码,采用Grouped-Query Attention优化 * 开源策略:社区友好许可证,允许商业使用(需申请) * 代表型号:Llama-2-7B/13B/70B,Llama-3-8B/70B * 优势:生态完善,工具链成熟,微调资源丰富 Mistral系列: * 技术特点:采用滑动窗口注意力(Sliding Window

By Ne0inhk