JavaSE进阶(Day1面向对象基础、Day2常用API、Day3集合基础)

JavaSE进阶(Day1~Day3)

Day1-面向对象基础

一、类和对象

面向对象和面向过程的思想对比 :

  • 面向过程 :是一种以过程为中心的编程思想,实现功能的每一步,都是自己实现的;
  • 面向对象 :是一种以对象为中心的编程思想,通过指挥对象实现具体的功能;
  • 在这里插入图片描述
    在这里插入图片描述

1、类和对象的关系

  客观存在的事物皆为 对象 ,所以我们也常常说万物皆对象。
类的理解

  • 类是对现实生活中一类具有共同属性和行为的事物的抽象
  • 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合
  • 简单理解:类就是对现实事物的一种描述

类的组成

  • 属性:指事物的特征,例如:手机事物(品牌,价格,尺寸)
  • 行为:指事物能执行的操作,例如:手机事物(打电话,发短信)

类和对象的关系
:类是对现实生活中一类具有共同属性和行为的事物的抽象
对象:是能够看得到摸的着的真实存在的实体
简单理解类是对事物的一种描述,对象则为具体存在的事物
在这里插入图片描述

2、类的定义【应用】

类的组成是由属性行为两部分组成

  • 属性:在类中通过成员变量来体现(类中方法外的变量)
  • 行为:在类中通过成员方法来体现(和前面的方法相比去掉static关键字即可)

类的定义步骤:

① 定义类
② 编写类的成员变量
③ 编写类的成员方法

定义类:单独一个定义累的程序是不能运行的,因为没有main方法;

package com.chuangTi;

public class Student {
    // 属性 : 姓名, 年龄
    // 成员变量: 跟之前定义变量的格式一样, 只不过位置发生了改变, 类中方法外
    String name;
    int age;

    // 行为 : 学习
    // 成员方法: 跟之前定义方法的格式一样, 只不过去掉了static关键字.
    public void study() {
        System.out.println("学习");
    }
}

3、对象的创建和使用

创建对象的格式:

  • 类名 对象名 = new 类名();

调用成员的格式:

  • 对象名.成员变量
  • 对象名.成员方法();
package com.chuangTi;

public class TestStudent {
    /*
       创建对象的格式:
               类名 对象名 = new 类名();
       调用成员变量的格式:
               对象名.变量名
       调用成员方法的格式:
               对象名.方法名();
    */
    public static void main(String[] args) {
        // 类名 对象名 = new 类名();
        Student stu = new Student();   //创建对象
        // 对象名.变量名
        // 默认初始化值
        System.out.println(stu.name);  // null     //调用对象的变量,stu.name
        System.out.println(stu.age);   // 0

        stu.name = "张三";
        stu.age = 23;

        System.out.println(stu.name);  // 张三
        System.out.println(stu.age);   // 23

        // 对象名.方法名();
        stu.study();     //调用成员方法;
        // com.chuangTi.Student@4eec7777
        // 全类名(包名 + 类名)
        System.out.println(stu);
    }
}

二、对象内存图

1、单个对象内存图

在这里插入图片描述

2、多个对象内存图【理解】

在这里插入图片描述
总结:
  多个对象在堆内存中,都有不同的内存划分,成员变量存储在各自的内存区域中,成员方法多个对象共用的一份

3、多个对象指向相同内存图【理解】

在这里插入图片描述
总结 :

  • 当多个对象的引用指向同一个内存空间(变量所记录的地址值是一样的)
  • 只要有任何一个对象修改了内存中的数据,随后,无论使用哪一个对象进行数据获取,都是修改后的数据。

三、成员变量和局部变量

成员变量和局部变量的区别
类中位置不同:成员变量(类中方法外)局部变量(方法内部或方法声明上)
内存中位置不同:成员变量(堆内存)局部变量(栈内存)
生命周期不同:成员变量(随着对象的存在而存在,随着对象的消失而消失;局部变量(随着方法的调用而存在,随着方法的调用完毕而消失)
初始化值不同:成员变量(有默认初始化值)局部变量(没有默认初始化值,必须先定义,赋值才能使用)

四、封装

1、private关键字

概述 : private是一个权限修饰符,可以用来 修饰成员(成员变量,成员方法)
特点 : 被private修饰的成员,只能在本类进行访问,针对private修饰的成员变量,如果需要被其他类使用, 提供相应的操作

提供 get变量名()”方法,用于获取成员变量的值,方法用public修饰;
提供 set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰;
也可以用带参构造方法赋值

2、private关键字的使用

定义标准的学生类,要求name和age使用private修饰
并提供set和get方法以及便于显示数据的show方法

3、this关键字【应用】

概述 : this修饰的变量用于指代成员变量,其主要作用是(区分局部变量和成员变量的重名问题

  • 方法的形参如果与成员变量同名,不带this修饰的变量指的是形参,而不是成员变量;
  • 方法的形参没有与成员变量同名,不带this修饰的变量指的是成员变量;

注意 : this代表当前调用方法的引用,哪个对象调用的方法,this就代表哪一个对象

1、2、3、的代码示例

定义类

package com.chuangTi;

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

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

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void show() {
        System.out.println(name + "..." + age);
    }
}

使用对象:

package com.chuangTi;

public class TestStudent {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.setName("张三");
        stu.setAge(3);

        System.out.println(stu.getName());
        System.out.println(stu.getAge());

        int age = stu.getAge();

        for (int i = 1; i <= age; i++) {
            System.out.println("生日快乐");
        }

        stu.show();  // 仅仅是对数据做展示
    }
}

