当前位置: 首页 > news >正文

Java 学习笔记(基础篇12)

1. static 静态变量:

① 被 static 修饰的成员变量,成为静态变量

  • 特点:该类被所有类共享、不属于对象,属于类、随着类的加载而加载,优于对象存在
  • 调用方法:类名调用

② 被 static 修饰的成员方法,成为静态方法

  • 特点:多用在测试类和工具类中、JavaBean类中很少用
  • 调用方法:类名调用

③ 注意

(1) 静态方法只能访问静态变量和静态方法

(2) 非静态方法可以访问所有(静态\非静态的(成员)变量\方法)

(3) 静态方法是没有this关键字

④ 总结:

(1) 静态方法中,只能访问静态

(2) 非静态方法可以访问所有

(3) 静态方法无this关键字

2. main 方法重识

3. 继承

面向对象三大特性:封装、继承、多态。

① 继承:

  • java提供的一个关键字extends,可以让一个类和另一个类建立起继承关系。public class Student extends Person{}
  • 子类可以在父类的基础上添加新功能,继承父类方法和变量

当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码。子类只能访问父类中非私有的成员

② 注意事项:

(1) Java 是单继承的:一个类只能继承一个直接父类;Java 中的类不支持多继承,但是支持多层继承。

(2) Object 类是 Java 中所有类的祖宗。

class A {} //extends Object{}  
class B extends A{}  
// class C extends B , A{} // 报错  
class D extends B{}  

③ 继承中成员的可继承性分析

(1) 成员变量

修饰符能否继承?访问权限
非私有public/protected/ 默认)✅ 直接继承子类可直接访问(默认修饰符仅同包子类可直接访问)
private✅ 继承(占子类对象内存),但 ❌ 直接访问需通过父类的 getter/setter 间接操作
(2) 成员方法
修饰符能否继承?说明
非私有public/protected/ 默认)✅ 直接继承子类可重写或直接调用
private❌ 不继承父类私有方法对 subclass 完全隐藏
(3) 构造方法
  • 任何构造方法都不能被继承
  • 子类构造时,必须通过 super() 调用父类构造(隐式或显式),但父类构造方法本身不会成为子类的方法。

(4) PS:构造方法和成员方法的区别:

构造方法:创建并初始化对象(给对象的成员变量赋初始值)。

成员方法:定义对象的行为 / 功能(如计算、打印、逻辑处理等)。

④ 继承中成员变量的访问特点

(1) 就近原则:访问成员变量时,优先使用 “距离近” 的变量(子类有则用子类的;子类没有,再找父类)。

class Father { int num = 10; }
class Son extends Father { int num = 20; }
Son s = new Son();
System.out.println(s.num); // 输出 20(优先用子类的 num)

(2) super 调用:若需明确访问父类的成员变量,用 super.变量名,直接到父类中查找。

class Son extends Father {public void show() {System.out.println(super.num); // 输出 10(访问父类的 num)}
}

⑤ 方法重写(Override)

(1) 适用场景:当父类的方法无法满足子类当前的功能需求时,子类对父类方法进行重写

(2) 语法格式:子类与父类有完全一致的方法声明(方法名、参数列表、返回值类型相同),子类的该方法即为 “重写的方法”。

(3) @Override 注解的作用:加在子类重写的方法上,校验重写语法是否正确(如方法签名不匹配,IDE 会显示红色波浪线报错)。

(4) 底层原理:子类重写方法后,JVM 的虚方法表中,该方法的 “父类版本” 会被 “子类版本” 覆盖。

⑥ 继承中成员方法的重写规则

(1) 签名一致性:重写方法的名称、参数列表(行式) 必须与父类完全一致。

(2) 访问权限更宽松:子类重写方法的访问权限 ≥ 父类方法(如父类是 protected,子类可改为 public)。

(3) 返回值类型更严格 / 兼容:子类重写方法的返回值类型 ≤ 父类方法(支持 “协变返回”,例如父类返回 Number,子类可返回 Integer)。

(4) 建议性原则:重写方法尽量与父类保持一致(保证子类行为对父类的 “兼容性”)。

(5) 底层限制:只有被加入 虚方法表 的方法(非 private、非 static、非 final 的方法),才能被重写。

⑦ 继承中「构造方法」的访问特点

(1) 不可继承,但可调用:子类不能直接继承父类的构造方法,但可以通过 super(...) 调用父类构造。

(2) 默认调用父类无参构造:子类构造方法的第一行,默认隐含 super()(自动调用父类的无参构造)。

(3) 执行顺序:子类所有构造方法,会先调用父类的无参构造,再执行自身的构造逻辑。

(4) 调用父类有参构造:若需调用父类的有参构造,必须手动书写 super(参数)(替换默认的 super())。

4. 多态

① 多态是继承 / 实现关系下的现象,表现为:对象多态(父类引用可指向子类对象)、行为多态(同一方法调用,子类有不同实现)。

② 具体代码体现:父类引用指向子类对象,调用方法时执行子类重写的逻辑:

People p1 = new Student(); // 父类People引用指向子类Student对象
p1.run(); // 执行Student类中重写的run()方法People p2 = new Teacher(); 
p2.run(); // 执行Teacher类中重写的run()方法

③ 多态的前提

