Java中的面向对象(OOP)

本文讲解了Java中的面向对象编程,涉及类、对象、封装、继承、多态和抽象的概念,以及如何在实际项目中应用这些概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概念

        面向对象 Object-Oriented Programming, 作为Java编程语言的核心思想,其实就是将现实世界中的事物抽象成对象, 并通过对象之间的交互来实现程序的功能。

        1.1万事万物皆对象

                Java语言的一种设计理念,在Java编程中,几乎所有的事物都可以被视为对象。每个对象都有自己的状态(即属性)和行为(即方法)。例如,一个人(Person)可以被看作是一个对象,他有姓名、年龄、性别等状态,有吃饭、睡觉、工作等行为。

        在Java中,基本数据类型(如int、float、char等)是一个例外,它们不是对象。但是,为了能够将这些基本类型也当作对象处理,Java为每个基本数据类型都提供了一个包装类(如Integer、Float、Character等)。

        此外,Java中的类(Class)本身也是对象。每个类都是java.lang.Class类的一个实例。例如,如果你有一个名为Person的类,那么Person.class就是一个Class类的实例。

这种"万事万物皆对象"的设计理念,使得Java编程更加灵活和统一,可以更好地利用面向对象的特性(如封装、继承、多态)来设计和实现代码。

2.面向对象的三个基本概念

        2.1 类(class):类是对象的模板或蓝图。定义了一组对象的属性和行为。属性是类的状态的一部分,通常用变量来表示;行为则是类可以执行的操作,通常用方法来表示。例如,我们可以定义一个“学生”类,其中包含“姓名”、“年龄”等属性和“学习”、“睡觉”等行为。

        2.2 对象:对象是类的实例。当我们根据类创建一个对象时,该对象将具有类定义的所有属性和行为。每个对象都有自己的状态(即属性的值),但它们共享相同的行为(即方法)。例如,我们可以创建一个名为"小明"的学生对象。

        2.3 继承:继承是面向对象编程的一个重要特性,允许我们创建一个新的类,继承现有类的属性和行为,并可以添加新的属性和行为。这样,我们可以重用现有类的代码,避免重复编写相同的代码。例如,我们可以创建一个“大学生”类,继承“学生”类,并添加“参加社团活动”的行为。

3.详解四大特征

        3.1封装

               封装:一种将类的实现细节隐藏起来,只暴露公共接口的机制。Java 中可以使用访问控制符(public、private、protected)来控制类的成员的可见性,从而实现封装。主要目的是保护对象内部的状态数据。通过封装,我们可以隐藏对象的内部细节,只提供一个公开的接口供外部访问。

        3.1.1 基本的封装

我们定义一个Person类,将其属性nameage设置为私有(private),并通过公开的getNamesetNamegetAgesetAge方法来访问和修改这些属性。

public class Person {

    //封装属性,只通过get set方法来访问
    private String name;
    private int 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;
    }

}

        3.1.2 封装和数据验证

我们可以在setAge方法中添加数据验证的逻辑,确保age的值在合理的范围内。

public class Person {
    private String name;
    private int age;

    // ...

    public void setAge(int age) {
        if (age >= 0 && age <= 120) {
            this.age = age;
        } else {
            throw new IllegalArgumentException("年龄必须在0到120之间");
        }
    }
}

        3.1.3 封装和计算属性

我们可以定义一个Rectangle类,其属性widthheight是私有的,但我们可以提供一个公开的getArea方法来计算矩形的面积。

public class Rectangle {
    private double width;
    private double height;

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }

    public double getArea() {
        return width * height;
    }
}

        3.1.4 封装集合

public class CustomList {
    private List<Object> list = new ArrayList<>();

    public void addItem(Object item) {
        list.add(item);
    }

    public void removeItem(Object item) {
        list.remove(item);
    }
}

        这个CustomList类是对ArrayList的一个简单封装。在这个类中,我们定义了一个私有的ArrayList对象list,这个list对象是这个类的内部状态,外部代码不能直接访问。

        然后,我们为这个类定义了两个公开的方法:addItemremoveItem。这两个方法是这个类对外提供的接口,外部代码可以通过这两个方法来操作list对象,添加或删除元素。

        这样,我们就隐藏了ArrayList的具体实现细节,比如元素是如何存储的,如何实现添加和删除操作的等等。外部代码只需要知道如何使用addItemremoveItem这两个方法,就可以操作list对象,而不需要了解ArrayList的具体实现。

        这就是封装的主要思想:隐藏对象的内部状态(内部状态其实就是这个类的属性)和实现细节,只提供一个公开的接口供外部代码访问。这样可以使代码更容易理解和使用,也可以保护对象的内部状态不被外部代码错误地修改。

        3.1.5 封装数据库操作

