Java基础---OOP

1. Java面向对象编程简介

1.1 面向对象编程的概念

面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它使用“对象”来设计软件。对象可以包含数据(通常称为属性或字段)和代码(通常称为方法或函数)。OOP的核心思想是将现实世界中的实体抽象成对象,并通过这些对象之间的交互来模拟现实世界的行为。

1.2 面向对象编程的优点

  • 代码重用:通过继承和多态,可以减少重复代码,提高开发效率。
  • 易于维护:封装性使得每个对象都是自包含的,易于维护和修改。
  • 模块化:对象的独立性使得软件更加模块化,易于管理和扩展。
  • 可读性:面向对象的代码通常更接近自然语言,易于理解和阅读。
  • 灵活性:多态性允许使用统一的接口来处理不同类型的对象,增加了代码的灵活性。

1.3 Java中的OOP

Java是一种支持面向对象编程的语言,从设计之初就完全按照面向对象的原则构建。Java的OOP特性包括:

  • 类和对象:Java中一切都是对象,包括基本数据类型。
  • 封装:Java通过访问控制符(public, private, protected)来实现封装,保护对象的内部状态。
  • 继承:Java支持单继承,允许一个类继承另一个类的属性和方法。
  • 多态:Java通过接口和抽象类来实现多态,允许将不同类的对象视为同一类型处理。
  • 抽象:Java允许创建抽象类和接口,它们可以定义不能被实例化的蓝图。
  • 接口:Java中的接口定义了一组方法规范,可以被多个类实现。
  • 异常处理:Java提供了一套异常处理机制,使得错误处理更加结构化和统一。
  • 集合框架:Java提供了一套丰富的集合框架,用于存储和操作对象集合。

这些特性使得Java成为了一种强大且灵活的编程语言,广泛应用于各种软件开发领域。

这个整理和扩展的内容提供了Java面向对象编程简介部分的详细概述。

以下是对Java面向对象编程中的基本面向对象概念的整理和扩展内容:

2. 基本面向对象概念

2.1 类和对象

  • 类(Class):类是现实世界中某些具有共同属性和行为的事物的抽象。它是创建对象的蓝图或模板。
  • 对象(Object):对象是类的实例,具有类定义的属性和行为。对象可以与现实世界中的事物相对应,如一个人、一辆车等。

2.2 封装

  • 封装:封装是将数据(属性)和操作数据的方法组合在一起的过程。它隐藏了对象的内部状态和实现细节,只暴露有限的操作界面。
  • 实现封装:在Java中,通过使用访问修饰符(如private、public)来控制成员变量和方法的可见性,从而实现封装。

2.3 继承

  • 继承:继承是一种机制,允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。
  • 实现继承:Java使用关键字extends来实现继承。子类可以添加新的属性和方法,也可以覆盖父类的方法。
  • 层次结构:继承可以形成层次结构,有助于代码的组织和重用。

2.4 多态

  • 多态:多态是指允许不同类的对象对同一消息做出响应的能力,但具体的行为会根据对象的实际类型而有所不同。
  • 方法重载(Overloading):方法重载是同一个类中具有相同名称但参数不同的方法,它是编译时多态的一种形式。
  • 方法重写(Overriding):方法重写是子类中具有与父类相同名称、参数和返回类型的一个方法,它是运行时多态的一种形式。
  • 接口和抽象类:Java使用接口和抽象类来实现多态。接口定义了方法的签名,而抽象类可以包含部分实现。

这些概念是面向对象编程的核心,它们共同构成了Java中面向对象设计的基础。通过类和对象,我们能够构建复杂的软件系统;通过封装,我们能够保护数据和实现细节;通过继承,我们能够创建层次结构并重用代码;通过多态,我们能够编写灵活且可扩展的代码。

3. Java中的类和对象

3.1 定义类

  • 类的定义:在Java中,使用关键字class来定义一个类。类定义通常包括类名、成员变量(属性)、方法(行为)和构造函数。

  • 类名命名规则:类名通常使用大驼峰式命名法(CamelCase),并且首字母大写。

  • 示例

    public class Car {
        // 成员变量
        private String color;
        private int speed;
    
        // 方法
        public void start() {
            // 启动汽车的代码
        }
    
        // 构造函数
        public Car(String color) {
            this.color = color;
        }
    }
    

