当前位置:首页 > 随笔 > 正文内容

Java面向对象编程核心概念详解

访客 随笔 2026年6月30日 1

面向对象编程基础

Java是一种支持面向对象编程(OOP)的语言,其核心理念是将现实世界中的事物抽象为程序中的对象。每个对象都包含数据(属性)和行为(方法)两部分。

面向对象的本质在于:以类的形式组织代码结构,以对象的形式封装数据信息。

面向对象的三大特性

封装

封装是将对象的属性和行为捆绑在一起,对外只暴露必要的接口,隐藏内部实现细节。这种机制有效保护了对象的内部状态,防止外部代码随意修改。

封装的优势:

  • 提高数据安全性
  • 隐藏实现细节
  • 增强代码可维护性

class Employee {
    private String employeeName;  // 私有属性,外部无法直接访问
    
    // 公开方法,提供受控的访问方式
    public void setName(String name) {
        this.employeeName = name;
    }
    
    public String getName() {
        return employeeName;
    }
}
// employeeName 变量被声明为 private,外部无法直接访问
// 必须通过 setName() 和 getName() 方法进行间接操作

继承

继承允许子类获取父类的属性和方法,实现代码的复用和扩展。通过继承,可以建立类之间的层次关系。

继承的优势:

  • 减少代码重复
  • 提高代码可维护性
  • 增强代码扩展性

// 父类
class Vehicle {
    void move() {
        System.out.println("交通工具在移动");
    }
}

// 子类继承 Vehicle
class Car extends Vehicle {
    void honk() {
        System.out.println("汽车按喇叭");
    }
}

public class Test {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.move();  // 继承自父类的方法
        myCar.honk();  // 子类特有的方法
    }
}
// Car 类继承 Vehicle 类,因此可以使用 move() 方法

多态

多态是指同一个方法在不同对象上可以表现出不同的行为。它允许使用父类类型的引用指向子类对象,提高代码的灵活性和可扩展性。

多态的优势:

  • 提高代码灵活性
  • 增强代码可维护性
  • 实现接口与实现的分离

class Shape {
    void draw() {
        System.out.println("绘制图形");
    }
}

class Circle extends Shape {
    void draw() {
        System.out.println("绘制圆形");
    }
}

class Square extends Shape {
    void draw() {
        System.out.println("绘制正方形");
    }
}

public class Test {
    public static void main(String[] args) {
        Shape myShape = new Circle(); // 父类引用指向子类对象
        myShape.draw(); // 调用 Circle 类的 draw 方法
    }
}
// Shape 是父类,Circle 和 Square 继承它,并重写了 draw() 方法

方法调用机制

Java中的方法调用分为两种情况:静态方法和实例方法。

静态方法调用

静态方法(使用 static 关键字修饰)属于类本身,不需要创建对象即可调用。


class Calculator {
    // 静态方法
    static int multiply(int a, int b) {
        return a * b;
    }
}

public class Test {
    public static void main(String[] args) {
        int result = Calculator.multiply(5, 3); // 直接通过类名调用
        System.out.println("结果: " + result);
    }
}
// 静态方法中不能使用 this 关键字

实例方法调用

实例方法属于对象,必须先创建对象才能调用。


class Student {
    // 实例方法
    void introduce() {
        System.out.println("大家好,我是学生!");
    }
}

public class Test {
    public static void main(String[] args) {
        Student s = new Student();  // 先创建对象
        s.introduce();             // 通过对象调用方法
    }
}

参数传递机制

Java中的参数传递都是值传递,但根据参数类型不同,表现出不同的行为。

基本类型参数传递

当参数是基本类型时,传递的是值的副本,方法内修改不会影响原始变量。


class Test {
    static void modifyValue(int num) {
        num = 10; // 修改的是 num 的副本
    }

    public static void main(String[] args) {
        int a = 5;
        modifyValue(a);
        System.out.println(a); // 输出:5(a 没有被修改)
    }
}

对象引用参数传递

当参数是对象时,传递的是对象引用的副本,方法内通过引用修改对象内容会影响原始对象。


class Book {
    String title;
}

class Test {
    static void changeBookTitle(Book b) {
        b.title = "Java编程思想"; // 修改对象属性
    }

    public static void main(String[] args) {
        Book myBook = new Book();
        myBook.title = "Java核心技术";

        changeBookTitle(myBook);
        System.out.println(myBook.title); // 输出:Java编程思想
    }
}

构造方法详解

