Java基础之类封装、继承、多态

简介: Java基础之类封装、继承、多态

Java基础之类封装、继承、多态Java基础之类封装、继承、多态
上篇我们学习了Java的类和对象,类定义了对象的属性和方法,对象可以使用new关键字将类实例化。
今天来看面向对象编程(OOP)的三大基本也是其核心特性: 封装、继承与多态。
封装
在Java中,一个个的包(Package)包含了很多很多的类,每个类中都有各自的属性和行为,我们在使用的时候,可以通过import关键字引入包中的类。
然后实例化对象来调用其中的属性和方法,方法内部对调用者来说是不可见的,这个就是封装的概念。
封装是面向对象编程的基础,它将数据和行为组合在一个包中,并对对象的使用者隐藏了具体的实现细节。
也就是说我们通过定义类(Class)来实现了封装,同时使用private、public等关键字来实现对属性和方法的可访问权限控制。
public class Person {
private String name; // 私有属性,外部不能直接访问
private int age; // 私有属性,外部不能直接访问
// 构造函数
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 公共方法,用于获取name属性
public String getName() {
return name;
}
// 公共方法,用于设置name属性
public void setName(String name) {
this.name = name;
}
// 公共方法,用于获取age属性
public int getAge() {
return age;
}
// 公共方法,用于设置age属性
public void setAge(int age) {
if (age >= 0) { // 设置年龄前进行校验
this.age = age;
} else {
System.out.println("年龄不能为负数");
}
}
// 行为方法
public void introduce() {
System.out.println("我的名字是:" + name + ",我今年" + age + "岁");
}
}
// 使用Person类
public class Main {
public static void main(String[] args) {
Person person = new Person("张三", 25);
person.introduce(); // 输出:我的名字是:张三,我今年25岁
person.setAge(-1); // 输出:年龄不能为负数
}
}
在上面的代码中,Person 类封装了 name 和 age 属性,以及与之相关的方法。通过将属性设置为私有(private),我们防止了外部直接访问这些属性,必须通过公共(public)方法来间接访问和修改,从而保证了数据的完整性和安全性。
这就是类的封装,调用者只需关注调用方法,不需要关注方法内部的实现,而且等到需要修改方法中实现的时候,也不会影响到调用者的代码逻辑。

继承(Inheritance)
继承其实就和现实中父与子的关系一样了,一个子类可以通过继承父类来获取父类的属性和方法。
子类可以有父类没有的拓展的属性和方法,也可以重写覆盖掉父类的方法。
现实中一个儿子只能有一个爹,但是一个爹能有多个儿子。父类和子类也一样,父类可以有多个子类继承,但是子类必须只能有一个父类。
// 父类
public class Animal {
    protected String name; // 保护级别属性,子类可以访问
    public Animal(String name) {
        this.name = name;
    }
    public void makeSound() {
        System.out.println("动物叫声");
    }
}
// 子类
public class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类构造函数
    }
    @Override
    public void makeSound() {
        System.out.println(name + "在汪汪叫");
    }
    public void fetch() {
        System.out.println(name + "在取东西");
    }
}
// 使用继承
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("旺财");
        dog.makeSound(); // 输出:旺财在汪汪叫
        dog.fetch();     // 输出:旺财在取东西
    }
}
Dog 类继承自 Animal 类。Dog 类不仅拥有了 Animal 类的 name 属性和 makeSound 方法,还添加了一个新的方法 fetch。同时,Dog 类覆盖了 makeSound 方法,提供了自己的实现。
这就是继承的概念,父类也叫超类。注意protected关键和private一样也是用来访问控制的,意思是非公共但是子类也可以访问的权限。