3.2 创建对象

  • 创建对象:使用关键字new来创建一个类的实例,也就是对象。

  • 对象引用:创建对象后,会返回一个指向该对象的引用,通常是一个变量。

  • 示例

    Car myCar = new Car("Red");
    

3.3 类的成员变量和方法

  • 成员变量:也称为属性或字段,用于存储对象的状态信息。

  • 方法:也称为函数,定义了对象的行为。方法可以访问和操作类的成员变量。

  • 访问修饰符:成员变量和方法可以使用访问修饰符来控制其可见性(如public, private, protected)。

  • 示例

    public class Person {
        private String name;
        public int age;
    
        public void introduce() {
            System.out.println("Hello, my name is " + name);
        }
    }
    

3.4 构造函数

  • 构造函数:是一种特殊的方法,用于在创建对象时初始化对象的状态。

  • 名称规则:构造函数的名称必须与类名完全相同,并且没有返回类型。

  • 重载构造函数:可以为类定义多个构造函数,只要它们的参数列表不同,这称为构造函数重载。

  • 示例

    public class Book {
        private String title;
        private String author;
    
        // 无参构造函数
        public Book() {
            // 初始化代码
        }
    
        // 有参构造函数
        public Book(String title, String author) {
            this.title = title;
            this.author = author;
        }
    }
    

4. 封装

4.1 访问修饰符:public, private, protected

  • public:当成员变量或方法被声明为public时,它们可以被任何其他类访问,没有访问限制。

    • 示例:

      public class Circle {
          public double radius; // 任何其他类都可以访问radius
      }
      
  • privateprivate成员变量和方法只能在声明它们的类内部访问。这是封装数据的一种方式,防止外部直接访问和修改。

    • 示例:

      public class Circle {
          private double radius; // 只能在Circle类内部访问radius
      
          public double getRadius() {
              return radius;
          }
      
          public void setRadius(double radius) {
              this.radius = radius;
          }
      }
      
  • protectedprotected成员变量和方法可以在声明它们的类中,同一包中的其他类以及任何继承自该类的子类中访问。

    • 示例:

      public class Shape {
          protected double area() {
              // 计算面积的方法
          }
      }
      
      public class Rectangle extends Shape {
          public void printArea() {
              System.out.println(area()); // 子类可以访问protected方法
          }
      }
      

4.2 封装的重要性

封装提供了以下好处:

  • 安全性:通过限制对成员变量的直接访问,可以防止它们被外部代码不当修改。
  • 简化接口:外部代码不需要了解内部实现细节,只需要通过公共接口与对象交互。
  • 灵活性:在不影响使用对象的代码的情况下,可以自由地修改对象的内部实现。
  • 可维护性:封装使得代码更容易理解和维护,因为每个类都封装了特定的功能。

4.3 封装的实现

  • 隐藏内部状态:将成员变量设置为private,防止外部直接访问。
  • 提供公共接口:为每个private成员提供公共的getter和setter方法,允许受控访问。
  • 使用构造函数初始化:通过构造函数为对象的private成员变量提供初始值。
  • 封装行为:将与对象状态相关的操作封装在方法中,这些方法可以访问和修改对象的状态。
  • 不变性:通过只提供getter方法而不提供setter方法,可以创建不可变对象。
  • 封装复杂性:将复杂的逻辑封装在类内部,只暴露简单的接口给外部。

示例:封装一个简单的银行账户类

public class BankAccount {
    private String accountNumber;
    private double balance;

    // 私有构造函数
    private BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        this.balance = initialBalance;
    }

    // 公共静态方法创建账户
    public static BankAccount createAccount(String accountNumber, double initialBalance) {
        return new BankAccount(accountNumber, initialBalance);
    }

    // Getter方法
    public String getAccountNumber() {
        return accountNumber;
    }

    public double getBalance() {
        return balance;
    }

    // Setter方法
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
        }
    }
}

