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

java —— 面向对象(下)

一、类的继承

(一)继承

子类在继承父类的时候,就会自动拥有父类的所有成员

关键字:extends

格式:子类 extends 父类

class Animal {
    String name;

    // 定义动物叫的方法
    void shout() {
        System.out.println("动物发出叫声");
    }
}

// 定义 Dog 类继承Animal类
class Dog extends Animal {
    // 定义一个打印name的方法
    public void printName() {
        System.out.println("name=" + name);
    }
}

public class Ex01_04 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "沙皮狗";
        dog.printName();
        dog.shout();
    }
}

(二)重写父类方法

class Animal1 {

    void shout() {
        System.out.println("动物发出叫声");
    }
}


class Dog1 extends Animal1 {
    // 重写shout()
    void shout() {
        System.out.println("旺旺");
    }
}

public class Ex02_04 {
    public static void main(String[] args) {
        Dog1 dog1 = new Dog1();
        dog1.shout();
    }
}

(三)super关键字

当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,我们需要用到super关键字

1、案例一(调用父类)

class Animal2 {
    String name = "动物";

    // 定义动物叫的方法
    void shout() {
        System.out.println("动物发出叫声:");
    }
}

// 定义Dog 类继承动物类
class Dog2 extends Animal2 {
    String name = "狗";

    // 重写父的shout()方法
    void shout() {
        super.shout();  // 访问父的成员方法
    }

    // 定义定义name分方法
    void printName() {
        System.out.println("name=" + super.name);   // 访问父的成员变量
    }
}

// 定义测试类
public class Ex03_04 {
    public static void main(String[] args) {
        Dog2 dog2 = new Dog2();
        dog2.shout();       // 到子类
        dog2.printName();
    }
}

2、案例二(子类传参到父类)

class Animal3 {
    // 定义Animal 类有参的构造方法
    public Animal3(String name) {
        System.out.println("我是一只" + name);

    }
}

// 定义Dog3 类继承动物类
class Dog3 extends Animal3 {
    public Dog3(){
        super("小够");
    }
}

// 定义测试类
public class Ex04_04 {
    public static void main(String[] args) {
        Dog3 dog3 = new Dog3(); // 实例化对象,会自动调用Dog3的方法
    }
}

3、案例三(给父类一个无参,避免报错)

class Animal4 {
    // 定义Animal 类无参的构造方法
    public Animal4() {
        System.out.println("我是一只动物");
    }

    // 定义Animal 类有参的构造方法
    public Animal4(String name) {
        System.out.println("我是一只" + name);
    }
}

// 定义Dog4 类继承动物类
class Dog4 extends Animal4 {
    public Dog4() {
        // 当没有任何的调用或者输出,程序可能会报错,如果我们给父类一个无参输出,就不会报错
        
    }
}

// 定义测试类
public class Ex05_04 {
    public static void main(String[] args) {
        Dog4 dog4 = new Dog4(); // 实例化对象,会自动调用Dog4的方法
    }
}

二、final关键字

  • final修饰的类不能被继承
  • final修饰的方法不能班子类重写
  • final修饰的变量(成员变量和局部变量)是常量,只能赋值一次

(一)修饰类

当父类使用了final关键字,子类Dog5无法继承Animal5

(二)修饰方法

无法重写方法

(三)修饰变量

无法重现赋值

(四)案例

1、不给name任何赋值,实际会是null

class Student{
    String name;
    // 打印学生
    public void introduce(){
        System.out.println("我是一个学生,我叫"+name);
    }
}


public class Ex09_04 {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.introduce();
    }
}

2、使用final,程序会报错,因为没有任何的返回值

3、正确做法:

class Student{
    final String name = "小白";
    // 打印学生
    public void introduce(){
        System.out.println("我是一个学生,我叫"+name);
    }
}


public class Ex09_04 {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.introduce();
    }
}

三、抽象类

例如前面的Animal类或者shout方法,一个是动物,一个是动物的叫声,动物是什么动物?动物的叫声又是什么声音?我们无法想象。抽象方法我们必须使用abstract关键字来修饰。

抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法

abstract class Animal7{
    abstract void shout();
}

class Dog7 extends Animal7{
    void shout(){
        System.out.println("白白");
    }
}

public class Ex10_04 {
    public static void main(String[] args) {
        Dog7 dog7 = new Dog7();
        dog7.shout();
    }
}

四、接口

  • 解释:Java 中类只能单继承,但一个类可以实现多个接口。通过使用接口,可以让一个类同时具有多个不同类型的行为,达到类似多继承的效果。
  • 示例:假设有一个 Robot 类,它既需要像 Worker 一样工作,又需要像 Singer 一样唱歌。可以定义 Worker 和 Singer 接口,然后让 Robot 类实现这两个接口。