构造方法是Java中一种特殊的方法,用于在创建对象时初始化对象状态。构造方法名称必须与类名相同,且没有返回值类型。

构造方法的特点

  • 名称必须与类名相同
  • 没有返回值类型(不能写void)
  • 在创建对象时自动调用
  • 支持方法重载
  • 如果不定义,系统会提供默认无参构造方法

构造方法分类

无参构造方法


class Person {
    String name;
    
    // 无参构造方法
    public Person() {
        name = "默认姓名";
    }
}

有参构造方法


class Person {
    String name;
    int age;
    
    // 有参构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

this关键字在构造方法中的应用

区分成员变量和参数


class Product {
    String name;
    
    public Product(String name) {
        this.name = name; // 使用 this 区分成员变量和参数
    }
}

调用其他构造方法


class User {
    String username;
    String email;
    
    // 调用其他构造方法
    public User() {
        this("默认用户", "default@example.com"); // 调用有参构造
    }
    
    public User(String username, String email) {
        this.username = username;
        this.email = email;
    }
}

构造代码块

构造代码块是类中{}包裹的代码,每次创建对象都会执行,且在构造方法之前执行。


class Computer {
    // 构造代码块
    {
        System.out.println("构造代码块执行!");
    }
    
    public Computer() {
        System.out.println("构造方法执行!");
    }
}

public class Main {
    public static void main(String[] args) {
        new Computer();
        new Computer();
    }
}
// 输出:
// 构造代码块执行!
// 构造方法执行!
// 构造代码块执行!
// 构造方法执行!

封装深入理解

封装是面向对象编程的核心概念之一,通过隐藏对象内部细节,仅暴露必要的接口,提高代码的安全性和可维护性。

封装的核心原则:属性私有化,方法公开化(private属性,public方法)。

封装的实现方式


class BankAccount {
    // 1. 将属性私有化
    private String accountNumber;
    private double balance;
    
    // 2. 提供getter和setter方法
    public String getAccountNumber() {
        return accountNumber;
    }
    
    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }
    
    public double getBalance() {
        return balance;
    }
    
    public void setBalance(double balance) {
        if (balance >= 0) { // 添加数据验证
            this.balance = balance;
        } else {
            System.out.println("余额不能为负数!");
        }
    }
    
    // 3. 提供公开的业务方法
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("存款成功,当前余额: " + balance);
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("取款成功,当前余额: " + balance);
        } else {
            System.out.println("取款金额无效或余额不足!");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount();
        account.setAccountNumber("123456789");
        account.setBalance(1000.0);
        account.deposit(500.0);
        account.withdraw(200.0);
        
        // 尝试直接修改余额(不允许)
        // account.balance = -1000; // 编译错误,balance是私有的
    }
}

继承机制详解

继承是面向对象编程的重要特性,允许子类获取父类的属性和方法,建立类之间的层次关系。

继承的基本语法


// 父类(基类)
class Animal {
    String name;
    
    void eat() {
        System.out.println(name + " 在吃东西");
    }
}

// 子类(派生类)
class Bird extends Animal {
    void fly() {
        System.out.println(name + " 在飞翔");
    }
}

// 测试继承
public class Test {
    public static void main(String[] args) {
        Bird bird = new Bird();
        bird.name = "鹦鹉";  // 继承了name属性
        bird.eat();         // 继承了eat()方法
        bird.fly();         // 调用子类自己的方法
    }
}

继承的特点

  • 子类继承父类的public和protected成员
  • Java只支持单继承(一个类只能继承一个父类)
  • 子类可以扩展父类的方法,也可以重写父类的方法
  • 构造方法不会被继承,但子类会调用父类的构造方法

Object类

Object类是Java中所有类的根类,所有类都直接或间接继承自Object类。它位于java.lang包中,无需导入即可使用。

super关键字

super关键字用于子类访问父类的内容,主要有以下用途:

调用父类的构造方法


class Parent {
    Parent() {
        System.out.println("父类无参构造方法");
    }
    
    Parent(String msg) {
        System.out.println("父类有参构造方法:" + msg);
    }
}

class Child extends Parent {
    Child() {
        super("来自Child的问候"); // 调用父类有参构造
        System.out.println("子类构造方法");
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child();
    }
}
// 输出:
// 父类有参构造方法:来自Child的问候
// 子类构造方法

访问父类的成员变量


class Parent {
    int value = 10;
}

class Child extends Parent {
    int value = 20;
    