在这个例子中,BankAccount类封装了账户编号和余额,提供了存款和取款的方法,并通过构造函数和静态方法控制对象的创建。这样,外部代码不需要了解账户的内部实现,只需要通过公共接口与账户交互。

封装是Java面向对象编程的一个基本原则,它有助于创建安全、灵活且易于维护的代码。

5. 继承

5.1 继承的概念

继承是面向对象编程的一个核心概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。继承支持代码重用,并可以创建一个类的层次结构。

5.2 父类和子类

  • 父类:也称为基类或超类,是被其他类继承的类。它定义了可以被继承的属性和方法。
  • 子类:也称为派生类,是从父类继承而来的类。子类可以添加新的属性和方法,也可以重写父类的方法。

5.3 方法覆盖/重写(Override)

  • 方法覆盖:子类可以提供一个已在父类中定义的方法的新实现,这称为方法覆盖或重写。
  • 重写规则:为了重写父类的方法,子类中的方法必须具有相同的方法名、返回类型和参数列表。
  • 使用@Override注解:Java提供了@Override注解来明确表示一个方法是重写的父类方法,这有助于编译时错误检查。

5.4 访问父类的方法

  • super关键字:在子类中,可以使用super关键字来访问父类的构造函数或方法。
  • 调用父类构造函数:可以使用super()来调用父类的构造函数,通常在子类的构造函数中进行。
  • 访问父类方法:如果子类重写了父类的方法,仍然可以使用super.methodName()来调用父类中的方法。

5.5 继承的层次结构

  • 继承链:一个类可以作为另一个类的父类,形成一条继承链。
  • 多层继承:Java支持多层继承,一个类可以是多个类的子类。
  • 菱形问题:由于Java不支持多重继承(一个类不能直接继承多个类),所以避免了C++中的菱形继承问题。

示例:使用继承创建一个简单的类层次结构

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

// 子类,继承自Animal
class Dog extends Animal {
    void bark() {
        System.out.println("Dog barks");
    }

    // 重写eat方法
    @Override
    void eat() {
        System.out.println("Dog eats dog food");
    }
}

// 另一个子类,继承自Animal
class Cat extends Animal {
    void meow() {
        System.out.println("Cat meows");
    }

    // 重写eat方法
    @Override
    void eat() {
        System.out.println("Cat eats cat food");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        myAnimal.eat(); // Animal eats food

        Dog myDog = new Dog();
        myDog.bark(); // Dog barks
        myDog.eat(); // Dog eats dog food

        Cat myCat = new Cat();
        myCat.meow(); // Cat meows
        myCat.eat(); // Cat eats cat food

        // 使用super调用父类构造函数和方法
        class Child extends Parent {
            Child() {
                super(); // 调用Parent的构造函数
            }

            void method() {
                super.someMethod(); // 调用Parent的someMethod
            }
        }
    }
}

在这个示例中,Animal类是父类,DogCat类是它的子类。每个子类都有自己的特定行为,并且重写了eat方法。super关键字用于调用父类的方法。

继承是Java面向对象编程中的一个重要特性,它允许开发者创建一个层次结构,其中子类可以扩展和修改父类的行为。

6. 多态

6.1 多态的概念

多态是面向对象编程的一个核心概念,它允许同一个接口接受不同的数据类型。在Java中,多态性主要通过方法重载(overloading)和方法重写(overriding)实现。

  • 编译时多态:通过方法重载实现。当多个方法具有相同的名称但参数类型或数量不同时,编译器根据方法签名(方法名和参数列表)来决定调用哪个方法。
  • 运行时多态:通过方法重写和接口实现实现。当子类重写父类的方法时,运行时Java虚拟机(JVM)会根据对象的实际类型来调用相应的方法。