(一)案例一

interface:接口
implements:实现


// Dog8类实现了Animal8接口
class Dog8 implements Animal8{
    // 实现breathe()方法
    public void breathe(){
        System.out.println("狗在呼吸");
    }

    // 实现run()方法
    public void run(){
        System.out.println("狗在跑");
    }
}

public class Ex11_04 {
    public static void main(String[] args) {
        Dog8 dog8 = new Dog8();
        dog8.breathe();
        dog8.run();
    }
}

(二)案例二

接口继承接口,先继承再实现

class Dog9 implements LandAnimal9 {
    // 实现breathe()方法
    public void breathe() {
        System.out.println("狗在呼吸");
    }

    // 实现run()方法
    public void run() {
        System.out.println("狗在跑");
    }

    public void liveOnland() {
        // TODO Auto-generated method stub
        System.out.println("狗生活在陆地上");
    }
}

public class Ex12_04 {
    public static void main(String[] args) {
        Dog9 dog9 = new Dog9();
        dog9.breathe();
        dog9.run();
        dog9.liveOnland();
    }
}
  • TODO:这是一个常见的注释标记,一般用于提醒开发者在后续需要完成某些任务或者进行代码完善。当 IDE(集成开发环境,像 IntelliJ IDEA、Eclipse 等)搜索代码中的 TODO 标记时,会把这些标记相关的注释显示出来,方便开发者集中处理待办事项。
  • Auto-generated method stub:意思是 “自动生成的方法存根”。在使用 IDE 的自动生成功能(例如实现接口方法、重写父类方法等)时,IDE 会自动创建方法的基本框架,也就是方法签名和空的方法体,同时添加这个注释来表明这是自动生成的代码,还需要开发者去完善具体的实现逻辑。

五、多态

(一)案例一

1、创建好接口

2、实现对口

class Cat10 implements Animal10 {
    public void shout() {
        System.out.println("喵喵~~");
    }
}

class Dog10 implements Animal10 {
    public void shout() {
        System.out.println("旺旺~~");
    }
}

public class Ex13_04 {
    public static void main(String[] args) {
        Animal10 animal1 = new Cat10();
        Animal10 animal2 = new Dog10();
        animalShout(animal1);
        animalShout(animal2);
    }

    public static void animalShout(Animal10 an) {
        an.shout();
    }
}

3、解析

引用类型不同

  • Cat10 animal1 = new Cat10();

    • 引用类型为 Cat10,即 animal1 这个引用变量被明确指定为 Cat10 类型。这意味着 animal1 可以直接访问 Cat10 类中定义的所有方法和属性,包括 Cat10 类特有的方法和属性,以及从父类继承过来的方法和属性。

  • Animal10 animal1 = new Cat10();

    • 引用类型为 Animal10,这里体现了 Java 的多态特性。animal1 是一个 Animal10 类型的引用变量,但它指向的是一个 Cat10 类的对象。在编译阶段,编译器会根据引用类型 Animal10 来检查可以调用的方法和属性,所以 animal1 只能访问 Animal10 类中定义的方法和属性(包括被 Cat10 类重写的方法),而不能直接访问 Cat10 类特有的方法和属性。

(二)案例二

instanceof:用于检查一个对象是否是某个特定类、接口的实例,或者是否是其子类、实现类的实例

class Cat11 implements Animal10 {
    public void shout() {
        System.out.println("喵喵~~");
    }

    void sleep() {
        System.out.println("猫睡觉---");
    }
}

class Dog11 implements Animal10 {
    public void shout() {
        System.out.println("旺旺~~");
    }
}

public class Ex14_04 {
    public static void main(String[] args) {
        Dog11 dog11 = new Dog11();
        animalShout(dog11);

    }

    public static void animalShout(Animal10 an) {
        if (an instanceof Cat11) {
            Cat11 cat11 = (Cat11) an;
            cat11.shout();
            cat11.sleep();
        } else {
            System.out.println("不是Cat11");
        }
    }
}
  • Animal10 an:方法的参数,Animal10 是一个接口类型,an 是传入的参数名。这意味着该方法可以接受任何实现了 Animal10 接口的对象作为参数,体现了多态性。
  • animalShout函数这里的作用是检查传入的 an 对象是否是 Cat11 类的实例。如果是,则执行 if 语句块中的代码;如果不是,则跳过该语句块。

(三)案例三

class Cat11 implements Animal10 {
    public void shout() {
        System.out.println("喵喵~~");
    }

    void sleep() {
        System.out.println("猫睡觉---");
    }
}