封装数据库的增删改查操作,提供简单的接口,使得使用者不需要了解SQL语句的具体写法。

public class DatabaseHelper {
    private Connection connection;

    public DatabaseHelper(Connection connection) {
        this.connection = connection;
    }

    public ResultSet query(String sql) {
        // 执行SQL查询并返回结果集
    }

    public int update(String sql) {
        // 执行SQL更新并返回影响的行数
    }

    // 其他数据库操作...
}

3.1.6 封装网络请求

封装HTTP的GET和POST请求,提供简单的接口,使得使用者不需要了解HTTP协议的具体细节。

public class HttpClient {
    public String get(String url) {
        // 发送GET请求并返回响应内容
    }

    public String post(String url, String body) {
        // 发送POST请求并返回响应内容
    }
}

        这个HttpClient类是对HTTP GET和POST请求的一个封装。在这个类中,我们定义了两个公开的方法:getpost。这两个方法是这个类对外提供的接口,外部代码可以通过这两个方法来发送HTTP请求。

        在get方法中,我们将实现发送HTTP GET请求的逻辑,并返回响应内容。在post方法中,我们将实现发送HTTP POST请求的逻辑,并返回响应内容。这些具体的实现逻辑可能涉及到HTTP协议的很多细节,比如如何构造请求头,如何编码请求体,如何解析响应等等。

        但是,对于使用这个HttpClient类的代码来说,它不需要了解这些细节。它只需要知道如何使用getpost这两个方法,提供正确的URL和请求体,就可以发送HTTP请求并获取响应。

        这就是封装的主要思想:隐藏实现的复杂性,只提供一个简单的接口供外部代码使用。这样可以使代码更容易理解和使用,也可以降低代码之间的耦合度,提高代码的可维护性。

3.2继承

继承是一种通过已有类创建新类的机制。通过继承,新类可以继承已有类的属性和方法,也可以在此基础上进行扩展和重载。

// 父类
public class Animal {
    public void eat() {
        System.out.println("Animal eats...");
    }
}

// 子类
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("Dog eats...");
    }
}

例子中,Dog类继承了Animal类,同时重写了eat方法。

注意:

一个类继承另一个类并不必须重写父类的所有方法。实际上,继承的主要目的就是为了复用父类的代码。当子类继承父类时,子类会自动拥有父类的所有属性和方法,除非子类显式地重写了父类的某个方法。

以下是几种可能的情况,子类可以不重写父类的方法:

  1. 子类需要父类的功能并且没有特殊的需求。在这种情况下,子类可以直接使用父类的方法,无需重写。

  2. 子类只需要重写父类的部分方法。如果子类只需要修改父类的部分行为,那么子类只需要重写那部分方法,其他方法可以保持不变。

  3. 子类需要扩展父类的功能。在这种情况下,子类可以添加新的方法,而不是重写父类的方法。

只有当子类需要改变父类的某个方法的行为时,才需要重写这个方法。重写父类的方法是面向对象编程中的一个重要特性,它允许子类在继承父类的同时,也可以定制自己的行为。

3.3多态

        3.3.1 多态:多种形态

        3.3.2 多态的表现方式

                ①方法的重写(Override):子类可以重写父类的方法,当通过父类引用调用这个方法时,实际执行的是子类的方法。这就是所谓的"运行时多态"或"动态绑定"。

                ②接口的实现:一个类可以实现一个或多个接口,然后通过接口引用调用接口中定义的方法,实际执行的是类的方法。

                ③类的多态性:一个引用变量可以指向任何类型的对象,只要这个对象的类型是引用变量的类型,或者是它的子类或实现的接口。这样,引用变量就可以在运行时动态地指向不同类型的对象,实现不同的行为。

public class Main {
    public static void main(String[] args) {
        // 父类引用指向子类对象,实现多态
        Animal animal = new Dog();
        // 调用的是Dog的eat方法
        animal.eat();
    }
}

例子中,虽然animal的静态类型是Animal,但是它的动态类型是Dog,因此调用的是Dogeat方法,这就是多态

3.4抽象

在Java中,指把一类事物的共同特性总结出来,形成类。

抽象可以分为两个层次:类的抽象和方法的抽象。

3.4.1 类的抽象

        定义抽象类。抽象类是一种特殊的类,它不能被实例化,只能被继承。抽象类通常包含一些抽象方法,这些方法只有声明,没有具体的实现。

3.4.2 方法的抽象

        定义抽象方法。抽象方法是一种特殊的方法,它只有声明,没有具体的实现。抽象方法必须在抽象类或者接口中定义,子类或者实现类必须实现这个抽象方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值