结果;

张三
3
生日快乐
生日快乐
生日快乐
张三...3

5、封装思想

封装概述
面向对象三大特征之一(封装,继承,多态)
是面向对象编程语言对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界是无法直接操作的【隐藏实现细节,仅对外暴露公共的访问方式

封装好处

  • 通过方法来控制成员变量的操作,提高了代码的**安全性**
  • 把代码用方法进行封装,提高了代码的**复用性**

封装常见的体现

  • 私有成员变量,提供setXxx方法和getXxx方法;
      私有仅仅是封装的一种体现,不能说封装就是私有
  • 将代码抽取到方法中,这是对代码的一种封装
    在这里插入图片描述
  • 将属性抽取到类中,这是对数据的一种封装
    在这里插入图片描述

五、构造方法

1、构造方法的格式和执行时机

概述:构建、创造对象的时候,所调用的方法
格式注意 :

  • 方法名与类名相同,大小写也要一致
  • 没有返回值类型,连void都没有
  • 没有具体的返回值(不能由retrun带回结果数据)

执行时机 :

  • 创建对象的时候调用,每创建一次对象,就会执行一次构造方法
  • 不能手动调用构造方法;

2、构造方法的作用

  • 创建对象
  • 用于给对象的数据(属性)进行初始化

3、构造方法的注意事项

构造方法的创建 :
如果没有定义构造方法,系统将给出一个默认无参数构造方法
如果定义了构造方法,系统将不再提供默认的构造方法;
构造方法的重载: 如果定义了带参构造方法,还要使用无参数构造方法,就必须再写一个无参数构造方法;
推荐的使用方式 :
无论是否使用,都手动书写无参数构造方法,和带参数构造方法

今天的代码制作一个标准类:

JavaBean类:封装数据的类;
在这里插入图片描述

类的定义:

package com.chuangTi;

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

       //无参构造方法,方法名与类名相同、没有返回值、没有返回值类型
    public Student() {
    }

      //带参构造方法,方法名与类名相同、没有返回值、没有返回值类型
    public Student(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    public void show() {
        System.out.println(name + "..." + age);
    }
}

对象的创建和使用;

package com.chuangTi;

public class TestStudent {
    public static void main(String[] args) {
        // 1. 无参数构造方法创建对象, 通过setXxx方法给成员变量进行赋值
        Student stu1 = new Student();
        stu1.setName("张三");
        stu1.setAge(23);
        stu1.show();

        // 2. 通过带参数构造方法, 直接给属性进行赋值
        Student stu2 = new Student("李四", 24);
        stu2.show();
    }
}

Day2-常用API

一、API

1、API概述-帮助文档的使用

什么是API
   API (Application Programming Interface) :应用程序编程接口
java中的API
  指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用;
如何使用API帮助文档 :

  • 打开帮助文档
  • 找到索引选项卡中的输入框
  • 在输入框中输入Random
  • 看类在哪个包下
  • 看类的描述
  • 看构造方法
  • 看成员方法

2、键盘录入字符串

Scanner类 :
next() : 遇到了空格, 就不再录入数据了 , 结束标记: 空格, tab键
nextLine() : 可以将数据完整的接收过来 , 结束标记: 回车换行符
nextInt只能输入整型数据;

创建Scanner对象
Scanner sc = new Scanner(System.in);

代码实现:

package com.chuangTi;

import java.util.Scanner;

public class Demo1Scanner {
    /*
        next() : 遇到了空格, 就不再录入数据了

                结束标记: 空格, tab键

        nextLine() : 可以将数据完整的接收过来

                结束标记: 回车换行符
     */
    public static void main(String[] args) {
        // 1. 创建Scanner对象
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        // 2. 调用nextLine方法接收字符串
        // ctrl + alt + v : 快速生成方法的返回值
        String s = sc.nextLine();

        System.out.println(s);
    }
}

二、String类

1、String概述

1、String 类在 java.lang 包下,所以使用的时候不需要导包;
2、String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例(对象)也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象
3、字符串不可变,它们的值在创建后不能被更改

2、String类的构造方法

常用的构造方法
在这里插入图片描述

注意:
String这个类比较特殊,打印其对象名的时候,不会出现内存地址,而是该对象所记录的真实内容.

代码演示:

package com.chuangTi;

public class Demo2StringConstructor {
    /*
    String类常见构造方法:

       1、 public String() : 创建一个空白字符串对象,不含有任何内容
       2、public String(char[] chs) : 根据字符数组的内容,来创建字符串对象
       3、public String(String original) : 根据传入的字符串内容,来创建字符串对象
        String s = “abc”;  直接赋值的方式创建字符串对象,内容就是abc

     注意:
            String这个类比较特殊, 打印其对象名的时候, 不会出现内存地址
            而是该对象所记录的真实内容.

            面向对象-继承, Object类
 */
    public static void main(String[] args) {
        // public String() : 创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println(s1);

        // public String(char[] chs) : 根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println(s2);

        // public String(String original) : 根据传入的字符串内容,来创建字符串对象
        String s3 = new String("123");
        System.out.println(s3);
    }
}

3、创建字符串对象的区别对比

通过构造方法创建
  通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同;

直接赋值方式创建
  以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护;
在这里插入图片描述
故:
在这里插入图片描述

4、String字符串的特点(常见面试题)

在这里插入图片描述
题目:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、字符串的比较

1、字符串的比较