  • 存在继承 / 实现关系(类继承父类,或类实现接口);
  • 存在父类引用指向子类对象(如 父类 变量 = new 子类());
  • 存在方法重写(子类重写父类的方法)。

④ 调用规则:

(1) 方法编译看左边,运行看右边

  • 编译阶段(javac:检查左边父类引用的类型是否包含要调用的方法。若父类有该方法,编译通过;若没有,直接报错。
  • 运行阶段(java:实际执行右边子类对象重写后的方法(若子类重写了父类方法)。
Animal a = new Dog(); 
a.run(); // 编译时:检查Animal类是否有run()方法;运行时:执行Dog类重写的run()方法

(2) 成员变量访问规则:由左边的引用类型决定

  • 子类对象会继承父类的成员变量,但通过 “父类引用” 访问时,使用的是父类的成员变量(成员变量不体现 “多态”,多态是方法的特性)。

⑤ 多态的优势

(1) 解耦合,便于扩展和维护:多态场景下(如 父类 引用 = new 子类();),“右侧实际创建的子类对象” 可灵活替换,上层调用代码无需修改。新增子类或修改子类逻辑时,不影响原有代码结构,降低依赖、方便维护。

(2) 方法参数的通用性:当方法的参数声明为父类类型时,该方法可以接收这个父类的所有子类对象。无需为每个子类单独编写方法,提升代码复用性。

⑥ 多态的弊端

(1) 多态的核心是 “父类引用指向子类对象”,但此时 父类引用无法直接调用子类的 “特有方法”(即子类独有的、父类未定义的方法)。

class Animal { public void eat() {} }
class Dog extends Animal {public void eat() { System.out.println("吃骨头"); }public void watchHome() {} // Dog的特有方法
}Animal a = new Dog();
a.eat(); // 合法(父类、子类都有该方法)
a.watchHome(); // 编译错误!父类Animal没有该方法,无法调用

(2) 弊端的解决方案:向下转型(结合 instanceof 判断)

  • Java 新特性:模式匹配(instanceof 直接结合强转)
Animal a = new Dog();
if (a instanceof Dog d) { // 若a是Dog类型,直接强转为变量dd.watchHome(); // 用d调用特有方法
} else {// 非Dog类型的逻辑
}

代码示例:

package Test2;
public class test {public static void main(String[] args) {Person p1 = new Person("老王", 30);Dog d = new Dog("黑色", 2);Cat c = new Cat("橘黄色", 3);p1.keepPet(d, "狗粮"); // keepPet参数若为“父类(如Animal)”,可接收Dog子类对象// 若需调用Dog特有方法(如watchHome),则需向下转型:if (d instanceof Dog dog) {dog.watchHome();}}
}

⑦ 综合练习

题目:宠物喂养管理系统

需求:

设计一个简单的宠物喂养管理系统,通过面向对象的继承、多态等特性实现不同宠物的行为表现,具体包含以下类结构:

(1) 父类 Animal

  • 包含私有属性:age(年龄,int类型)、color(颜色,String类型)。
  • 提供构造方法:无参构造和带agecolor参数的有参构造。
  • 提供公共方法:getAge()(获取年龄)、getColor()(获取颜色);以及抽象方法 eat(String something)(需子类实现,定义宠物 “吃食物” 的行为)。

(2) 子类 Dog

  • 继承自 Animal,提供无参构造和带agecolor参数的有参构造(需调用父类构造)。
  • 重写 eat(String something) 方法:输出格式为 “X 岁的 Y 颜色的狗两只前腿死死的抱住 Z 猛吃”(其中 X 是年龄,Y 是颜色,Z 是传入的食物)。
  • 新增特有方法 lookHome():输出 “狗在看家”

(3) 子类 Cat

  • 继承自 Animal,提供无参构造和带agecolor参数的有参构造(需调用父类构造)。
  • 重写 eat(String something) 方法:输出格式为 “X 岁的 Y 颜色的猫眯着眼睛侧着头吃 Z”(参数含义同上)。
  • 新增特有方法 catchMouse():输出 “猫抓老鼠”

(4) 人类 Person

  • 包含私有属性:name(姓名,String类型)、age(年龄,int类型)。
  • 提供构造方法:无参构造和带nameage参数的有参构造。
  • 定义方法 keepPet(Animal a, String something)
    • 通过 instanceof 判断传入的AnimalDog还是Cat
    • 若为Dog:输出 “年龄为 A 岁的 B 养了一只 C 颜色的 D 岁的狗”(A 是Person的年龄,B 是姓名,C 是狗的颜色,D 是狗的年龄);然后调用狗的eat(something)lookHome()方法。
    • 若为Cat:输出 “年龄为 A 岁的 B 养了一只 C 颜色的 D 岁的猫”(参数含义同上);然后调用猫的eat(something)catchMouse()方法。
    • 若既不是Dog也不是Cat,输出 “没有这种动物”

(5) 测试类 Test
main方法中:

  • 实例化一个Person对象(姓名 “老王”,年龄 30)。
  • 实例化一个Dog对象(年龄 2,颜色 “黑”),调用PersonkeepPet方法,给狗喂 “骨头”。
  • 实例化一个Cat对象(年龄 3,颜色 “灰”),调用PersonkeepPet方法,给猫喂 “鱼”。
package Test3;public class test {public static void main(String[] args) {Person p = new Person("老王",30);Dog d = new Dog(2,"黑");Cat c = new Cat(3,"灰");p.keepPet(d,"骨头");p.keepPet(c,"鱼");}
}

关键逻辑:

    @Overridepublic void eat(String something) {System.out.println(getAge() + "岁的" + getColor() 
+ "颜色的狗两只前腿死死的抱住" + something + "猛吃");  //不太理解}
  • getAge()getColor() 前面不需要加 .,核心原因是:这些方法是当前对象(this)自身的方法,在实例方法中调用自身方法时,默认会隐式使用 this 关键字,而 this. 可以省略不写
  • getAge() 和 getColor() 是从父类 Animal 继承的方法(通常是属性的 getter 方法,用于获取 age 和 color 的值)。由于 Dog 继承了 Animal,这些方法就成为了 Dog 类自身的方法,属于 Dog 实例(对象)。
package Test3;public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public void keepPet(Dog dog, String something) {System.out.println("年龄为" + age + "岁的" + name + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗");  //为什么这里不用getAge这些}
}
  • 在 Person 类的 keepPet 方法中,直接使用 age 和 name 而不通过 getAge()getName() 方法,核心原因是:这些变量是当前类(Person 类)自己的私有成员变量,在本类内部可以直接访问,无需通过 getter 方法
  • Dog 类虽然继承了 Animal 类,但作为子类,它无法直接访问父类 Animal 中被 private 修饰的 age 和 color。因此,要获取这两个属性的值,必须依赖父类 Animal 提供的 public 级别的 getter 方法getAge() 和 getColor())。
http://www.dtcms.com/a/358738.html

相关文章:

  • 小狼毫输入法中让数字键盘上的数字键不再选择候选词而是与原始输入一起直接上屏
  • 计算机视觉与深度学习 | 基于深度学习的图像特征提取与匹配算法综述及MATLAB实现
  • 互联网大厂大模型应用开发岗位面试:技术点详解与业务场景演练
  • nacos3端口漂移问题
  • shell编程-核心变量知识
  • LeetCode - 234. 回文链表
  • 2025年高性能计算年会
  • Golang 面试题「高级」
  • 零碳智慧园区双碳方案
  • 代理IP网站哪家好?全球优质IP代理服务商有什么推荐?
  • 【Linux】网络安全管理:Netfilter、nftables 与 Firewalld | Redhat
  • Linux查看Java进程PID、端口号和内存占用脚本
  • 2023年山东省信息学小学组(CSP-X)第一轮题解
  • 【嵌入式原理系列-第六篇】从Flash到RAM:MCU ld脚本全解析
  • SUMO 与 孪易 IOC 协同:开启交通数字孪生新纪元
  • 哪些人需要考道路运输安全员证?政策要求与适用范围
  • 计算机网络面试集合
  • 通过jar -jar启动jar包的yml配置logback 指定log目录
  • 2025-08-18面试题关于公司
  • 【计算机视觉】Pixel逐像素分类Mask掩码分类理解摘要
  • Git 远程仓库操作:推送到远程仓库、拉取远程仓库到本地仓库
  • C语言 - 输出参数详解:从简单示例到 alloc_chrdev_region
  • AV1编码资源可用性模式
  • DC-HRNet
  • SQL学习记录
  • 键查跑分、比配置的手机性能排行
  • ThingsBoard使用Vue3实现
  • nacos 2.5.1 心跳源码解析
  • MCP进阶指南:如何挑选最适合你的AI助手“装备“
  • 计算机毕业设计 java 在线学习系统 基于 Java 的在线教育平台 Java 开发的学习管理系统