class Dog11 implements Animal10 {
    public void shout() {
        System.out.println("旺旺~~");
    }
}

public class Ex14_04 {
    public static void main(String[] args) {
        Dog11 dog11 = new Dog11();
        animalShout(dog11);

    }

    public static void animalShout(Animal10 an) {
        if (an instanceof Cat11) {
            Cat11 cat11 = (Cat11) an;
            cat11.shout();
            cat11.sleep();
        } else if (an instanceof Dog11) {
            Dog11 dog11 = (Dog11) an;
            dog11.shout();
        } else {
            System.out.println("类型不是Cat11");
        }
    }
}

(四)Object类

  • 在 Java 中,toString 是 Object 类中定义的一个方法,所有的类都继承自 Object 类,因此所有的 Java 类都拥有 toString 方法。
  • toString 方法的主要作用是返回一个对象的字符串表示形式。这个字符串通常用于调试、日志记录或者将对象信息以文本形式呈现给用户。当你直接打印一个对象或者将对象与字符串进行拼接时,Java 会自动调用该对象的 toString 方法。

1、实际的toString

class Animal11{
    // 重写Object类的toString()方法
    public String dd(){
        return "I am an animal";
    }

}

public class Ex17_04 {
    public static void main(String[] args) {
        Animal11 animal11 = new Animal11();
        System.out.println(animal11.toString());
    }
}

  • 前面是类名
  • “b4c966a”:这是对象哈希码(hash code)的十六进制表示 。在 Java 里,每个对象都有哈希码,默认由 Object 类的 hashCode 方法生成。这是 toString 方法默认实现的输出形式。因为没有在 Animal11 类中重写 toString 方法,所以直接打印对象时,就会按照 Object 类中 toString 方法的默认逻辑,显示类名加哈希码十六进制值。

2、重写Object的toString()方法

class Animal11 {
    // 重写Object类的toString()方法
    public String toString() {
        return "I am an animal";
    }

}


public class Ex17_04 {
    public static void main(String[] args) {
        Animal11 animal11 = new Animal11();
        System.out.println(animal11.toString());
    }
}

综合题(PCI)

// 网卡
class NetWorkCard implements PCI {
    public void start() {
        System.out.println("send。。。");
    }

    public void stop() {
        System.out.println("NetWord stop");
    }
}

// 声卡
class SoundCard implements PCI {
    public void start() {
        System.out.println("dudu");
    }

    public void stop() {
        System.out.println("sound stop");
    }
}

// 主板(只需要接收和调用)
class MainBoard {
    public void userPCICard(PCI p) {
        p.start();
        p.stop();
    }
}

// 执行者
public class Assembler {
    public static void main(String[] args) {
        MainBoard mb = new MainBoard();
        NetWorkCard nc = new NetWorkCard();
        mb.userPCICard(nc);
        SoundCard sc = new SoundCard();
        mb.userPCICard(sc);
    }
}
  • start 方法:当网卡启动时,输出 "send。。。",模拟网卡发送数据的操作。
  • stop 方法:当网卡停止时,输出 "NetWord stop",表示网卡停止工作。

六、异常

在 Java 中,Throwable是所有错误和异常的超类,它有一个层次清晰的类继承结构,以下是用文字形式描述的Throwable:

  1. Error:表示严重的系统错误,通常是 Java 虚拟机内部错误或资源耗尽等情况,应用程序一般不应该捕获和处理这类错误,比如OutOfMemoryError(内存溢出错误)、StackOverflowError(栈溢出错误)等。
  2. Exception:表示程序运行中可能出现的异常情况,又可进一步分为受检异常(Checked Exception)和非受检异常(Unchecked Exception)。——  一般都是这种

(一)try异常,try终止

getMessage() 方法返回异常的描述信息

public class Ex21_04 {
    public static void main(String[] args) {
        try {
            int result = divide(4, 0);
            System.out.println(result);
        } catch (Exception e) {
            System.out.println("异常信息为:" + e.getMessage());
        }
        System.out.println("继续");
    }

    public static int divide(int x, int y) {
        return x / y;
    }
}

(二)try异常,继续执行

public class E22_04 {
    public static void main(String[] args) {
        try {
            int result = divide(4, 0);
            System.out.println(result);
        } catch (Exception e) {
            System.out.println("异常信息为:" + e.getMessage());
        } finally {
            System.out.println("进入finally代码块");
        }
        System.out.println("继续");
    }

    public static int divide(int x, int y) {
        return x / y;
    }
}

(三)throws关键字

