第十一篇:复习Java基础

一、什么是Java

1. Java简介

Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。

Java是一种通用的,基于类的,面向对象的编程语言。它是用于应用程序开发的计算平台。因此,Java是快速,安全和可靠的。

Java语言的几种特点:

  1. 一种面向对象的编程语言。
    按照对象集合的方式组织程序是一种面向对象的编程思维。
    面向对象编程的四个主要概念是:抽象化,封装,继承,多态。
  2. 简单
    Java是简单的语言之一,因为它不具有指针,运算符重载,多重继承,显式内存分配等复杂功能。
  3. 分布式
    我们可以使用Java编程语言创建分布式应用程序。远程方法调用和企业Java Bean用于在Java中创建分布式应用程序。Java程序可以轻松地分布在通过Internet连接相互连接的一个或多个系统上。
  4. 多线程
    Java支持多线程。它是Java的一项功能,它允许并发执行程序的两个或更多部分,以最大程度地利用CPU。
  5. 可移植
    众所周知,在一台机器上编写的Java代码可以在另一台机器上运行。Java的平台无关功能,其中可以将其平台无关字节码带到任何平台上执行,从而使Java可移植。

2. Java开发环境配置

留个笔记,直接跳转:https://www.runoob.com/java/java-environment-setup.html

二、Java的基础中的基础

1. Java注释

Java中也支持单行注释以及多行注释,注释中的字符将被Java编译器忽略

// 我是单行注释

/*
我是多行注释
。。。
*/

2. Java标识符

Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。

Java 标识符,有以下几点需要注意:

  • 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始
  • 首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合
  • 关键字不能用作标识符
  • 标识符是大小写敏感的
  • 合法标识符举例:age、$salary、_value、__1_value
  • 非法标识符举例:123abc、-salary

3. Java关键字

Java 关键字。这些保留字不能用于常量、变量、和任何标识符的名称。

访问控制:

关键字说明
private私有的
protected受保护的
public公共的
default默认

类、方法和变量修饰符:

关键字说明
abstract声明抽象
class
extends扩充、继承
final最终值、不可改变的
implements实现(接口)
interface接口
native本地、原生方法(非 Java 实现)
new创建
static静态
strictfp严格浮点、精准浮点
synchronized线程、同步
transient短暂
volatile易失

程序控制语句:

关键字说明
break跳出循环
case定义一个值以供 switch 选择
continue继续
do运行
else否则
for循环
if如果
instanceof实例
return返回
switch根据值选择执行
while循环

异常处理:

关键字说明
assert断言表达式是否为真
catch捕捉异常
finally有没有异常都执行
throw抛出一个异常对象
throws声明一个异常可能被抛出
try捕获异常

基本类型:

关键字说明
boolean布尔型
byte字节型
char字符型
double双精度浮点
float单精度浮点
int整型
long长整型
short短整型

变量引用:

关键字说明
super父类、超类
this本类
void无返回值

4. 变量命名规则

在 Java 中,不同类型的变量(例如实例变量、局部变量、静态变量等)有一些命名规则和约定。

遵循一些基本规则,这有助于提高代码的可读性和维护性。

以下是各种变量命名规则的概述:

  • 使用有意义的名字: 变量名应该具有清晰的含义,能够准确地反映变量的用途。避免使用单个字符或无意义的缩写。

  • 驼峰命名法(Camel Case): 在变量名中使用驼峰命名法,即将每个单词的首字母大写,除了第一个单词外,其余单词的首字母都采用大写形式。例如:myVariableName。

  • 避免关键字: 不要使用 Java 关键字(例如,class、int、boolean等)作为变量名。

  • 区分大小写: Java 是大小写敏感的,因此变量名中的大小写字母被视为不同的符号。例如,myVariable 和 myvariable 是两个不同的变量。

  • 不以数字开头: 变量名不能以数字开头,但可以包含数字。

  • 遵循命名约定: 对于不同类型的变量(局部变量、实例变量、静态变量等),可以采用不同的命名约定,例如使用前缀或后缀来区分。