比较基本数据类型:比较的是具体的值
比较引用数据类型:比较的是对象地址值

String类 : public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写;

代码示例:

package com.chuangTi;

public class Demo1Equals {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ABC";
        String s3 = "abc";

        // equals : 比较字符串内容, 区分大小写
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));

        // equalsIgnoreCase : 比较字符串内容, 忽略大小写
        System.out.println(s1.equalsIgnoreCase(s2));
    }
}

2、用户登录案例

需求

  • 已知用户名和密码,请用程序实现模拟用户登录。
  • 总共给三次机会,登录之后,给出相应的提示

思路
1. 已知用户名和密码,定义两个字符串表示即可
2. 键盘录入要登录的用户名和密码,用 Scanner 实现
3. 拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。字符串的内容比较,用equals() 方法实现
4. 用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环;

程序实现:

package com.chuangTi;

import java.util.Scanner;
public class Test1 {

    public static void main(String[] args) {
        // 1. 已知用户名和密码,定义两个字符串表示即可
        String username = "admin";
        String password = "123456";
        // 2. 键盘录入要登录的用户名和密码,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        // 4. 用循环实现多次机会,这里的次数明确,采用for循环实现
        for (int i = 1; i <= 3; i++) {
            System.out.println("请输入用户名:");
            String scUsername = sc.nextLine();
            System.out.println("请输入密码:");
            String scPassword = sc.nextLine();
            // 3. 拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。
            if (username.equals(scUsername) && password.equals(scPassword)) {
                System.out.println("登录成功");
                break;
            } else {
                if (i == 3) {
                    System.out.println("您的登录次数已达到今日上限, 请明天再来");
                } else {
                    System.out.println("登录失败,您还剩余" + (3 - i) + "次机会");
                }
            }
        }
    }
}

3、案例(字符串的遍历)

案例需求 :
  键盘录入一个字符串,使用程序实现在控制台遍历该字符串;

实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现;
  2. 遍历字符串,首先要能够获取到字符串中的每一个字符, public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的
  3. 遍历字符串,其次要能够获取到字符串的长度;
  • public int length():返回此字符串的长度
  • 数组的长度:数组.length
  • 字符串的长度:字符串对象.length()
  1. 遍历打印
for (int i =0;i<s.length();i++){
       s.charAt(i);//就是指定索引处的字符值;
}

关键代码:

  // i : 字符串的每一个索引
            char c = s.charAt(i);
 // 2. 将字符串拆分为字符数组
        char[] chars = s.toCharArray();

方式一daima :

package com.itheima.test;

import java.util.Scanner;
public class Test2 {
    public static void main(String[] args) {
        //  1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        String s = sc.nextLine();
        // 2. 遍历字符串,首先要能够获取到字符串中的每一个字符
        for(int i = 0; i < s.length(); i++){
            // i : 字符串的每一个索引
            char c = s.charAt(i);
            System.out.println(c);
        }
    }
}

方式二代码:

package com.itheima.test;

import java.util.Scanner;
public class Test3 {
    public static void main(String[] args) {
        //  1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        String s = sc.nextLine();
        // 2. 将字符串拆分为字符数组
        char[] chars = s.toCharArray();
        // 3. 遍历字符数组
        for (int i = 0; i < chars.length; i++) {
            System.out.println(chars[i]);
        }
    }
}

4、统计字符次数案例【应用】

案例需求 :
键盘录入一个字符串,使用程序实现在控制台遍历该字符串;
实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现;
  2. 将字符串拆分为字符数组 , public char[] toCharArray( ):将当前字符串拆分为字符数组并返回;
  3. 要统计三种类型的字符个数,需定义三个统计变量,初始值都为0;
  4. 遍历字符数,得到每一个字符;
  5. 判断该字符属于那种类型,然后对应类型的同一边亮+1
    例如ch十余个字符,我要判断他属于大写字母,小写字母,还是数字,直接判断该字符是否在对应的范围即可;
  • 大写字母:ch>=‘A’&&ch<=‘Z’;
  • 小写字母:ch>=‘a’&&ch<=‘z’;
  • 数字:ch>=‘0’&&ch<=‘9’;

6.输出三中类型的字符个数;

5、手机号屏蔽-字符串截取

案例需求 :
以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽 最终效果为:156****1234
实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现
  2. 截取字符串前三位
  3. 截取字符串后四位
  4. 将截取后的两个字符串,中间加上****进行拼接,输出结果;

重点知识:字符串的截取:substring

String s = "itheima";
String ss = s.substring(2);  //有返回值
System.out.println(ss);

String sss = s.substring(0,2);
System.out.println(sss);

结果:

heima
it

6、敏感词替换-字符串替换

案例需求 :
键盘录入一个 字符串,如果字符串中包含(TMD),则使用***替换
实现步骤 :

  • 键盘录入一个字符串,用 Scanner 实现
  • 替换敏感词
      String replace(CharSequence target, CharSequence replacement)
      将当前字符串中的target内容,使用replacement进行替换,返回新的字符串;
  • 输出结果

字符串的替换方法:

 String s = "你TMD真是个人才!"
 // 2. 替换敏感词
String result = s.replace("TMD","***");
// 3. 输出结果
System.out.println(result);

7、切割字符串

