Java基础知识宝典(三)-只提供相关操作-供勾勒回忆-建议收藏(持续更新,一直到spring、springboot、mybatis、redis、mysql、消息队列、netty、微服务等等知识完结)

前言

本笔记旨在系统整理 Java 语法 中的重要知识点,涵盖各个方面的核心内容,从最原始的基础知识 到 -> 进阶API 到-> 框架API到->数据库API 到->中间件API到-> GitAPI``到-> 微服务 Linux API到->项目上线以及云服务API
通过表格与代码示例相结合的方式,帮助你快速查阅与理解常见的语法与用法。免去遗忘之苦。

只提供相关操作-供勾勒回忆-建议收藏(持续更新,一直到spring、springboot、mybatis、redis、mysql、消息队列、netty、微服务等等知识完结)

本文档适合作为 Java 速查手册,也可作为复习与面试准备的参考资料。 建议收藏。 左侧有目录


U14 ~ 抽象类

一、定义与命名建议

项目说明
定义方式使用 abstract class ClassName { ... } 来声明抽象类
命名建议常用 AbstractXxx 前缀(例如 AbstractPlayer),便于识别其抽象与基类角色
是否可实例化不能直接 new AbstractClass()(编译错误)

二、抽象类内部主要特征

特征说明
抽象方法abstract 方法没有方法体,子类必须实现(除非子类也声明为 abstract
普通方法抽象类可以包含具备实现的方法(供子类复用)
字段与构造器抽象类可以有字段和构造器,子类通过 super(...) 调用父类构造器
继承关系抽象类通过 extends 被继承,常用于定义模板或公用行为
接口对比抽象类可包含(字段)和具体实现;接口的话通常更轻

三、使用规则

规则 / 建议说明
子类实现非抽象子类必须实现父类所有抽象方法
多重继承Java 不支持类的多重继承(抽象类亦然),可通过接口组合行为
设计用途用于“部分实现 + 规范(abstract 方法)”的场景:把共性放到抽象类,把差异留给子类实现
API 设计若需要共享(字段)状态或公共方法实现且希望强制子类实现某些方法,选用抽象类;若只是规范(无状态(字段)),优先考虑接口

四、示例(完整代码)

下面示例展示一个抽象类 AbstractPlayer,含抽象方法 play() 和普通方法 sleep();两个具体子类 BasketballPlayer / FootballPlayer 实现 play()Demo 演示如何使用。

// 抽象基类
public abstract class AbstractPlayer {
	int age = 18;
	
    // 抽象方法:子类必须实现
    abstract void play();

    // 普通方法:子类可以直接继承使用
    public void sleep() {
        System.out.println("就算"+age+"岁运动员也要休息,而不是挑战极限。");
    }
}

// 具体子类:长跑运动员
class RunningPlayer extends AbstractPlayer {
    @Override
    void play() {
        System.out.println("开跑开跑 1万米!");
    }
}

// 具体子类:足球运动员
class FootballPlayer extends AbstractPlayer {
    @Override
    void play() {
        System.out.println("进攻 破门 守门。");
    }
}

// 测试类:展示创建子类实例并调用方法
public class Demo {
    public static void main(String[] args) {
        AbstractPlayer p1 = new RunningPlayer ();
        p1.play();   // 输出:开跑开跑 1万米!。
        p1.sleep();  // 输出:就算18岁运动员也要休息,而不是挑战极限。

        AbstractPlayer p2 = new FootballPlayer();
        p2.play();   // 输出:进攻 破门 守门。
        p2.sleep();  // 输出:就算18岁运动员也要休息,而不是挑战极限。
    }
}

U15 ~ 接口(重中之重: 一个项目 不可能离开接口)

1. 接口定义核心要点

类别核心内容说明与示例
定义关键字interface示例:public interface Electronic {}
成员特性变量隐式public static final(常量),值不可改;示例:String LED = "LED";
抽象方法隐式public abstract(无方法体);示例:int getElectricityUse();
静态方法(Java 8+)需显式static,通过接口名调用;示例:static boolean isEnergyEfficient(...)
默认方法(Java 8+)需显式default,有方法体(默认实现);示例:default void printDescription() {}
关键注意事项实例化限制接口不能直接实例化,需通过实现类实例化(Electronic e = new Computer();
空接口可无任何成员,仅作标记;示例:Serializable接口(序列化标记)
修饰符限制接口不能用final;抽象方法不能用private/protected/final

2. 接口的核心作用

作用类别核心说明示例代码片段
标记功能为类赋予特定能力(实现接口即具备对应功能)实现Cloneable接口可使用clone()方法:
class CloneableTest implements Cloneable { @Override protected Object clone() {} }
实现多重继承解决Java单继承限制,一个类可实现多个接口Pig类同时实现FlyRun接口:
class Pig implements Fly, Run { @Override public void fly() {} @Override public void run() {} }
实现多态同一行为在不同对象上有不同结果(需满足3前提:接口实现、方法重写、父类引用指向子类)Shape接口多态:
List<Shape> shapes = new ArrayList<>();
shapes.add(new Circle()); shapes.add(new Square());(遍历调用name()输出不同结果)

3. 接口的三种常用设计模式

模式名称设计思想核心实现(代码简化)应用场景
策略模式封装一组算法,通过接口统一调用,算法可灵活替换1. 定义Coach接口(void defend();
2. 实现类Hesai(防守策略1)、Guatu(防守策略2)
3. 调用:defend(new Hesai()); defend(new Guatu());
多种算法切换(如不同支付方式、排序算法)
适配器模式通过抽象类转接接口,避免实现类必须重写接口所有方法1. 定义Coach接口(defend(); attack();
2. 抽象适配器AdapterCoach(空实现接口方法)
3. 实现类Hesai继承适配器,仅重写defend()
接口方法过多,仅需使用部分方法时
工厂模式按“工厂-产品”对应关系,通过工厂接口创建产品接口实例,解耦创建与使用1. 产品接口Coach,工厂接口CoachFactorycreateCoach();
2. ACoachFactory创建ACoachCCoachFactory创建CCoach
3. 调用:create(new ACoachFactory());
批量创建同类型对象(如不同等级的服务实例)

4. 抽象类与接口的区别

对比维度抽象类(abstract class接口(interface
定义关键字abstract classinterface
成员变量支持任意类型(无隐式修饰)仅支持public static final(隐式)
方法类型可包含抽象方法、具体方法(有方法体)、静态方法Java 8前:仅抽象方法;Java 8+:可包含抽象方法、静态方法、默认方法(有方法体)
继承/实现数量一个类仅能继承1个抽象类一个类可实现多个接口
静态代码块支持定义静态代码块不支持静态代码块
设计关系is-a关系(子类是抽象类的具体类型,如“Bird是Animal”)has-a关系(类具备接口的行为,如“Bird具备Fly行为”)
变更影响新增方法可提供默认实现,子类无需修改新增方法(非默认/静态)时,所有实现类必须重写该方法

实例展示(形状接口+圆规类和矩形类)

// 定义一个形状接口
public interface Shape {
    // 常量 - 隐式为public static final
    String UNIT = "厘米";
    
    // 抽象方法 - 隐式为public abstract
    double calculateArea();  // 计算面积
    double calculatePerimeter();  // 计算周长
    
    // 默认方法 (Java 8+)
    default void printInfo() {
        System.out.println("这是一个形状,单位:" + UNIT);
    }
    
    // 静态方法 (Java 8+)
    static void printShapeType(Shape shape) {
        System.out.println("形状类型:" + shape.getClass().getSimpleName());
    }
}
--------------------------------------
// 实现Shape接口的圆形类
public class Circle implements Shape {
    private double radius;  // 半径
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    // 实现接口的抽象方法
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
    
    // 可以重写默认方法
    @Override
    public void printInfo() {
        System.out.println("这是一个圆形,半径:" + radius + UNIT);
    }
}
-------------------------------------------
// 实现Shape接口的矩形类
public class Rectangle implements Shape {
    private double length;  // 长度
    private double width;   // 宽度
    
    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    
    // 实现接口的抽象方法
    @Override
    public double calculateArea() {
        return length * width;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * (length + width);
    }
}
-------------------------
// 测试类
public class InterfaceDemo {
    public static void main(String[] args) {
        // 接口不能直接实例化,只能通过实现类实例化
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);
        
        // 调用实现的方法
        System.out.println("圆形面积:" + circle.calculateArea());
        System.out.println("矩形周长:" + rectangle.calculatePerimeter());
        
        // 调用默认方法
        circle.printInfo();
        rectangle.printInfo();
        
        // 调用静态方法
        Shape.printShapeType(circle);
        Shape.printShapeType(rectangle);
    }
}

U16 ~四种内部类(匿名内部类用的比较多)

类别定义特点访问外部类成员实例化方式
成员内部类定义在外部类成员位置,无static修饰可直接访问外部类实例.new 内部类()
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
静态内部类定义在外部类成员位置,有static修饰只能访问静态成员外部类.内部类 变量 = new 外部类.内部类()
Outer.StaticInner inner = new Outer.StaticInner();
局部内部类定义在外部类方法或代码块中可访问final/effectively final局部变量方法内部直接实例化:Inner inner = new Inner();(仅方法内可见)
匿名内部类无类名的局部内部类,直接继承父类或实现接口同局部内部类接口/父类 变量 = new 接口/父类() { 实现代码 };

U17 ~ Java 面向对象三大特性

一、封装

要点
定义将数据(字段)与对数据的操作(方法)组合到类中,并隐藏内部实现细节,只暴露受控的接口(如 getter/setter)。
目的降低耦合、保护数据一致性、便于修改实现、控制访问权限。
常用做法将字段 private,通过 public / protected 方法访问;在 setter 中加入校验逻辑。
好处更安全(可校验/限制输入)、易维护(内部实现可变而接口不变)、更可靠(防止外部随意篡改)。
注意不要把所有字段都暴露 getter/setter;应根据设计决定是否暴露、暴露何种语义(例如 getSexName() 而非直接暴露底层编码)。

示例:封装与校验

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

    public Person(String name, int age){
        this.name = name;
        setAge(age); // 通过 setter 统一校验/处理
    }

    public String getName(){ return name; }

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

    public int getAge(){ return age; }

    public void setAge(int age){
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("年龄不合法");
        }
        this.age = age;
    }
}

二、继承

项目要点
定义子类继承父类的属性与方法(非私有的),实现代码复用和行为扩展。
关键字extends(类继承),implements(实现接口,模拟多继承效果)。
Java 继承模型支持 单继承(一个类只能有一个直接父类);通过实现多个接口获得多重行为。
主要用途提取公共行为/属性到超类(基类);子类扩展或重写(override)父类行为。
构造与继承子类构造会先调用父类构造(super()),父类先初始化再初始化子类。
访问规则子类重写时不能缩小父方法的访问权限(可相等或放宽);private 成员不可继承/重写。
覆盖(Override)与重载(Overload)覆盖:方法签名相同,子类提供实现(动态绑定);重载:同名不同参,编译期选择。
分类说明
单继承每个类最多一个直接父类(class Sub extends Super
多层继承A <- B <- C,子类继承链可多层
接口实现(多实现)class C implements I1, I2 支持多接口以弥补类单继承的限制

示例:Animal 继承

class Animal {
    public void eat(){ System.out.println("动物吃"); }
    public void sayHello(){ System.out.println("hello"); }
}

class Dog extends Animal {
    @Override
    public void eat(){ System.out.println("狗吃骨头"); }
    public void bark(){ System.out.println("汪汪"); }
}

class Cat extends Animal {
    @Override
    public void eat(){ System.out.println("猫吃鱼"); }
    public void meow(){ System.out.println("喵喵"); }
}

三、多态

要点
定义相同的消息(方法调用)作用于不同对象时,表现出不同的行为(运行时决定具体实现)。
前提条件1. 有继承关系;2. 子类重写父类方法;3. 父类引用指向子类对象(向上转型)。
类型编译时多态(方法重载)、运行时多态(方法重写 + 动态绑定)。我们通常说的“多态”指运行时多态。
优点可扩展、可替换、降低耦合(通过父类型编程)。
限制父类引用只能访问父类声明的成员(若要访问子类特有方法需向下转型并谨慎)。
动态绑定在运行时根据对象真实类型选择要执行的方法实现(不是根据引用类型)。
构造器中调用多态在父类构造器中调用可被重写的方法会导致子类字段尚未初始化(可能得到意外结果),应谨慎。

示例:多态(数组遍历)

Animal[] animals = { new Animal(), new Dog(), new Cat() };
for (Animal a : animals) {
    a.eat(); // 根据运行时对象类型执行不同实现(Animal/Dog/Cat)
}

向上转型 / 向下转型

Animal a = new Dog(); // 向上转型(隐式)
a.eat(); // 调用 Dog 的 eat()

// 向下转型(需谨慎,可能 ClassCastException)
if (a instanceof Dog) {
    Dog d = (Dog) a;
    d.bark();
}

四、综合示例(封装 + 继承 + 多态)

// 封装:Person 有私有字段和受控 setter
class Person {
    private String name;
    private int age;
    public Person(String name, int age){ setName(name); setAge(age); }
    public String getName(){ return name; }
    public void setName(String name){ this.name = name; }
    public int getAge(){ return age; }
    public void setAge(int age){
        if (age < 0) throw new IllegalArgumentException("age<0");
        this.age = age;
    }
}

// 继承:Employee 扩展 Person
class Employee extends Person {
    public Employee(String name, int age){ super(name, age); }
    public void work(){ System.out.println(getName() + " is working"); }
}

// 多态:通过父类型引用调用子类行为(需方法在父类声明并被重写)
class Animal { public void speak(){ System.out.println("动物叫"); } }
class Dog extends Animal { @Override public void speak(){ System.out.println("汪"); } }
class Cat extends Animal { @Override public void speak(){ System.out.println("喵"); } }

public class Demo {
    public static void main(String[] args){
        // 封装使用
        Person p = new Person("Alice", 30);
        System.out.println(p.getName());

        // 继承/多态
        Animal[] as = { new Animal(), new Dog(), new Cat() };
        for (Animal a : as) a.speak(); // 动态绑定选择实际实现
    }
}

U18 ~ Java注解

Java注解核心知识总结(含创建与使用)

1. 注解基础概念

项目说明
引入版本Java 1.5
本质与class、interface同级的类型,用于装饰程序代码(类、方法、字段等)
核心特点不直接影响代码运行效果,由编译器或自定义逻辑(如反射)决定执行操作
常见示例@Override(方法重写)、@Autowired(Spring依赖注入)

2. 注解生命周期(RetentionPolicy枚举)

生命周期策略生效范围适用场景
SOURCE仅在源文件中有效,编译器处理后丢弃编译期检查(如@Override
CLASS在字节码文件中有效,但JVM运行时丢弃字节码增强(如部分框架优化)
RUNTIME运行时有效,可通过反射访问运行时动态处理(最常用)

3. 注解装饰目标(ElementType枚举)

目标类型适用对象
TYPE类、接口、注解、枚举
FIELD字段(类成员变量)、枚举常量
METHOD方法
PARAMETER普通方法或构造方法的参数
CONSTRUCTOR构造方法
LOCAL_VARIABLE局部变量
ANNOTATION_TYPE注解(用于自定义注解的元注解)
PACKAGE
TYPE_PARAMETER泛型参数
TYPE_USE声明语句、泛型或强制转换语句中的类型
MODULE模块(Java 9+)

4. 自定义注解步骤与说明

步骤操作说明对应代码标识
1. 定义注解结构使用@interface关键字,结合元注解(@Retention、@Target)指定生命周期和目标,定义注解参数如下1
2. 使用自定义注解在目标字段(如Writer类的name、bookName字段)上添加注解,支持显式传参或使用默认值如下2
3. 实现注解逻辑通过反射读取字段上的注解,编写序列化核心逻辑(如判断注解存在、处理字段值、转换JSON格式)如下3
4. 测试注解效果创建测试类,实例化目标对象并调用序列化方法,验证注解是否生效如下4

对应代码展示

如下1:定义自定义注解JsonField
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 指定注解生命周期为运行时(RUNTIME)
@Retention(RetentionPolicy.RUNTIME)
// 指定注解仅用于字段(FIELD)
@Target(ElementType.FIELD)
public @interface JsonField {
    // 定义注解参数,参数名为value,默认值为空字符串
    String value() default "";
}
如下 2:在Writer类中使用JsonField注解
public class Writer {
    // 无@JsonField注解,不参与JSON序列化
    private int age;

    // 显式指定@JsonField参数值为"writerName",序列化后key为"writerName"
    @JsonField("writerName")
    private String name;

    // 使用@JsonField默认值,序列化后key为字段名"bookName"
    @JsonField
    private String bookName;

    // 构造方法:初始化字段值
    public Writer(int age, String name, String bookName) {
        this.age = age;
        this.name = name;
        this.bookName = bookName;
    }

    // getter/setter方法(需手动补充,用于字段值访问)
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getBookName() { return bookName; }
    public void setBookName(String bookName) { this.bookName = bookName; }

    // toString方法:常规对象打印(非序列化逻辑)
    @Override
    public String toString() {
        return "Writer{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", bookName='" + bookName + '\'' +
                '}';
    }
}
如下 3:实现注解逻辑(JsonSerializer序列化类)
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class JsonSerializer {
    // 核心方法:将对象中带@JsonField的字段序列化为JSON字符串
    public static String serialize(Object object) throws IllegalAccessException {
        // 获取对象的Class对象,用于反射操作
        Class<?> objectClass = object.getClass();
        // 存储JSON键值对:key(注解参数/字段名)、value(字段值)
        Map<String, String> jsonElements = new HashMap<>();

        // 遍历对象所有声明字段(包括private字段)
        for (Field field : objectClass.getDeclaredFields()) {
            // 突破private权限限制,允许反射访问字段值
            field.setAccessible(true);
            // 判断字段是否带有@JsonField注解
            if (field.isAnnotationPresent(JsonField.class)) {
                // 获取JSON的key(调用工具方法处理注解参数与字段名)
                String jsonKey = getSerializedKey(field);
                // 获取字段的实际值(强转为String,此处假设字段为字符串类型)
                String fieldValue = (String) field.get(object);
                // 将键值对存入map
                jsonElements.put(jsonKey, fieldValue);
            }
        }

        // 将map转换为标准JSON格式字符串
        return toJsonString(jsonElements);
    }

    // 工具方法:处理JSON的key——注解有值则用注解值,无值则用字段名
    private static String getSerializedKey(Field field) {
        // 获取字段上的@JsonField注解实例
        JsonField jsonField = field.getAnnotation(JsonField.class);
        // 读取注解的value参数值
        String annotationValue = jsonField.value();
        // 注解值为空则返回字段名,否则返回注解值
        return annotationValue.isEmpty() ? field.getName() : annotationValue;
    }

    // 工具方法:将map转换为标准JSON字符串(使用Stream流处理)
    private static String toJsonString(Map<String, String> jsonMap) {
        // 遍历map条目,转换为"key":"value"格式字符串
        String jsonEntries = jsonMap.entrySet()
                .stream()
                .map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"")
                .collect(Collectors.joining(",")); // 用逗号连接所有条目
        // 包裹大括号,形成JSON对象格式
        return "{" + jsonEntries + "}";
    }
}
如下 4:测试注解效果(JsonFieldTest测试类)
public class JsonFieldTest {
    public static void main(String[] args) {
        // 1. 实例化Writer对象,传入字段值
        Writer writer = new Writer(18, "沉默王二", "Web全栈开发进阶之路");
        
        // 2. 调用序列化方法,验证注解效果
        try {
            String jsonResult = JsonSerializer.serialize(writer);
            // 3. 打印序列化结果(预期:age无注解不输出,name映射为writerName,bookName用字段名)
            System.out.println(jsonResult); 
            // 实际输出:{"bookName":"Web全栈开发进阶之路","writerName":"沉默王二"}
        } catch (IllegalAccessException e) {
            // 捕获反射权限异常并打印
            e.printStackTrace();
        }
    }
}

U19 ~ Java 枚举

一、枚举定义与基础语法

项目说明
定义方式使用 enum 关键字:enum Color { RED, GREEN, BLUE }
编译行为编译器将枚举生成 final 类,继承自 java.lang.Enum,自动包含 values()valueOf() 等静态方法
可比较枚举常量是单例,使用 == 比较更安全且高效
用途用于表示一组类型安全的常量(替代整型常量),提高可读性与类型安全
public enum Color {
    RED,
    GREEN,
    BLUE
}

二、有参枚举(带字段与构造器)

项目说明
字段枚举可以定义字段保存附加信息(如描述、代码等)
构造器枚举构造器默认私有,可接收参数初始化字段
方法枚举类型可包含 getter、业务方法,甚至实现接口
public enum PlayerType {
    TENNIS("网球"),
    FOOTBALL("足球"),
    BASKETBALL("篮球");

    private final String name;

    PlayerType(String name) { this.name = name; }

    public String getName() { return name; }
}

三、枚举集合:EnumSet 与 EnumMap

工具说明示例
EnumSet专为枚举设计的高效 Set,通常内部用位向量实现,空间与速度优秀EnumSet<PlayerType> all = EnumSet.allOf(PlayerType.class);
EnumMap专为枚举设计的高效 Map,键类型固定为某枚举,遍历与存取都很快EnumMap<PlayerType, String> map = new EnumMap<>(PlayerType.class);
EnumSet<PlayerType> all = EnumSet.allOf(PlayerType.class);
EnumSet<PlayerType> none = EnumSet.noneOf(PlayerType.class);

EnumMap<PlayerType, String> map = new EnumMap<>(PlayerType.class);
map.put(PlayerType.BASKETBALL, "篮球运动员");
System.out.println(map.get(PlayerType.BASKETBALL));

四、使用枚举实现单例(推荐)

优点说明
线程安全JVM 保证枚举实例在类加载阶段唯一初始化,天然线程安全
序列化安全枚举实例序列化/反序列化始终保持单例(无需 readResolve
防反射攻击通过反射难以创建第二个枚举实例
简洁代码极其简洁明了,推荐用于单例实现
public enum AppConfig {
    INSTANCE;

    private int value;

    public int getValue() { return value; }
    public void setValue(int v) { this.value = v; }

    public void doSomething() {
        System.out.println("执行单例方法");
    }
}

// 使用
AppConfig.INSTANCE.setValue(10);
AppConfig.INSTANCE.doSomething();

五、常用 API 与操作

API / 操作说明
values()返回枚举常量的数组(按声明顺序)
valueOf(String)返回指定名字的枚举常量(名字严格匹配,否则抛 IllegalArgumentException
ordinal()返回枚举常量的序号(从 0 开始) —— 用于排序或存储时要慎用(非稳定语义)
name()返回枚举常量声明时的名字(String)
== 比较推荐使用 == 进行常量比较(安全且高效)
switch 支持枚举可用于 switch 语句的 case 分支
for (PlayerType p : PlayerType.values()) {
    System.out.println(p + " => " + p.getName());
}

PlayerType t = PlayerType.valueOf("TENNIS");

switch (t) {
    case TENNIS: System.out.println("网球"); break;
    case FOOTBALL: System.out.println("足球"); break;
    default: System.out.println("其他");
}


27届双非硕士持续学习 ! 每日更新!
建议收藏 – 持续更新中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值