6.2 方法重载(Overloading)

  • 定义:方法重载发生在同一个类中,当有两个或多个方法具有相同的名称但参数列表不同时。

  • 规则:方法的返回类型可以相同或不同,但参数列表必须不同(参数的数量、类型或顺序至少有一项不同)。

  • 示例

    public class Calculator {
        public int add(int a, int b) {
            return a + b;
        }
    
        public double add(double a, double b) {
            return a + b;
        }
    
        public int add(int a, int b, int c) {
            return a + b + c;
        }
    }
    

6.3 方法重写(Overriding)

  • 定义:子类可以提供一个已在父类中定义的方法的新实现,这称为方法重写。

  • 规则:重写的方法必须具有相同的方法名、返回类型和参数列表。

  • @Override注解:使用@Override注解可以明确表示一个方法是重写的父类方法,有助于编译时错误检查。

  • 示例

    class Animal {
        public void sound() {
            System.out.println("Animal makes a sound");
        }
    }
    
    class Dog extends Animal {
        @Override
        public void sound() {
            System.out.println("Dog barks");
        }
    }
    

6.4 接口和抽象类

  • 接口:接口是一种形式的契约,它定义了一组方法规范,但不需要实现这些方法。任何实现该接口的类都必须提供接口中所有方法的具体实现。
  • 抽象类:抽象类是不能被实例化的类,它可以包含抽象方法(没有实现的方法)和具体方法。抽象类通常用作其他类的基类。
  • 多态性:接口和抽象类在多态性中扮演重要角色,因为它们允许将不同类的对象视为同一类型处理,只要这些类实现了相同的接口或继承自同一个抽象类。

示例:使用接口和抽象类实现多态性

interface Animal {
    void makeSound();
}

class Dog implements Animal {
    public void makeSound() {
        System.out.println("Woof woof");
    }
}

class Cat implements Animal {
    public void makeSound() {
        System.out.println("Meow meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound(); // 输出: Woof woof
        myCat.makeSound(); // 输出: Meow meow

        // 这里展示了运行时多态性,JVM会根据对象的实际类型调用相应的makeSound方法
    }
}

在这个示例中,Animal是一个接口,DogCat类实现了这个接口。main方法中,myDogmyCat都是Animal类型的对象,但JVM在运行时会根据它们实际的类型调用相应的makeSound方法。

多态性是Java中一个强大的特性,它提高了代码的灵活性和可扩展性。

7. 接口和抽象类

7.1 接口的定义和实现

**接口(Interface)**是Java中的一个引用类型,它是一组抽象方法的集合,这些方法没有具体的实现。接口可以被类实现,实现接口的类必须提供接口中所有方法的具体实现。

  • 定义接口:使用interface关键字定义接口。
  • 实现接口:使用implements关键字实现接口。
  • 默认方法:从Java 8开始,接口可以包含具有默认实现的方法,使用default关键字标识。
  • 静态方法:接口也可以包含静态方法,使用static关键字标识。

示例

// 定义接口
interface Vehicle {
    void start();
    void stop();
    default void showInfo() {
        System.out.println("This is a vehicle");
    }
}

// 实现接口
class Car implements Vehicle {
    public void start() {
        System.out.println("Car starts");
    }

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

// 使用接口
Vehicle myCar = new Car();
myCar.start();
myCar.stop();
myCar.showInfo(); // 默认方法

7.2 抽象类的定义

**抽象类(Abstract Class)**是不能被实例化的类,它通常用作基类。抽象类可以包含抽象方法(没有实现的方法)和具体方法。

  • 定义抽象类:使用abstract关键字定义抽象类。
  • 抽象方法:没有方法体的方法,使用abstract关键字标识。
  • 具体方法:抽象类中也可以包含具有实现的方法。

示例

// 定义抽象类
abstract class Animal {
    abstract void makeSound();

    void eat() {
        System.out.println("Animal eats");
    }
}

// 继承抽象类
class Dog extends Animal {
    public void makeSound() {
        System.out.println("Dog barks");
    }
}

// 使用抽象类
Animal myDog = new Dog();
myDog.makeSound();
myDog.eat();

7.3 接口和抽象类的区别

  1. 定义

    • 接口使用interface关键字定义,可以包含默认方法和静态方法。
    • 抽象类使用abstract关键字定义,可以包含抽象方法和具体方法。
  2. 实现