局部变量:

  • 使用驼峰命名法。
  • 应该以小写字母开头。
  • 变量名应该是描述性的,能够清晰地表示其用途。

实例变量(成员变量):

  • 使用驼峰命名法。
  • 应该以小写字母开头。
  • 变量名应该是描述性的,能够清晰地表示其用途。

静态变量(类变量):

  • 使用驼峰命名法,应该以小写字母开头。
  • 通常也可以使用大写蛇形命名法,全大写字母,单词之间用下划线分隔。
  • 变量名应该是描述性的,能够清晰地表示其用途。

常量:

  • 使用全大写字母,单词之间用下划线分隔。
  • 常量通常使用 final 修饰。

参数:

  • 使用驼峰命名法。
  • 应该以小写字母开头。
  • 参数名应该是描述性的,能够清晰地表示其用途。

类名:

  • 使用驼峰命名法。
  • 应该以大写字母开头。
  • 类名应该是描述性的,能够清晰地表示其用途。

5. 修饰符

Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

  • default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

  • private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

  • public : 对所有类可见。使用对象:类、接口、变量、方法

  • protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

6. 运算符

6.1 算数运算符

算术运算符用在数学表达式中,它们的作用和在数学中的作用一样。下表列出了所有的算术运算符。

表格中的实例假设整数变量A的值为10,变量B的值为20:

操作符描述例子
+加法 - 相加运算符两侧的值A + B 等于 30
-减法 - 左操作数减去右操作数A – B 等于 -10
*乘法 - 相乘操作符两侧的值A * B等于200
/除法 - 左操作数除以右操作数B / A等于2
取余 - 左操作数除以右操作数的余数B%A等于0
++自增: 操作数的值增加1B++ 或 ++B 等于 21
自减: 操作数的值减少1B-- 或 --B 等于 19

6.2 关系运算符

下表为Java支持的关系运算符

表格中的实例整数变量A的值为10,变量B的值为20:

运算符描述例子
==检查如果两个操作数的值是否相等,如果相等则条件为真。(A == B)为假。
!=检查如果两个操作数的值是否相等,如果值不相等则条件为真。(A != B) 为真。
>检查左操作数的值是否大于右操作数的值,如果是那么条件为真。(A> B)为假。
<检查左操作数的值是否小于右操作数的值,如果是那么条件为真。(A <B)为真。
>=检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。(A> = B)为假。
<=检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。(A <= B)为真。

三、Java基础

1. 基本数据类型

1.1 内置数据类型

Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。

  1. byte(整数)
  2. short(整数)
  3. int(整数)我用这个
  4. long(整数)
  5. float(浮点)
  6. double(浮点)这个
  7. boolean(布尔)这个
  8. char(字符)还有string

1.2 Java的常量

常量在程序运行时是不能被修改的。

在 Java 中使用 final 关键字来修饰常量,声明方式和变量类似(为了区分,变量名一般用大写):

final double PI = 3.1415926;

1.3 Java中的转义字符

Java语言支持一些特殊的转义字符序列。

符号字符含义
\n换行 (0x0a)
\r回车 (0x0d)
\f换页符(0x0c)
\b退格 (0x08)
\0空字符 (0x0)
\s空格 (0x20)
\t制表符
"双引号
单引号
\反斜杠
\ddd八进制字符 (ddd)
\uxxxx16进制Unicode字符 (xxxx)

1.4 自动类型转换

整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。

低-————>>>高
byte,short,char—> int —> long—> float —> double

数据类型转换必须满足如下规则:

  1. 不能对boolean类型进行类型转换。

  2. 不能把对象类型转换成不相关类的对象。

  3. 在把容量大的类型转换为容量小的类型时必须使用强制类型转换。

  4. 转换过程中可能导致溢出或损失精度

  5. 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入

2. 循环结构

2.1 while循环

while循环时最基本的循环,它的结构为:

while(表达式){
//循环内容
}

只要表达式为True,while则会一直循环下去

实例:

public class test {
    public static void main(String[] args) {
        int a = 0;
        while( a < 10 ) {
            a++;
            System.out.println(a);
        }
    }
}

运行结果如下:
在这里插入图片描述

2.2 do while循环

对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。

do {
	// 代码语句
}while(表达式);

注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。 如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
实例:

public class test {
    public static void main(String[] args) {
        int a = 0;
        do{
            a++;
            System.out.println(a);
        }while(a<10);
    }
}

结果如下:
在这里插入图片描述

2.3 for 循环

增强 for 循环语法格式如下:

for(变量;条件判断;满足结果){
//执行结果
}

实例

public class test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }
}

结果如下:
在这里插入图片描述

2.4 break/continue

break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。

break 跳出最里层的循环,并且继续执行该循环下面的语句。

continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。

在 for 循环中,continue 语句使程序立即跳转到更新语句。

在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。

3. 条件语句

Java 中的条件语句允许程序根据条件的不同执行不同的代码块。

3.1 if … else…

if 语句后面可以跟 else 语句,当 if 语句的布尔表达式值为 false 时,else 语句块会被执行。
语法
if 语句的语法如下:

if(布尔表达式){
   //如果布尔表达式的值为true
}else{
   //如果布尔表达式的值为false
}

如果布尔表达式的值为 true,则执行 if 语句中的代码块,否则执行 else 语句块后面的代码。

实例:

public class test{

   public static void main(String args[]){
      int x = 30;
       
      if( x < 20 ){
         System.out.print("这是 if 语句");
      }else{
         System.out.print("这是 else 语句");
      }
   }
}

3.2 if … else if … if…

if…else if…else 语句
if 语句后面可以跟 else if…else 语句,这种语句可以检测到多种可能的情况。

使用 if,else if,else 语句的时候,需要注意下面几点:

  • if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
  • if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
  • 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。
if...else 语法格式如下:

if(布尔表达式 1){
   //如果布尔表达式 1的值为true执行代码
}else if(布尔表达式 2){
   //如果布尔表达式 2的值为true执行代码
}else if(布尔表达式 3){
   //如果布尔表达式 3的值为true执行代码
}else {
   //如果以上布尔表达式都不为true执行代码
}

实例如下:

public class test {
   public static void main(String args[]){
      int x = 30;
 
      if( x == 10 ){
         System.out.print("Value of X is 10");
      }else if( x == 20 ){
         System.out.print("Value of X is 20");
      }else if( x == 30 ){
         System.out.print("Value of X is 30");
      }else{
         System.out.print("这是 else 语句");
      }
   }
}

注意:条件语句中也可以嵌套使用,例如满足一个条件之后,进行二次判断,或者三次判断就可以嵌套使用

4. swit case语句

switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
switch case 语句语法格式如下:

switch(expression){
    case value :
       //语句
       break; //可选
    case value :
       //语句
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
}

实例:

public class test {
   public static void main(String args[]){
      //char grade = args[0].charAt(0);
      String grade = 'C';
 
      switch(grade)
      {
         case 'A' :
            System.out.println("优秀"); 
            break;
         case 'B' :
         case 'C' :
            System.out.println("良好");
            break;
         case 'D' :
            System.out.println("及格");
            break;
         case 'F' :
            System.out.println("你需要再努力努力");
            break;
         default :
            System.out.println("未知等级");
      }
      System.out.println("你的等级是 " + grade);
   }
}

如果case语句块中没有break语句时,switch case并不会顺序输出每一个case对应的返回值,而是继续匹配,匹配不成功则返回默认case.

5. 数组

Java 语言中提供的数组是用来存储固定大小的同类型元素。
声明一个数组变量,如 numbers[100] 来代替直接声明 100 个独立变量 number0,number1,…,number99。

声明数组变量

int[] myList;//推荐使用这个
//或者
int myList[];//效果一样

创建数组
Java语言使用new操作符来创建数组,语法如下:

arrayRefVar = new dataType[arraySize];
上面的语法语句做了两件事:

  • 一、使用 dataType[arraySize] 创建了一个数组。
  • 二、把新创建的数组的引用赋值给变量arrayRefVar。