    void display() {
        System.out.println("子类的value: " + value);       // 访问子类变量
        System.out.println("父类的value: " + super.value); // 访问父类变量
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child();
        c.display();
    }
}
// 输出:
// 子类的value: 20
// 父类的value: 10

调用父类的方法


class Parent {
    void show() {
        System.out.println("父类的方法");
    }
}

class Child extends Parent {
    @Override
    void show() {
        super.show(); // 先调用父类的方法
        System.out.println("子类的方法");
    }
}

public class Main {
    public static void main(String[] args) {
        Child c = new Child();
        c.show();
    }
}
// 输出:
// 父类的方法
// 子类的方法

多态深入理解

多态是面向对象编程的重要特性,允许使用父类类型的引用指向子类对象,并根据实际对象的类型调用相应的方法。

方法重写

方法重写(Override)是指子类对父类继承的方法进行重新定义,以提供更适合子类的实现。

方法重写的规则

  • 方法名相同,参数列表相同
  • 返回值类型:JDK 1.5后可以是父类返回类型的子类
  • 访问权限不能比父类更严格
  • static方法不能被重写(只能隐藏)
  • final方法不能被重写
  • 必须在继承关系中进行

class Vehicle {
    void start() {
        System.out.println("交通工具启动");
    }
}

class Motorcycle extends Vehicle {
    @Override
    void start() {
        System.out.println("摩托车启动:转动钥匙,踩踏板");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("汽车启动:插入钥匙,转动点火开关");
    }
}

public class Test {
    public static void main(String[] args) {
        Vehicle motorcycle = new Motorcycle();
        Vehicle car = new Car();
        
        motorcycle.start(); // 输出:摩托车启动:转动钥匙,踩踏板
        car.start();       // 输出:汽车启动:插入钥匙,转动点火开关
    }
}

instanceof运算符

instanceof是Java中的运算符,用于判断对象是否是指定类或其子类的实例。


class Fruit {}
class Apple extends Fruit {}
class Banana extends Fruit {}

public class Test {
    public static void main(String[] args) {
        Fruit fruit = new Fruit();
        Apple apple = new Apple();
        Fruit appleFruit = new Apple(); // 向上转型
        
        System.out.println(fruit instanceof Fruit);   // true
        System.out.println(apple instanceof Apple);   // true
        System.out.println(apple instanceof Fruit);   // true
        System.out.println(appleFruit instanceof Apple); // true
        System.out.println(fruit instanceof Apple);    // false
    }
}

向下转型

向下转型是将父类引用转换为子类类型,但需要使用instanceof进行检查以确保类型安全。


class Device {
    void powerOn() {
        System.out.println("设备开机");
    }
}

class Smartphone extends Device {
    void makeCall() {
        System.out.println("拨打电话");
    }
}

public class Test {
    public static void main(String[] args) {
        Device device = new Smartphone(); // 向上转型
        device.powerOn(); // 只能调用Device类的方法
        
        // 向下转型
        if (device instanceof Smartphone) {
            Smartphone phone = (Smartphone) device; // 向下转型
            phone.makeCall(); // 现在可以调用Smartphone特有的方法
        }
    }
}

static关键字详解

static关键字用于修饰类的成员,使其属于类而不是实例。

静态变量

静态变量(类变量)被所有实例共享,只有一个副本。


class Counter {
    static int count = 0; // 静态变量
    
    public Counter() {
        count++; // 每次创建对象时增加count
    }
    
    public void getCount() {
        System.out.println("当前count值: " + count);
    }
}

public class Test {
    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = new Counter();
        Counter c3 = new Counter();
        
        c1.getCount(); // 输出:当前count值: 3
        c2.getCount(); // 输出:当前count值: 3
        c3.getCount(); // 输出:当前count值: 3
    }
}

静态方法

静态方法属于类,不依赖于实例,可以通过类名直接调用。静态方法不能访问非静态成员。


class MathUtils {
    static int square(int x) {
        return x * x;
    }
    
    int instanceVar = 10; // 实例变量
    
    static void demo() {
        // System.out.println(instanceVar); // 编译错误:不能访问实例变量
        System.out.println("这是一个静态方法");
    }
}

public class Test {
    public static void main(String[] args) {
        int result = MathUtils.square(5); // 通过类名调用
        System.out.println("5的平方是: " + result);
        
        MathUtils.demo(); // 通过类名调用静态方法
    }
}

静态代码块

静态代码块在类加载时执行,且只执行一次,通常用于初始化静态变量。


class DatabaseConnection {
    static String connectionUrl;
    