多态(Polymorphism)
多态是面向对象编程中的一个核心概念,它允许我们以统一的接口来处理不同类型的对象。
在Java中,多态通常通过继承和接口实现。
上面我们知道了多个子类可以通过继承父类来继承父类的属性和方法,然后对父类的方法进行不同的覆盖实现。
多态的原理就是基于类的继承关系:当子类继承父类时,子类会继承父类的所有公有(public)和受保护(protected)的成员变量和方法。
这样,我们就可以使用父类的引用来指向子类的对象,而调用方法时,会根据实际的对象类型来执行相应的方法。
// 父类
class Animal {
    public void makeSound() {
        System.out.println("动物叫声");
    }
}
// 子类
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪叫");
    }
}
// 子类
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵叫");
    }
}

// 使用多态
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();
        dog.makeSound(); // 输出:汪汪叫
        cat.makeSound(); // 输出:喵喵叫
    }
}
在上面的例子中,我们定义了一个父类 Animal 和两个子类 Dog 和 Cat。
子类都覆盖了父类的 makeSound 方法。
我们创建了 Animal 类型的引用,但实际上指向了 Dog 和 Cat 的对象。当我们调用 makeSound 方法时,会根据实际的对象类型来执行相应的方法,这就是多态的概念。
同样都是makeSound(),但是不同对象调用后就会有不同的实现,狗是汪汪,猫是喵喵。
还有一种多态的实现,是用接口实现。
接口是什么呢?
接口是一种抽象类型,它允许我们定义一组方法,而不需要实现这些方法。
通过用类来实现接口,类就可以使用接口类型的引用来指向实现接口的类的对象,而调用方法时,会执行类实现的相应方法。
所以接口就相当于一个父类,但是接口不需要像父类一样有自己的实现:
// 这样就定义了一个接口。
interface Flyable {
    //飞
    void fly();
}
// 实现接口的类
class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("鸟儿飞翔");
    }
}
// 实现接口的类
class Airplane implements Flyable {
    @Override
    public void fly() {
        System.out.println("飞机飞行");
    }
}

// 使用多态
public class Main {
    public static void main(String[] args) {
        Flyable bird = new Bird();
        Flyable airplane = new Airplane();
        bird.fly(); // 输出:鸟儿飞翔
        airplane.fly(); // 输出:飞机飞行
    }
}
我们定义了一个接口 Flyable 和两个实现接口的类 Bird 和 Airplane。在 Main 类中,我们创建了 Flyable 类型的引用,但实际上指向了 Bird 和 Airplane 的对象。当我们调用 fly 方法时,会根据实际的对象类型来执行相应的方法。

父类通常用来表示is-a关系,即子类是父类的一种。
接口用来表示can-do关系,即实现接口的类具有某种能力或行为。
子类只能有一个父类,但是实现类能实现多个接口