数组变量的声明,和创建数组可以用一条语句完成,如下所示:

dataType[] arrayRefVar = new dataType[arraySize];

另外,你还可以使用如下的方式创建数组。

dataType[] arrayRefVar = {value0, value1, ..., valuek};

数组的元素是通过索引访问的。数组索引从 0 开始,所以索引值从 0 到 arrayRefVar.length-1。

实例:
下面的语句首先声明了一个数组变量 myList,接着创建了一个包含 10 个 double 类型元素的数组,并且把它的引用赋值给 myList 变量。

public class TestArray {
   public static void main(String[] args) {
      // 数组大小
      int size = 10;
      // 定义数组
      double[] myList = new double[size];
      myList[0] = 5.6;
      myList[1] = 4.5;
      myList[2] = 3.3;
      myList[3] = 13.2;
      myList[4] = 4.0;
      myList[5] = 34.33;
      myList[6] = 34.0;
      myList[7] = 45.45;
      myList[8] = 99.993;
      myList[9] = 11123;
      // 计算所有元素的总和
      double total = 0;
      for (int i = 0; i < size; i++) {
         total += myList[i];
      }
      System.out.println("总和为: " + total);
   }
}

6. 方法

Java方法是语句的集合,它们在一起执行一个功能。

  • 方法是解决一类问题的步骤的有序组合
  • 方法包含于类或对象中
  • 方法在程序中被创建,在其他地方被引用

方法其中四个优点:

  1. 使程序变得简短而清晰。
  2. 有利于程序维护。
  3. 可以提高程序的开发效率
  4. 提高了代码的重用性

方法的定义
一般情况下,定义一个方法包含以下语法:

修饰符 返回值类型 方法名(参数类型 参数名){
    ...
    方法体
    ...
    return 返回值;
}

方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

  • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。

  • 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。

  • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。

  • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

  • 方法体:方法体包含具体的语句,定义该方法的功能。
    在这里插入图片描述

方法的调用
实例:

下面的例子演示了如何定义一个方法,以及如何调用它:

public class TestMax {
   /** 主方法 */
   public static void main(String[] args) {
      int i = 9;
      int j = 2;
      int k = max(i, j);
      System.out.println( i + " 和 " + j + " 比较,最大值是:" + k);
   }
 
   /** 返回两个整数变量较大的值 */
   public static int max(int num1, int num2) {
      int result;
      if (num1 > num2)
         result = num1;
      else
         result = num2;
 
      return result; 
   }
}

运行结果如下:
9和2比较,最大值是:9

7. Scanner 键盘接收

通过 Scanner 类来获取用户的输入。
基础语法如下:

Scanner s = new Scanner(System.in);

下面演示一个简单的例子:

import java.util.Scanner; 

public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的成绩");
        int score = sc.nextInt();
        if (score != 0){
            System.out.println(score);
        }
    }
}

键盘输入一个数字,如果数字不是0,那么控制台输出。

8. 异常处理

异常发生的原因有很多,通常包含以下几大类:

  • 用户输入了非法数据。
  • 要打开的文件不存在。
  • 网络通信时连接中断,或者JVM内存溢出。

Java内置异常类:

异常描述
ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。
ArrayIndexOutOfBoundsException用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。
ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常。
ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常。
IllegalArgumentException抛出的异常表明向方法传递了一个不合法或不正确的参数。
IllegalMonitorStateException抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。
IllegalStateException在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。
IllegalThreadStateException线程没有处于请求操作所要求的适当状态时抛出的异常。
IndexOutOfBoundsException指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。
NegativeArraySizeException如果应用程序试图创建大小为负的数组,则抛出该异常。
NullPointerException当应用程序试图在需要对象的地方使用 null 时,抛出该异常
NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。
SecurityException由安全管理器抛出的异常,指示存在安全侵犯。
StringIndexOutOfBoundsException此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。
UnsupportedOperationException当不支持请求的操作时,抛出该异常。