案例需求 :
以字符串的形式从键盘录入学生信息,例如:“张三 , 23”
从该字符串中切割出有效数据,封装为Student学生对象
实现步骤 :

  • 编写Student类,用于封装数据
  • 键盘录入一个字符串,用 Scanner 实现
  • 根据逗号切割字符串,得到(张三)(23)
    String[] split(String regex) 根据传入的字符串作为规则进行切割 将切割后的内容存入字符串数组中,并将字符串数组返回;
  • 从得到的字符串数组中取出元素内容,通过Student类的有参构造方法封装为对象
  • 调用对象getXxx方法,取出数据并打印。

如何截取字符串:

stuInfo = "张三,23";
// 根据逗号切割字符串,得到(张三)(23)
String[] sArr = stuInfo.split(",");

System.out.println(sArr[0]);
System.out.println(sArr[1]);

结果:

张三
23

代码实现:
类的定义:

package com.itheima.domain;

public class Student {
    private String name;  //私有化
    private String age;

    public Student() {
    }
    public Student(String name, String age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAge() {
        return age;
    }
    public void setAge(String age) {
        this.age = age;
    }
}

创建对象

package com.itheima.test;

import com.itheima.domain.Student;

import java.util.Scanner;
public class Test7 {
    public static void main(String[] args) {
        // 2. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学生信息:");
        String stuInfo = sc.nextLine();
        // 3. 根据逗号切割字符串,得到(张三)(23)
        String[] sArr = stuInfo.split(",");

        // 4. 从得到的字符串数组中取出元素内容,通过Student类的有参构造方法封装为对象
        Student stu = new Student(sArr[0],sArr[1]);

        // 5. 调用对象getXxx方法,取出数据并打印。
        System.out.println(stu.getName() + "..." + stu.getAge());
    }
}

8、 String方法小结

方法名说明
public boolean equals(Object anObject)比较字符串的内容,严格区分大小写
public boolean equalsIgnoreCase(String anotherString)比较字符串的内容,忽略大小写
public int length()返回此字符串的长度
public char charAt(int index)返回指定索引处的 char 值
public char[] toCharArray()将字符串拆分为字符数组后返回
public String substring(int beginIndex, int endIndex)根据开始和结束索引进行截取,得到新的字符串(包含头,不包含尾)
public String substring(int beginIndex)从传入的索引处截取,截取到末尾,得到新的字符串
public String replace(CharSequence target, CharSequence replacement)使用新值,将字符串中的旧值替换,得到新的字符串
public String[] split(String regex)根据传入的规则切割字符串,得到字符串数组

四、StringBuilder类

1、 StringBuilder类概述

概述 : StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器(可装任何内容的数据,但最终都会变成字符串数据),这里的可变指的是 StringBuilder 对象中的内容是可变的;
StringBuilder的作用: 提高字符串的操作效率;
示例代码(验证提高效率的代码):

package com.itheima.stringbuilder;

public class Demo1StringBuilder {
    public static void main(String[] args) {
        // 264
        long start = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();

        for(int i = 1; i <= 50000; i++){
            sb.append(i);
        }
        System.out.println(sb);
        long end = System.currentTimeMillis();
        System.out.println(end - start);      //返回上面代码运行时间
    }

    public static void method() {
        // 2939
        long start = System.currentTimeMillis();  // 获取1970年1月1日 0时0分0秒 到当前时间所经历过的毫秒值
        String s = "";

        for(int i = 1; i <= 50000; i++){
            s += i;
        }
        System.out.println(s);
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}

通过结果哦们可以知道,使用StringBuilder()完成字符串的拼接用时最少
StringBuilder类和String类的区别

  • String类:内容是不可变的;
  • StringBuilder类:内容是可变的;

2、StringBuilder类的构造方法

方法名说明
public StringBuilder()创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str)根据字符串的内容,来创建可变字符串对象

示例代码:

package com.itheima.stringbuilder;

public class Demo2StringBuilder {
    public static void main(String[] args) {
        // public StringBuilder() : 创建一个空白可变字符串对象,不含有任何内容
        StringBuilder sb = new StringBuilder();
        System.out.println(sb);     //打印一个空白;

        // public StringBuilder(String str) : 根据字符串的内容,来创建可变字符串对象
        StringBuilder sb2 = new StringBuilder("abc");  
        System.out.println(sb2);      //打印"abc"
    }
}

3、StringBuilder常用的成员方法

方法名说明
public StringBuilder append(任意类型)添加数据,并返回对象本身
public StringBuilder reverse()返回相反的字符序列、
public int length()返回长度(字符出现的个数)
public String toString()通过toString()就可以实现把StringBuilder转换成String

示例代码:

package com.itheima.stringbuilder;

public class Demo3StringBuilder {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        // 链式编程: 如果一个方法返回的是对象类型, 对象就可以继续向下调用方法.   重要;
        sb.append("红色").append("蓝色").append("绿色");

        System.out.println("反转前:" + sb);

        sb.reverse();   //翻转;

        System.out.println("反转后:" + sb);

        System.out.println("sb中字符的个数为:" + sb.length());   //返回长度;

        // public String toString() : 通过toString()就可以实现把StringBuilder转换为String
        String s = sb.toString();
        System.out.println(s);
    }
}

4、StringBuilder提高效率的原理

不使用StringBuilder
在这里插入图片描述
使用StringBuilder
在这里插入图片描述

5、【案例】StringBuilder和String相互转换【应用】

StringBuilder转换为String
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
String转换为StringBuilder
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder

对称字符串的代码实现:
在这里插入图片描述

package com.itheima.test;