向上转型和向下转型的类型转换
上面实现多态的这种将子类对象引用赋值给父类引用的过程其实叫向上转型。当然实现类引用赋值给接口也一样。
这种转型是安全的,因为子类对象一定是父类的一个实例。向上转型会丢失子类特有的方法和属性,但仍然可以访问父类中定义的方法和属性。
还有对应的一种是向下转型,将父类对象引用赋值给子类引用的过程。这种转型是不安全的,因为父类对象可能不是子类的一个实例。如果直接进行向下转型,可能会导致 ClassCastException。因此,在向下转型之前,通常需要使用 instanceof 运算符来检查对象是否是子类的实例。
当然我们编写代码的时候一般肯定是知道,所以常用的就是直接强转:
if (animal instanceof Dog) {
    Dog dog = (Dog) animal; // 向下转型,前提是animal确实是Dog类型的实例
} else {
    // 不是Dog类型的实例,不能进行向下转型
}
向上转型和向下转型是多态性的两个方面。
向上转型是隐式的,通常在继承和接口实现中自动发生。
向下转型是显式的,需要使用强制类型转换,并且在使用前应该进行类型检查,以确保类型转换的安全性。
END
目录
相关文章
|
3天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
16 1
|
3天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
10 0
java基础(13)String类
|
3天前
|
存储 Java
Java编程中的对象和类
【8月更文挑战第55天】在Java的世界中,“对象”与“类”是构建一切的基础。就像乐高积木一样,类定义了形状和结构,而对象则是根据这些设计拼装出来的具体作品。本篇文章将通过一个简单的例子,展示如何从零开始创建一个类,并利用它来制作我们的第一个Java对象。准备好让你的编程之旅起飞了吗?让我们一起来探索这个神奇的过程!
24 10
|
1天前
|
安全 Java 数据安全/隐私保护
Java 封装怎么理解
封装是Java中的一种重要机制,它将对象的状态(数据)和行为(方法)打包在一起并控制外部访问权限,以保护数据不被随意修改。封装的主要目的包括数据保护、接口设计和增强模块性。通过使用`private`、`protected`及`public`等访问控制修饰符,结合getter和setter方法,可以有效隐藏对象内部实现细节。下面是一个简单的`BankAccount`类示例,展示了如何通过封装保护类的内部状态,确保数据安全和一致性,简化类的使用。理解封装有助于编写高质量代码和设计优秀程序架构。
|
1天前
|
Java 数据安全/隐私保护
Java 封装详解
在 Java 中,封装是面向对象编程的关键特性,通过将对象的状态(数据)和行为(方法)结合并利用访问控制保护数据,防止外部随意访问和修改。主要特点包括访问控制(如 `private` 和 `protected`)、数据隐藏及方法暴露(如 getter 和 setter)。封装的优点在于保护数据、隐藏实现细节、易于维护以及提高代码可读性。下面是一个简单的 `Person` 类封装示例,展示了如何通过 getter 和 setter 控制对类内部状态的访问,并进行合法性检查。总结而言,封装有助于构建清晰、易用且可维护的代码结构,是编写高质量 Java 程序的重要原则。
|
3天前
|
Java
java的class类
java的class类
15 5
|
2天前
|
Java
Java 多态趣解
在一个阳光明媚的午后,森林中的动物们举办了一场别开生面的音乐会。它们组成了一支乐队,每种动物都有独特的演奏方式。通过多态的魅力,狗、猫和青蛙分别展示了“汪汪”、“喵喵”和“呱呱”的叫声,赢得了观众的阵阵掌声。熊指挥着整个演出,每次调用 `perform()` 方法都能根据不同的动物对象唤起对应的 `makeSound()` 方法,展现了 Java 多态性的强大功能,让整场音乐会既有趣又充满表现力。
|
2天前
|
Java
Java 的继承
在一个森林中,各种动物共存,如狗和猫。为了管理和组织这些动物,我们采用面向对象的方法设计模型。首先创建 `Animal` 超类,包含 `name` 和 `age` 属性及 `makeSound()` 和 `displayInfo()` 方法。接着,通过继承 `Animal` 创建子类 `Dog` 和 `Cat`,重写 `makeSound()` 方法以发出不同的声音。实例化这些子类并使用它们,展示了继承带来的代码重用、扩展性和多态性等优点。这种方式不仅简化了代码,还体现了现实世界的层次结构。
|
3天前
|
Java 数据处理
Java Scanner 类详解
`Scanner` 类是 Java 中 `java.util` 包提供的强大工具,用于从多种输入源(如键盘、文件、字符串)读取数据。本文详细介绍如何创建 `Scanner` 对象并使用其常用方法(如 `next()`, `nextInt()`, `nextLine()` 等)。通过示例代码展示如何从标准输入、字符串及文件中读取数据,并进行输入验证。使用时需注意关闭 `Scanner` 以释放资源,并确保输入类型匹配,避免异常。掌握 `Scanner` 可显著提升程序的数据处理能力。
|
9天前
|
安全 Java
Java StringBuffer 和 StringBuilder 类详解
在 Java 中,`StringBuffer` 和 `StringBuilder` 用于操作可变字符串,支持拼接、插入、删除等功能。两者的主要区别在于线程安全性和性能:`StringBuffer` 线程安全但较慢,适用于多线程环境;`StringBuilder` 非线程安全但更快,适合单线程环境。选择合适的类取决于具体的应用场景和性能需求。通常,在不需要线程安全的情况下,推荐使用 `StringBuilder` 以获得更好的性能。