下面的则是Java 定义在 java.lang 包中的检查性异常类。

异常描述
ClassNotFoundException应用程序试图加载类时,找不到相应的类,抛出该异常。
CloneNotSupportedException当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。
IllegalAccessException拒绝访问一个类的时候,抛出该异常。
InstantiationException当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。
InterruptedException一个线程被另一个线程中断,抛出该异常。
NoSuchFieldException请求的变量不存在
NoSuchMethodException请求的方法不存在

捕获异常
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。

try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:

try
{
   // 程序代码
}catch(ExceptionName e1)
{
   //Catch 块
}

Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。

如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。

多重捕获块
一个 try 代码块后面跟随多个 catch 代码块的情况就叫多重捕获。

try{
   // 程序代码
}catch(异常类型1 异常的变量名1){
  // 程序代码
}catch(异常类型2 异常的变量名2){
  // 程序代码
}catch(异常类型3 异常的变量名3){
  // 程序代码
}

上面的代码段包含了 3 个 catch块。

可以在 try 语句后面添加任意数量的 catch 块。

如果保护代码中发生异常,异常被抛给第一个 catch 块。

如果抛出异常的数据类型与 ExceptionType1 匹配,它在这里就会被捕获。

如果不匹配,它会被传递给第二个 catch 块。

如此,直到异常被捕获或者通过所有的 catch 块。

throws/throw关键字
throw 和 throws 关键字是用于处理异常的。

throw 关键字用于在代码中抛出异常,而 throws 关键字用于在方法声明中指定可能会抛出的异常类型。

throw和throws的区别:

  • throw代表动作,表示抛出一个异常的动作;
  • throws代表一种状态,代表方法可能有异常抛出

throw用在方法实现中,而throws用在方法声明中;
throw只能用于抛出一种异常,而throws可以抛出多个异常

throw关键字用来在程序中明确的抛出异常,相反 throws语句用来表明方法不能处理的异常。
每一个方法都必须要指定哪些异常不能处理,所以方法的调用者才能够确保处理可能发生的异常,多个异常是用逗号分隔的。

finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。

无论是否发生异常,finally 代码块中的代码总会被执行。

在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。

finally 代码块出现在 catch 代码块最

四、小结

写本文主要是为了分享我的学习过程,也是给自己记个笔记,哪里忘记了,回来再看一眼,也可以很快的回想起来

  • 47
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,我可以帮你复习Java基础面试题。以下是一些常见的Java基础面试题及其答案: 1. Java中的基本数据类型有哪些? 答:Java中的基本数据类型包括byte、short、int、long、float、double、boolean和char。 2. Java中的包装类是什么? 答:包装类是一种将基本数据类型封装成对象的方式。Java提供了对应于每个基本数据类型的包装类,如Integer、Double、Boolean等。 3. Java中的String类是可变的吗? 答:String类是不可变的,即一旦创建就不能被修改。如果需要对字符串进行修改操作,可以使用StringBuilder或StringBuffer类。 4. Java中的final关键字有什么作用? 答:final关键字可以用来修饰类、方法和变量。当修饰类时,表示该类不能被继承;当修饰方法时,表示该方法不能被重写;当修饰变量时,表示该变量的值不能被修改。 5. Java中的抽象类和接口有什么区别? 答:抽象类是一种不能被实例化的类,它可以包含抽象方法和非抽象方法。接口是一种完全抽象的类,它只能包含抽象方法和常量。一个类可以实现多个接口,但只能继承一个抽象类。 6. Java中的异常处理机制是什么? 答:Java中的异常处理机制通过try-catch-finally语句块来实现。当可能发生异常的代码放在try块中,如果发生异常,则会被catch块捕获并进行处理,最后无论是否发生异常,都会执行finally块中的代码。 7. Java中的多线程是如何实现的? 答:Java中实现多线程有两种方式,一种是继承Thread类,另一种是实现Runnable接口。通过重写Thread类的run()方法或实现Runnable接口的run()方法来定义线程的执行逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值