import java.util.Scanner;
public class Test8 {
    public static void main(String[] args) {
        //  1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入对称字符串:");
        String s = sc.nextLine();
        // 2. 将键盘录入的字符串反转
        // 将字符串封装为StringBuilder对象, 目的是为了掉用其反转的方法
        StringBuilder sb = new StringBuilder(s);  //String转换为StringBuilder
        sb.reverse();    //字符串的翻转在StringBuilder中;
        String reverseStr = sb.toString();  //StringBuilder转换为String
        // s : String
        // sb : StringBuilder
        // 3. 使用反转后的字符串,和原字符串进行比对
        if(s.equals(reverseStr)){
            System.out.println("是对称字符串");
        }else{
            System.out.println("不是对称字符串");
        }
    }
}

6、【案例】StringBuilder拼接字符串

案例需求 :
  定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,并在控制台输出结果。例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]字符串;
实现步骤 :

  • 定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
  • 定义一个方法,用于把int数组中的数据按照指定格式拼接成一个字符串返回。
    返回值类型 String,参数列表 int[] arr
  • 在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
  • 调用方法,用一个变量接收结果
  • 输出结果

程序代码:

package com.itheima.test;

public class Test9 {

    public static void main(String[] args) {
        // 1. 定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
        int[] arr = {1,2,3};
        // 4. 调用方法,用一个变量接收结果
        String s = arrayToString(arr);    //调用方法;
        // 5. 输出结果
        System.out.println(s);
    }

    // 2. 定义一个方法,返回值类型 String,参数列表 int[] arr
    public static String arrayToString(int[] arr){
        // 3. 在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < arr.length; i++) {
            if(i == arr.length -1){
                sb.append(arr[i]).append("]");
            }else{
                sb.append(arr[i]).append(", ");
            }
        }
        return sb.toString();   //将StringBuilder转换成String;
    }
}

Day3-集合基础

一、ArrayList(数组列表)

1、集合和数组的区别对比

集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以发生改变
集合和数组的区别 :
共同点:都是存储数据的容器
不同点数组的容量是固定的集合的容量是可变的

来一个案例:
在这里插入图片描述
学生类的定义:

package com.heima.domain;

public class Student {   //定义学生类;
    private String name;
    private int age;
    
    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = 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;
    }
}

创建对象并完成功能:

package com.heima.array;

public class TestObjectArray {
    public static void main(String[] args) {
        // 2. 动态初始化长度为3的数组,类型为Student类型
        Student[] arr = new Student[3];
        // 3. 根据需求创建3个学生对象
        Student stu1 = new Student("张三",23);
        Student stu2 = new Student("李四",24);
        Student stu3 = new Student("王五",25);
        // 4. 将学生对象存入数组
        arr[0] = stu1;
        arr[1] = stu2;
        arr[2] = stu3;
        // 5. 遍历数组,取出每一个学生对象
        for (int i = 0; i < arr.length; i++) {
            Student temp = arr[i];
            System.out.println(temp.getName() + "..." + temp.getAge());
        }
    }
}

以上代码的缺点:不能自动扩容;

2、ArrayList的构造方法和添加方法

方法说明
public ArrayList()创建一个空的初始容量为 10的集合对象
public boolean add(E e)将指定的元素追加到此集合的末尾
public void add(int index,E element)在此集合中的指定位置插入指定的元素

ArrayList :
可调整大小的数组实现
<> 泛型: 对集合容器存储的数据类型进行限制;
怎么用呢 ?
在出现E的地方我们使用引用数据类型替换即可
举例: ArrayList<String> list = new ArrayList<>();

代码说明:

package com.heima.list;

public class Demo1ArrayList {
    public static void main(String[] args) {
        // 1. 创建集合容器对象
        ArrayList<String> list = new ArrayList<>();
        // 2. 调用对象的add方法, 向容器中添加数据
        list.add("111");
        list.add("222");
        list.add("333");
        list.add("444");
        list.add("555");

        list.add(0,"666");

        System.out.println(list);
    }
}

3、ArrayList类常用方法

方法说明
public boolean remove(Object o)删除指定的元素,返回删除是否成功
public E remove(int index)删除指定索引处的元素,返回被删除的元素
public E set(int index,E element)修改指定索引处的元素,返回被修改的元素
public E get(int index) 返回指定索引处的元素
public int size()返回集合中的元素的个数

程序说明:

package com.heima.list;

import java.util.ArrayList; //导包
public class Demo2ArrayList {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("111");
        list.add("222");
        list.add("555");

        // public E get(int index) 返回指定索引处的元素
        String s1 = list.get(0);
        String s2 = list.get(1);
        String s3 = list.get(2);

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

        // public int size() 返回集合中的元素的个数
        int size = list.size();
        System.out.println(size);
    }
    public static void testSet() {
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("111");
        list.add("222");
        list.add("555");

        //  public E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
        String s = list.set(0,"666");
        System.out.println(s);

        System.out.println(list);
    }

    public static void testRemove() {    //
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");
        list.add("111");
        list.add("222");
        list.add("555");
        //  public boolean remove(Object o) 删除指定的元素,返回删除是否成功
        boolean b1 = list.remove("abc");
        boolean b2 = list.remove("zzz");

        System.out.println(b1);
        System.out.println(b2);

        System.out.println(list);

        // public E remove(int index)  删除指定索引处的元素,返回被删除的元素
        String s = list.remove(0);
        System.out.println(s);

        System.out.println(list);
    }
}

4、 ArrayList存储字符串并遍历

案例需求 :
  创建一个存储字符串的集合,存储3个字符串元素,使用程序实现在控制台遍历该集合;