    // 静态代码块
    static {
        System.out.println("静态代码块执行,初始化数据库连接");
        connectionUrl = "jdbc:mysql://localhost:3306/mydb";
    }
    
    public static void connect() {
        System.out.println("连接到: " + connectionUrl);
    }
}

public class Test {
    public static void main(String[] args) {
        DatabaseConnection.connect();
        DatabaseConnection.connect();
    }
}
// 输出:
// 静态代码块执行,初始化数据库连接
// 连接到: jdbc:mysql://localhost:3306/mydb
// 连接到: jdbc:mysql://localhost:3306/mydb

静态内部类

静态内部类不依赖于外部类的实例,可以直接创建,只能访问外部类的静态成员。


class OuterClass {
    private static String staticMsg = "这是静态消息";
    private String instanceMsg = "这是实例消息"; // 外部类实例变量
    
    // 静态内部类
    static static InnerClass {
        void displayStaticMsg() {
            System.out.println(staticMsg); // 可以访问外部类的静态成员
            // System.out.println(instanceMsg); // 编译错误:不能访问非静态成员
        }
    }
}

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass inner = new OuterClass.InnerClass();
        inner.displayStaticMsg();
    }
}

抽象类详解

抽象类是不能直接实例化的类,通常用于作为其他类的父类,提供一些通用行为和抽象方法。

抽象类的特点

  • 使用abstract关键字声明
  • 不能直接实例化,只能通过子类实例化
  • 可以包含普通方法和抽象方法(没有方法体)
  • 子类必须实现抽象方法,或者自身也是抽象类
  • 抽象方法只能写在抽象类中

抽象类的示例


// 抽象类
abstract class Shape {
    // 抽象方法(没有方法体,子类必须实现)
    public abstract double calculateArea();
    
    // 普通方法(子类可以直接使用)
    public void display() {
        System.out.println("这是一个图形");
    }
}

// 具体子类
class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
}

public class Test {
    public static void main(String[] args) {
        Shape circle = new Circle(5.0);
        Shape rectangle = new Rectangle(4.0, 6.0);
        
        System.out.println("圆的面积: " + circle.calculateArea());
        System.out.println("矩形的面积: " + rectangle.calculateArea());
        
        circle.display();
        rectangle.display();
    }
}

接口详解

接口是Java中用于定义行为规范的机制,它规定了一组方法,但不提供具体实现。实现接口的类必须提供接口中定义的所有方法。

接口的特点

  • 接口中的方法默认是public abstract
  • 接口中的变量默认是public static final(常量)
  • 类使用implements关键字实现接口
  • 一个类可以实现多个接口
  • Java 8后,接口可以包含default方法和static方法

接口示例


interface Payment {
    // 接口方法默认是 public abstract
    void processPayment(double amount);
    
    // Java 8+ 可以有默认方法
    default void validatePayment() {
        System.out.println("验证支付信息");
    }
    
    // Java 8+ 可以有静态方法
    static void logTransaction(String id) {
        System.out.println("记录交易: " + id);
    }
}

class CreditCardPayment implements Payment {
    @Override
    public void processPayment(double amount) {
        System.out.println("使用信用卡支付: " + amount);
    }
}

class PayPalPayment implements Payment {
    @Override
    public void processPayment(double amount) {
        System.out.println("使用PayPal支付: " + amount);
    }
}

public class Test {
    public static void main(String[] args) {
        Payment creditCard = new CreditCardPayment();
        Payment payPal = new PayPalPayment();
        
        creditCard.processPayment(100.0);
        creditCard.validatePayment();
        
        payPal.processPayment(200.0);
        payPal.validatePayment();
        
        Payment.logTransaction("TX12345"); // 调用接口的静态方法
    }
}

内部类详解

内部类是在一个类的内部定义的类,它可以访问外部类的成员,包括private成员。

内部类的类型

成员内部类


class Outer {
    private String message = "来自外部类的消息";
    
    class Inner {
        void displayMessage() {
            System.out.println(message); // 可以访问外部类的私有成员
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner(); // 通过外部类对象创建内部类对象
        inner.displayMessage(); // 输出:来自外部类的消息
    }
}

静态内部类


class Outer {
    private static String staticMessage = "静态消息";
    private String instanceMessage = "实例消息"; // 外部类实例变量
    