使用场景

  • 受检异常处理:对于受检异常(即继承自 Exception 但不继承自 RuntimeException (RuntimeException 是 Exception 类的子类)的异常),Java 要求必须对其进行处理,要么使用 try-catch 块捕获,要么使用 throws 关键字声明抛出。当方法内部可能抛出受检异常,而方法本身不想处理时,就可以使用 throws 声明抛出该异常,让调用者处理。
  • 异常责任传递:在大型项目中,为了遵循单一职责原则,一个方法可能只负责完成特定的任务,而将异常处理的责任交给调用者,此时可以使用 throws 关键字将异常抛给调用者。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

class ThrowsExample2 {
    // 声明该方法可能会抛出 FileNotFoundException 和 IOException 异常
    public static void readFile(String filePath) throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream(filePath);
        int data = fis.read();
        while (data != -1) {
            // 处理数据
            data = fis.read();
        }
        fis.close();
    }

    public static void main(String[] args) {
        try {
            readFile("nonexistentfile.txt");
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + e.getMessage());
        } catch (IOException e) {
            System.out.println("读取文件时发生 I/O 错误:" + e.getMessage());
        }
    }
}

七、包

在 Java 里,包(Package)是一种组织类和接口的机制,它能将相关的类和接口放在一起,方便代码的管理、维护和复用。下面从包的概念、作用、定义与使用、命名规范等方面详细介绍。

(一)概念

包是一种命名空间,它把类和接口按照一定的逻辑结构进行分组。就好比文件系统中的文件夹,用于存放不同类型的文件,包则用于存放不同功能的类和接口。

(二)作用

  • 避免命名冲突:在大型项目中,可能会有很多类和接口。如果没有包的组织,不同开发者或不同模块定义的类名可能会重复,从而引发命名冲突。使用包可以将类和接口分隔在不同的命名空间中,避免这种冲突。例如,不同公司开发的同名类可以放在不同的包中。
  • 提高代码的可维护性:将相关的类和接口放在同一个包中,使得代码结构更加清晰,便于开发者查找和管理。比如,将所有与数据库操作相关的类放在一个名为 com.example.database 的包中,将所有与用户界面相关的类放在 com.example.ui 包中。
  • 控制访问权限:包可以和访问修饰符(如 privateprotectedpublic)配合使用,实现对类和接口的访问控制。例如,使用 protected 修饰的成员可以被同一个包中的其他类访问。

(三)创建包和导入包

* :通配符(所有的方法),如果单一调用某个方法,则后面使用方法名

(四)命名规范

Java 包名通常采用小写字母,并且遵循域名反转的规则。例如,一个公司的域名为 example.com,那么该公司开发的 Java 项目的包名通常以 com.example 开头。这样做的好处是可以确保包名的全球唯一性,避免命名冲突。以下是一些常见的包名示例:

  • java.lang:Java 语言的核心类库所在的包。
  • java.util:包含了很多实用工具类和集合类的包。
  • com.google.gson:Google 开发的 Gson 库的包名。

(五)包的目录结构

在文件系统中,包的结构对应着目录结构。例如,包 com.example.util 对应的目录结构为 com/example/util(可在电脑文件查看)

刚刚创建包的位置:


http://www.kler.cn/a/522063.html

相关文章:

  • Java中的泛型
  • 【以音频软件FFmpeg为例】通过Python脚本将软件路径添加到Windows系统环境变量中的实现与原理分析
  • 1.27补题 回训练营
  • python学opencv|读取图像(四十九)使用cv2.bitwise()系列函数实现图像按位运算
  • 25美赛ABCDEF题详细建模过程+可视化图表+参考论文+写作模版+数据预处理
  • TypeScript 学习 -类型 - 7
  • 【数据结构】(2)时间、空间复杂度
  • 学习yosys(一款开源综合器)
  • 一文掌握ADB的安装及使用
  • 【全栈】SprintBoot+vue3迷你商城(9)
  • 线程配置经验
  • 一元函数微积分的几何应用:二维平面光滑曲线的曲率公式
  • 苍穹外卖 项目记录 day09 历史订单
  • arkui-x 前端布局编码模板
  • 详解Redis之事务
  • 深度解析:MyBatis-Plus实现分页查询的封装!
  • Meta 计划 2025 年投资 650 亿美元推动 AI 发展
  • mysql DDL可重入讨论
  • 面试题-Java集合框架
  • 【C++高并发服务器WebServer】-9:多线程开发
  • 图形编辑器基于Paper.js教程22:在图形矢量编辑器中,实现两个元素的差集,交集,并集,切割
  • 若依基本使用及改造记录
  • 【C++】0xc0000005写入位置时发生访问冲突解决方法
  • 基于51单片机和ESP8266(01S)、LCD1602、DS1302、独立按键的WiFi时钟
  • sprinboot车辆充电桩
  • 面试场景问题集合