实现步骤 :

  • 1:创建集合对象
  • 2:往集合中添加字符串对象
  • 3:遍历集合,首先要能够获取到集合中的每一个元素,这个通过get(int index)方法实现
  • 4:遍历集合,其次要能够获取到集合的长度,这个通过size()方法实现
  • 5:遍历集合的通用格式
  • 在这里插入图片描述

程序实现:

package com.heima.test;

import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) {
        // 1. 创建集合对象
        ArrayList<String> list = new ArrayList<>();
        // 2. 往集合中添加字符串对象
        list.add("张三");
        list.add("李四");
        list.add("王五");
        // 3. 遍历集合
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
    }
}

5、 ArrayList存储学生对象并遍历

案例需求 :
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
实现步骤 :
1:定义学生类
2:创建集合对象
3:创建学生对象
4:添加学生对象到集合中
5:遍历集合,采用通用遍历格式实现
代码实现:
ArrayList<Student> list = new ArrayList<>();

package com.heima.test;

public class Test2 {
    public static void main(String[] args) {
        // 2. 创建集合对象
        ArrayList<Student> list = new ArrayList<>();
        // 3. 创建学生对象
        Student stu1 = new Student("张三1",23);
        Student stu2 = new Student("张三2",23);
        Student stu3 = new Student("张三3",23);
        // 4. 添加学生对象到集合中
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);
        // 5. 遍历集合,采用通用遍历格式实现
        for (int i = 0; i < list.size(); i++) {
            Student stu = list.get(i);
            System.out.println(stu.getName() + "..." + stu.getAge());
        }
    }
}

6、 键盘录入学生信息到集合

案例需求 :
  创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合学生的姓名和年龄来自于键盘录入。
实现步骤 :

  • 1:定义学生类,为了键盘录入数据方便,把学生类中的成员变量都定义为String类型
  • 2:创建集合对象
  • 3:键盘录入学生对象所需要的数据
  • 4:创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
  • 5:往集合中添加学生对象
  • 6:遍历集合,采用通用遍历格式实现

代码实现:
首先是学生类的创建代码(之前写过多次,不再赘述)
对象的创建和使用:
方式一:

package com.heima.test;

public class Test3 {
    public static void main(String[] args) {
        // 2. 创建集合对象
        ArrayList<Student> list = new ArrayList<>();
        Student stu1 = getStudent();
        Student stu2 = getStudent();
        Student stu3 = getStudent();
        // 5. 往集合中添加学生对象
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);
        //  6. 遍历集合,采用通用遍历格式实现
        for (int i = 0; i < list.size(); i++) {
            Student stu = list.get(i);
            System.out.println(stu.getName() + "..." + stu.getAge());
        }
    }
    public static Student getStudent() {
        // 3. 键盘录入学生对象所需要的数据
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学生姓名:");
        // next()   nextInt();
        String name = sc.next();
        System.out.println("请输入学生年龄:");
        int age = sc.nextInt();
        // 4. 创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
        Student stu = new Student(name, age);
        return stu;
    }
}

方式二:

public class ArrayListTest {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList<Student> array = new ArrayList<Student>();

        //为了提高代码的复用性,我们用方法来改进程序
        addStudent(array);
        addStudent(array);
        addStudent(array);

        //遍历集合,采用通用遍历格式实现
        for (int i = 0; i < array.size(); i++) {
            Student s = array.get(i);
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
    /*
        两个明确:
            返回值类型:void
            参数:ArrayList<Student> array
     */
    public static void addStudent(ArrayList<Student> array) {
        //键盘录入学生对象所需要的数据
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入学生姓名:");
        String name = sc.nextLine();

        System.out.println("请输入学生年龄:");
        String age = sc.nextLine();

        //创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
        Student s = new Student();
        s.setName(name);
        s.setAge(age);

        //往集合中添加学生对象
        array.add(s);
    }
}

7、集合删除元素

需求:
   创建一个存储String的集合,内部存储(test,张三,李四,test,test)字符串;删除所有的test字符串,删除后,将集合剩余元素打印在控制台;
思路:

  • 创建集合对象
  • 调用add方法,添加字符串
  • 遍历集合,取出每一个字符串元素
  • 加入if判断,如果是test字符串,调用remove方法删除
  • 打印集合元素

注意:

  • 根据元素进行删除, 只能删除集合中的第一个元素:list.remove("test");
  • 删除集合中的所有元素,每一次循环删除之后,一定要加一个i--,否则会错过元素;
  • 常量和变量进行比较,往往以常量作为基准:"test".equals(s)

代码实现:

package com.heima.test;

import java.util.ArrayList;

public class Test4 {
    public static void main(String[] args) {
        // 1. 创建集合对象
        ArrayList<String> list = new ArrayList<>();
        // 2. 调用add方法,添加字符串
        list.add("test");
        list.add("张三");
        list.add("李四");
        list.add("test");
        list.add("test");
        // 3. 遍历集合,取出每一个字符串元素
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            // 4. 加入if判断,如果是test字符串,调用remove方法删除
            //if(s.equals("test")){}
            if("test".equals(s)){  //常量和变量进行比较,往往以常量作为基准:"test".equals(s)
                list.remove(i);
                i--;   //删除集合中的所有元素,每一次循环删除之后,一定要加一个i--;
            }
        }
        System.out.println(list);
    }
}

8、集合的数据筛选