    • 一个类可以实现多个接口。
    • 一个类只能继承一个抽象类。
  3. 构造方法

    • 接口不能有构造方法。
    • 抽象类可以有构造方法。
  4. 字段

    • 接口中的字段默认是public static final的,但Java 8开始可以有默认方法和静态方法。
    • 抽象类可以有各种类型的字段。
  5. 继承

    • 接口本身不能被继承。
    • 抽象类可以被其他类继承。
  6. 主要目的

    • 接口用于定义一个类必须遵循的契约或行为。
    • 抽象类用于共享代码和表示一个不完整的类。
  7. 多态

    • 接口和抽象类都支持多态性,但接口提供了一种更灵活的方式来实现多态。

通过理解接口和抽象类的定义、实现和它们之间的区别,Java开发者可以更有效地设计和实现面向对象的程序。

8. Java注解

8.1 注解的概念

注解(Annotation)是一种特殊的接口,用于为Java代码提供元数据。注解不会改变代码的结构,但可以提供额外的信息给编译器或运行时环境,从而影响代码的处理方式。

  • 标记注解:没有属性,仅用于标记。
  • 单值注解:有一个属性,并且属性值默认为value
  • 元注解:用于注解其他注解的注解,如@Retention@Target@Documented@Inherited

示例:

@Deprecated // 标记注解示例
public class OldClass {
    // ...
}

8.2 Java内置注解

Java提供了一些内置注解,用于不同的用途:

  • @Override:表示当前方法是重写父类的方法。
  • @Deprecated:表示某个元素(类、方法、变量等)已经过时。
  • @SuppressWarnings:告诉编译器忽略特定的警告。
  • @SafeVarargs:从Java 7开始,用于告诉编译器忽略在使用可变参数时可能抛出的unchecked警告。
  • @FunctionalInterface:用于标识一个函数式接口。

示例:

@Override
public void method() {
    // ...
}

@SuppressWarnings("unchecked")
public void methodWithWarning() {
    // ...
}

@FunctionalInterface
interface Callable {
    void call();
}

8.3 自定义注解

开发者可以创建自己的注解,以满足特定的需求。

  • 定义注解:使用@interface关键字定义注解。
  • 元注解@Retention@Target@Documented@Inherited用于定义注解的保留策略、使用目标、是否被文档工具提取、是否被子类继承。
  • 注解方法:注解中的方法相当于注解的属性。

示例:

// 定义自定义注解
public @interface MyAnnotation {
    String value(); // 必须有value方法
    int number() default 1; // 可以有默认值
}

// 使用自定义注解
public class MyClass {
    @MyAnnotation(value = "Example", number = 5)
    public void myMethod() {
        // ...
    }
}

自定义注解可以有属性,并且可以指定属性的默认值。注解的保留策略决定了注解信息在哪些阶段可用(源代码、类文件、运行时)。通过定义注解的使用目标,可以限制注解可以应用于类型、方法、构造函数、成员变量等。

注解是Java提供的一种强大功能,它使得代码更加灵活和可维护。通过注解,开发者可以为代码添加元数据,这些元数据可以在编译时、类加载时或运行时被读取和处理。

9. Java OOP最佳实践

9.1 代码重用

代码重用是面向对象编程的一个关键优势,它可以帮助减少重复代码,提高开发效率。

  • 继承:通过继承现有类,可以重用父类的代码。
  • 组合:使用组合代替继承,可以提供更灵活的代码重用方式。
  • 设计模式:应用设计模式,如工厂模式、单例模式等,可以解决常见问题,实现代码重用。

示例:

class Vehicle {
    void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    void drive() {
        System.out.println("Car drives");
    }
}

// 使用组合
class Car {
    private Engine engine;

    Car(Engine engine) {
        this.engine = engine;
    }

    void drive() {
        System.out.println("Car drives");
    }
}

9.2 代码封装

封装是将数据和操作数据的方法组合在一起,并隐藏内部实现细节。