    static class StaticInner {
        void displayStaticMessage() {
            System.out.println(staticMessage); // 可以访问外部类的静态成员
            // System.out.println(instanceMessage); // 编译错误:不能访问非静态成员
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Outer.StaticInner inner = new Outer.StaticInner(); // 直接创建,不需要外部类实例
        inner.displayStaticMessage(); // 输出:静态消息
    }
}

局部内部类


class Outer {
    void display() {
        // 局部内部类,定义在方法内部
        class LocalInner {
            void show() {
                System.out.println("局部内部类");
            }
        }
        
        LocalInner inner = new LocalInner();
        inner.show(); // 输出:局部内部类
    }
}

public class Test {
    public static void main(String[] args) {
        Outer outer = new Outer();
        outer.display();
    }
}

匿名内部类


// 匿名内部类实现接口
interface Greeting {
    void sayHello();
}

public class Test {
    public static void main(String[] args) {
        Greeting englishGreeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("Hello!");
            }
        };
        
        Greeting chineseGreeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("你好!");
            }
        };
        
        englishGreeting.sayHello(); // 输出:Hello!
        chineseGreeting.sayHello(); // 输出:你好!
    }
}

总结

面向对象编程是Java的核心特性,通过封装、继承和多态三大特性,可以构建结构清晰、可维护性高的程序。理解这些概念对于掌握Java编程至关重要。

在实际开发中,合理运用面向对象的思想可以有效地组织代码,提高代码的可重用性和可扩展性。抽象类和接口的使用可以帮助我们更好地设计系统的架构,而内部类则提供了更灵活的代码组织方式。

标签: Javaoop封装

相关文章

可以按小时收费的VPS

很多 VPS 提供商都支持 按小时计费(hourly billing),想短期试用 / 临时搭建节点、测试网络、短期项目等场景非常合适。下面是当前最主流且靠谱的按小时 VPS 选项,分别按不同需求场景整理: 1. Vultr(全球节点,包括日本) 按小时计费 可选机房:东京 / 大阪 / 洛杉矶 / 法兰克福 / 伦敦 … 支持 PayPal(部分情况),但更常用信用卡/PayPal+卡价格参考$...

在 iPhone 上下载国外App

地区/国家限制App Store 会根据 Apple ID 的国家或地区限制应用下载。如果你的 Apple ID 绑定的是中国大陆,就可能无法下载 OpenAI 官方的 ChatGPT 应用,因为它在大陆 App Store 不上架。解决办法:换成美国、加拿大、香港等地区的 Apple ID。或者在现有 Apple ID 上更改地区。注册一个国外 Apple ID(推荐)比如注册 美国区 Appl...

Node.js 中的异步编程:回调与 Promise

Node.js 是一个基于 JavaScript 构建的单线程、非阻塞运行环境,它通过异步编程机制来高效处理多个操作。在执行如文件读取、API 请求或数据库查询等任务时,Node.js 不会等待这些操作完成,而是使用回调函数和 Promise 来避免阻塞主线程。 回调方式实现异步 那么当异步操作完成后,Node.js 如何知道接下来要做什么呢?这就要用到 回调函数(callback)。 回调本质上...

Selenium自动化测试入门指南

Selenium自动化测试入门指南

什么是自动化测试? 自动化测试是指利用软件工具自动执行测试用例,模拟用户操作,如打开网页、点击链接、输入文本等,并验证结果是否符合预期。 其主要优点包括: 大幅减少人工成本 测试速度快 可以在非工作时间运行 支持持续集成和交付 然而,它也存在一些局限性,例如开发成本较高、不适合快速变化的项目、依赖稳定的UI界面等。 自动化测试的应用条件 适合引入自动化测试的情况包括: 手动测试耗时且需要大量...

MariaDB Galera集群故障快速恢复指南

OpenStack控制节点采用三节点MariaDB Galera集群架构。当数据库集群因故障重启时,有时会出现Galera集群无法正常启动的问题。虽然有多种方法可以恢复数据库服务,但如何实现快速启动同时确保数据完整性呢? 通过分析日志发现,MariaDB Galera集群节点宕机时会在日志中输出以下信息: [Note] WSREP: 新集群视图:全局状态: 874d8e7e-5980-11e8-8...

Android 中 EventBus 的通信机制与实现原理深度解析

EventBus 核心设计思想 EventBus 是一个基于观察者模式的事件总线框架,广泛应用于 Android 平台以实现组件解耦。它通过中心化的消息分发机制,使不同层级、不同线程的对象能够以"发布-订阅"方式通信,避免了传统接口回调或广播带来的强依赖问题。 核心角色说明 事件(Event):任意 Java 对象,作为数据载体,如网络状态变更通知、用户登录信息等。 发布者(Publi...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。