需求:
定义一个方法,方法接收一个集合对象(泛型为Student),方法内部将年龄低于18的学生对象找出,并存入新集合对象,方法返回新集合。
思路:

  • 1:定义方法,方法的形参定义为ArrayList list
  • 2:方法内部定义新集合,准备存储筛选出的学生对象 ArrayList newList
  • 3:遍历原集合,获取每一个学生对象
  • 4:通过学生对象调用getAge方法获取年龄,并判断年龄是否低于18
  • 5:将年龄低于18的学生对象存入新集合
  • 6:返回新集合
  • 7:main方法中测试该方法

注意: 一个方法的传参和返回值都可以是集合类型;
实现代码:
学生类的定义【之前写过很多次,在此不做赘述】
对象的创建和使用:

package com.heima.test;

import com.heima.domain.Student;

import java.util.ArrayList;

public class Test5 {
    public static void main(String[] args) {
        // 7. main方法中测试该方法
        ArrayList<Student> list = new ArrayList<>();
        Student stu1 = new Student("张三1",10);
        Student stu2 = new Student("张三2",10);
        Student stu3 = new Student("张三3",20);
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);

        ArrayList<Student> newList = getList(list);
        //循环遍历新集合,打印年龄小于18岁的学生;
        for (int i = 0; i < newList.size(); i++) {
            Student stu = newList.get(i);
            System.out.println(stu.getName() + "..." + stu.getAge());
        }
    }
    // 1. 定义方法,方法的形参定义为ArrayList<Student> list
    public static ArrayList<Student> getList(ArrayList<Student> list) {
        // 2. 方法内部定义新集合,准备存储筛选出的学生对象 ArrayList<Student> newList
        ArrayList<Student> newList = new ArrayList<>();
        // 3. 遍历原集合,获取每一个学生对象
        for (int i = 0; i < list.size(); i++) {
            Student stu = list.get(i);
            // 4. 通过学生对象调用getAge方法获取年龄,并判断年龄是否低于18
            int age = stu.getAge();
            if (age < 18) {
                //  5. 将年龄低于18的学生对象存入新集合
                newList.add(stu);
            }
        }
        // 6. 返回新集合
        return newList;
    }
}

二、学生管理系统

1、实现步骤分析和学生类的代码编写

案例需求
针对目前我们的所学内容,完成一个综合案例:学生管理系统!该系统主要功能如下:

  • 添加学生:通过键盘录入学生信息,添加到集合中
  • 删除学生:通过键盘录入要删除学生的学号,将该学生对象从集合中删除
  • 修改学生:通过键盘录入要修改学生的学号,将该学生对象其他信息进行修改
  • 查看学生:将集合中的学生对象信息进行展示
  • 退出系统:结束程序

实现思路:
在这里插入图片描述
实现步骤:

1、定义学生类,包含以下成员变量
学生类: Student成员变量:
学号:sid
姓名:name
年龄:age
生日:birthday
构造方法
无参构造
带四个参数的构造成员方法:
成员方法
每个成员变量对应给出get/set方法

学生类的代码编写

package com.itheima.domain; 
public class Student { 
    private String sid; // 学号 
    private String name; // 姓名 
    private int age; // 年龄 
    private String birthday; // 生日 
    public Student() { 

    }
    public Student(String sid, String name, int age, String birthday) {
         this.sid = sid; 
         this.name = name; 
         this.age = age; 
         this.birthday = birthday;
    }public String getSid() {
         return sid;
     }
     public void setSid(String sid) {
         this.sid = sid;
    }
    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;
     }public String getBirthday() {
         return birthday;
     }public void setBirthday(String birthday) {
         this.birthday = birthday;
     }
 }

2、学生管理系统实现步骤

实现对集合的增删改查的功能

2.1、学生管理系统主界面的搭建步骤
  • ①用输出语句完成主界面的编写
  • ②用Scanner实现键盘录入数据
  • ③用switch语句完成操作的选择
  • ④用循环完成再次回到主界面
2.2、学生管理系统的添加学生功能实现步骤
  • ①用键盘录入选择添加学生

要先判断该学号是否存在;使用一个while(ture)的无限循环;

  • ②定义一个方法,用于添加学生

显示提示信息,提示要输入何种信息
键盘录入学生对象所需要的数据
创建学生对象,把键盘录入的数据赋值给学生对象的成员变量
将学生对象添加到集合中(保存)
给出添加成功提示

  • ③调用方法
2.3、学生管理系统的查看学生功能实现步骤
  • ①用键盘录入选择查看所有学生信息
  • ②定义一个方法,用于查看学生信息

查看有无学生,没有的话要显示提示信息;
显示表头信息
将集合中数据取出按照对应格式显示学生信息,年龄显示补充“岁”

  • ③调用方法
2.4、学生管理系统的删除学生功能实现步骤
  • ①用键盘录入选择删除学生信息
  • ②定义一个方法,用于删除学生信息

显示提示信息
键盘录入要删除的学生学号
调用getIndex方法查找该学号在集合的索引
如果索引为-1,提示信息不存在
如果索引不是-1,调用remove方法删除并提示删除成功

  • ③调用方法
2.5、 学生管理系统的修改学生功能实现步骤
  • ①用键盘录入选择修改学生信息
  • ②定义一个方法,用于修改学生信息

显示提示信息
键盘录入要修改的学生学号
调用getIndex方法,查找该学号在集合的索引
如果索引为-1,提示信息不存在
如果索引不是-1,键盘录入要修改的学生信息
集合修改对应的学生信息
给出修改成功提示

  • ③调用方法
2.6、退出系统

使用System.exit(0);退出JVM

3、测试类的定义(详细的说明都在程序里)