  • 访问修饰符:使用privateprotectedpublic来控制成员的可见性。
  • Getter和Setter:为私有成员提供公共的getter和setter方法,以受控的方式访问和修改数据。
  • 不变性:通过不提供setter方法或使类不可变,可以创建不可变对象。

示例:

class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    // 没有setter方法,age不可变
}

9.3 代码维护

良好的代码维护实践可以帮助保持代码的可读性和可维护性。

  • 文档:编写清晰的文档和注释,说明类的用途和方法的行为。
  • 模块化:将代码分解为模块,每个模块负责一个特定的功能。
  • 重构:定期重构代码,以改进设计、提高性能或适应新的需求。

示例:

/**
 * Represents a user account.
 */
class Account {
    // ...
    public void deposit(double amount) {
        // ...
    }
    // ...
}

9.4 代码测试

测试是确保代码质量和正确性的关键步骤。

  • 单元测试:对代码的最小可测试单元进行检查,确保它们按预期工作。
  • 集成测试:测试模块之间的交互,确保它们协同工作。
  • 测试驱动开发(TDD):先编写测试用例,然后编写满足测试的代码。

示例:

public class CalculatorTest {
    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();
        assertEquals(5, calculator.add(2, 3));
    }
}

遵循Java OOP最佳实践可以帮助开发者创建可重用、封装良好、易于维护和测试的代码。这些实践不仅提高了代码质量,还有助于团队协作和项目的长期成功。

10. 案例研究

10.1 实际案例分析

实际案例分析通常涉及对一个现实世界问题或现有系统的深入研究,以展示面向对象设计和编程的实际应用。

  • 问题定义:明确问题的范围和需求。
  • 系统设计:使用面向对象的概念设计系统架构。
  • 类和对象的识别:识别现实世界中的实体,并将它们映射为系统中的类和对象。
  • 实现和测试:实现设计并进行测试,确保系统满足需求。

示例:

假设我们要设计一个图书馆管理系统,我们可以从分析图书馆的基本组成部分开始,如书籍、会员、借阅记录等,并将它们转化为系统中的类。

10.2 面向对象设计原则

面向对象设计原则是一组指导原则,用于指导开发者创建灵活、可维护和可扩展的面向对象系统。

  • 单一职责原则:一个类应该只有一个引起它变化的原因。
  • 开放-封闭原则:类应该对扩展开放,对修改关闭。
  • 里氏替换原则:子类对象应该能够替换其父类对象被使用。
  • 接口隔离原则:不应该强迫客户依赖于它们不使用的方法。
  • 依赖倒置原则:高层模块不应该依赖于低层模块,两者都应该依赖于抽象。
  • 最少知识原则:一个对象应该对其他对象有尽可能少的了解。

示例:

在设计一个电子商务平台时,我们可以遵循单一职责原则,为产品管理、订单处理、用户认证等创建不同的类和模块。

10.3 面向对象设计模式应用

面向对象设计模式是解决特定问题的模板,它们在软件开发中广泛应用。

  • 创建型模式:如单例模式、工厂模式、建造者模式等,用于对象创建。
  • 结构型模式:如适配器模式、装饰器模式、代理模式等,用于对象组合。
  • 行为型模式:如策略模式、观察者模式、命令模式等,用于对象间的交互。

示例:

假设我们需要设计一个支持多种支付方式的在线支付系统,我们可以使用工厂模式来创建不同类型的支付对象,使用策略模式来允许用户在不同的支付策略之间选择。

综合案例分析:

考虑一个简单的银行系统,我们需要设计一个可以处理账户、交易和用户信息的系统。

  • 识别实体:识别出Account(账户)、Customer(客户)、Transaction(交易)等实体。
  • 应用设计原则:为每个类确保单一职责,使用依赖倒置原则来降低模块间的耦合。
  • 设计模式应用:使用工厂模式创建不同类型的账户,使用策略模式来处理不同的交易类型。

通过案例研究,我们可以更好地理解面向对象设计的实际应用,以及如何将理论和原则应用于解决现实世界的问题。这有助于提高我们的软件设计和开发能力。

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值