package com.itheima.test;

import com.itheima.domain.Student;

import java.util.ArrayList;
import java.util.Scanner;

public class StudentManager {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        // 创建集合容器对象
        ArrayList<Student> list = new ArrayList<>();

        lo: while (true) {
            // 1. 搭建主界面菜单
            System.out.println("--------欢迎来到学生管理系统--------");
            System.out.println("1 添加学生");
            System.out.println("2 删除学生");
            System.out.println("3 修改学生");
            System.out.println("4 查看学生");
            System.out.println("5 退出");
            System.out.println("请输入您的选择:");

            String choice = sc.next();

            switch (choice) {
                case "1":
                    // System.out.println("添加学生");
                    addStudent(list);
                    break;
                case "2":
                    // System.out.println("删除学生");
                    deleteStudent(list);
                    break;
                case "3":
                    // System.out.println("修改学生");
                    updateStudent(list);
                    break;
                case "4":
                    // System.out.println("查看学生");
                    queryStudents(list);
                    break;
                case "5":
                    System.out.println("感谢您的使用");
                    break lo; // 退出死循环;
                default:
                    System.out.println("您的输入有误");
                    break;
            }
        }

    }

    // 修改学生的方法
    public static void updateStudent(ArrayList<Student> list) {
        // 给出录入的提示信息;
        System.out.println("请输入您要修改的学生学号:");
        Scanner sc = new Scanner(System.in);
        String updateSid = sc.next();
        // 3. 调用getIndex方法, 查找该学号在集合中出现的索引位置
        int index = getIndex(list, updateSid);
        // 4. 根据索引判断, 学号在集合中是否存在
        if (index == -1) {
            // 不存在: 给出提示
            System.out.println("查无信息, 请重新输入");
        } else {
            // 存在: 接收新的学生信息
            System.out.println("请输入新的学生姓名:");
            String name = sc.next();
            System.out.println("请输入新的学生年龄:");
            int age = sc.nextInt();
            System.out.println("请输入新的学生生日:");
            String birthday = sc.next();
            // 封装为新的学生对象
            Student stu = new Student(updateSid, name, age, birthday);
            // 调用集合的set方法, 完成修改
            list.set(index, stu);
            System.out.println("修改成功!");
        }
    }

    // 删除学生的方法
    public static void deleteStudent(ArrayList<Student> list) {
        // 1. 给出提示信息 (请输入您要删除的学号)
        System.out.println("请输入您要删除的学生学号:");
        // 2. 键盘接收要删除的学号
        Scanner sc = new Scanner(System.in);
        String deleteSid = sc.next();
        // 3. 调用getIndex方法, 查找该学号在集合中出现的索引位置
        int index = getIndex(list, deleteSid);
        // 4. 根据索引判断, 学号在集合中是否存在
        if (index == -1) {
            // 不存在: 给出提示
            System.out.println("查无信息, 请重新输入");
        } else {
            // 存在:删除
            list.remove(index);
            System.out.println("删除成功!");
        }
    }

    // 查看学生的方法
    public static void queryStudents(ArrayList<Student> list) {
        // 1. 判断集合中是否存在数据, 如果不存在直接给出提示
        if (list.size() == 0) {
            System.out.println("无信息, 请添加后重新查询");
            return;
        }
        // 2. 存在: 展示表头数据
        System.out.println("学号\t\t姓名\t年龄\t生日");    //制表符\t
        // 3. 遍历集合, 获取每一个学生对象的信息, 打印在控制台
        for (int i = 0; i < list.size(); i++) {
            Student stu = list.get(i);
            System.out.println(stu.getSid() + "\t" + stu.getName() + "\t" + stu.getAge() + "\t\t" + stu.getBirthday());
        }
    }

    // 添加学生的方法
    public static void addStudent(ArrayList<Student> list) {
        Scanner sc = new Scanner(System.in);
        // 1. 给出录入的提示信息

        String sid;

        while (true) {
            System.out.println("请输入学号:");
            sid = sc.next();

            int index = getIndex(list, sid);

            if (index == -1) {
                // sid不存在, 学号可以使用
                break;
            }
        }

        System.out.println("请输入姓名:");
        String name = sc.next();
        System.out.println("请输入年龄:");
        int age = sc.nextInt();
        System.out.println("请输入生日:");
        String birthday = sc.next();
        // 2. 将键盘录入的信息封装为学生对象
        Student stu = new Student(sid, name, age, birthday);
        // 3. 将封装好的学生对象, 添加到集合容器当中
        list.add(stu);
        // 4. 给出添加成功的提示信息
        System.out.println("添加成功!");
    }

    /*
     * getIndex : 接收一个集合对象, 接收一个学生学号
     * 
     * 查找这个学号, 在集合中出现的索引位置
     */
    public static int getIndex(ArrayList<Student> list, String sid) {
        // 1. 假设传入的学号, 在集合中不存在
        int index = -1;
        // 2. 遍历集合, 获取每一个学生对象, 准备进行查找
        for (int i = 0; i < list.size(); i++) {
            Student stu = list.get(i);
            // 3. 获取每一个学生对象的学号
            String id = stu.getSid();
            // 4. 使用获取出的学生学号, 和传入的学号(查找的学号)进行比对
            if (id.equals(sid)) {
                // 存在: 让index变量记录正确的索引位置
                index = i;
            }
        }
        return index;
    }
}

注意:nextInt()nextline()方法在一起会使得nextline()丢失一次录入的机会;
有时直接使用next()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值