Java中级语法

本文详细介绍了Java中的IDEA快捷键、访问修饰符的用法,深入讲解了封装、继承和多态的概念,包括super的使用、方法重写与覆盖以及动态绑定机制。此外,还探讨了Object类的equals、hashCode和toString方法,以及如何进行断点调试。文章通过实例展示了如何在实践中应用这些概念,帮助读者巩固和理解Java的中级语法。
摘要由CSDN通过智能技术生成

此文章是基础语法的后续。进阶中级

前言


以下是本篇文章正文内容,下面案例可供参考

1.IDEA快捷键

ctrl+D删除光标当前行

ctrl+alt+向下光标复制光标当前行

alt+/ 补全代码

自动导入该行需要的类:首先需要打开setting--Editor---General---Auto import,把所属java的框框打勾。可以使用Alt+enter

快速格式化代码:ctrl+alt+L

快速运行程序:alt+R(自己设定)

 生成构造器:alt+insert

查看一个类的层级关系ctrl+H

将光标放一个方法上,输入ctrl+B可以定位到方法(学到继承有用)

自动分配生成变量名,(在后面加.var)

 模板快捷键   main模板、sout模板、fori模板,然后回车

 包基本语法:package com.hspedu表示包名

包名命名规则:只能包含字母、数字、下划线、小圆点,不能数字开头不能是关键字和保留字 

一般命名以com.公司名.项目名.业务模块名

package的作用是申明当前类所在包,需要放在最上面,一个类最多只有一句package

,导入其他包放它下面

常用包:

java.lang.*基本包,不需要导入

java.util.*  系统提供工具包如Scanner

java.net.* 网络包

java.awt.*  java界面开发GUI

2.访问修饰符

public:对所有公开

protected:对子类、本类或同一个包的类公开

默认级别:没有修饰符,向同一个包、本类公开,不对子类公开

私有级别:private只有本类里面可以访问,不对外公开。

修饰类只有默认和public可以修饰类

3.面向对象编程(封装、继承、多态)

3.1封装encapsulation

封装就是把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过授权的操作(方法)。才能对数据操作。

封装实现步骤:1.将属性私有化【不能直接修改属性】

                         2.提供一个公共的方法set,用于对属性判断和赋值public void setXxx(类型 参数名)

                         3.提供一个公共的get方法用于获取属性值 public XX get()  

快速获得get、set方法

 get、set方法与构造器混和使用保护机制仍然存在,

package com.xiaoming;

public class Person {
    public static void main(String[] args)
    {
        ZZZ z=new ZZZ("lala",20,3000,"数据的");
        z.setName("sdasd");
        z.setAge(52);
        z.setSalary(2000);
        System.out.println(z.info());
    }

}

class ZZZ
{
    public String name;
    private int age;
    private int salary;
    private String job;

    public ZZZ(String name, int age, int salary, String job) {
            setSalary(salary);//这样构造器执行set方法仍然有保护机制
            this.setAge(age);
            setName(name);
            setJob(job);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length()>6)
        {
            System.out.println("不合理名字");
        }
        else
        {
            this.name = name;
        }

    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age>=1&&age<=120)
        {
            this.age = age;
        }
        else
        {
            System.out.println("不合理");
            this.age=18;//默认年纪
        }
    }

    public int getSalary() {
        //可以增加权限访问
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }
    public String info()
    {
        return "返回信息为"+name+"年龄"+age+"工资"+salary;
    }
}

3.2继承Extends

解决代码复用性,当多个类存在相同属性和方法,可以从这些类抽象出父类,在父类中定义的属性和方法,所有子类不需要重新定义,只需要通过extends声明继承父类即可。

class  子类 extends 父类,子类会自动拥有父类定义的属性和方法(就是因为super作用)

public class Students {//父类
    public  String name;
    public int age;
    public double score;
    public void setScore(double score) {
        this.score = score;
    }
    public void show()
    {
        System.out.println("学生名字"+name+" 年纪"+age+" 分数"+score);
    }
}



public class pupil extends Students {//继承
    public void testing()
    {
        System.out.println("正在考试"+name);
    }
}

继承细节:

                1.子类继承父类所有属性方法。但是父类私有(private)属性和私有方法不可以直接访问。可以通过父类提供的公共方法得到(通过返回值方式获得私有属性,或者父类公共方法调用私有方法)

                2.子类必须调用父类构造器,完成父类初始化,在创建子类对象时,不管使用子类哪一个构造器,默认情况下都会调用父类无参构造器,若父类没有无参构造器则必须在子类的构造器用super指定使用父类的哪一个构造器完成父类属性初始化工作否则编译不通过。

注意:子类和父类还不是一个对象,只是子类有父类属性和方法。

                3.指定调用父类某个构造器,直接显示调用 super(构造器形参参数)

                4.super调用构造器时使用,必须放在子类构造器第一行,只能在构造器中使用。

                5.super()与this()都必须放在构造器里的第一行,因此这两个方法不可以同时存在一个构造器中

                6.Object类是java所有类的父类,而且父类构造器被调用不仅仅局限于直接父类,会一直追溯到Object类。(father类构造器随着new son()被调用,father的父类Object构造器也会被调用)

                7.子类只能继承一个父类,java是单继承机制

                8.不能滥用继承,子类和父类之间必须满足is-a逻辑关系

//父类

public class father {
    public String name="lal";
    protected String work="工人";
    private int age=18;
    public father() {
        System.out.println("父类无参构造物被调用");
    }
    public father(String name, String work, int age) {
        this.name = name;
        this.work = work;
        this.age = age;
        System.out.println("新father父类有参构造物被调用");
    }
    public void getwork()
    {
        System.out.println("这人工作是"+work);
    }
    public void getage()
    {
        System.out.println("这人年纪是"+age);
    }

}

//子类
public class son extends father{
    public son()
    {
        //super();//默认调用父类无参构造器
        super("smith","白领",10);//调用另一个父类有参构造器,在没有无参构造器必须申明
        System.out.println("子类无参构造");
    }
    public void speak()//子类方法
    {
        System.out.println("我爸的名字是"+name+work);
        getwork();
        getage();
    }
}
//测试
public class test {
    public static void main(String[] args)
    {
        son s=new son();
        s.speak();

    }
}

继承本质:当子类继承父类,创建子类对象时,先加载类信息、在堆里分配对象空间并指向常量区一些参数。栈里生成对象名。查找规则:先看子类是否有该属性,有并且可以访问返回该信息,若不能访问可以使用公共方法,如果子类没有就向上一级父类查找(从子向父查)。

注意:若子类属性是private,而父类是public,也不可以访问到父类的,被子类private“卡住”,只能通过公共方法获得子类属性

public class ExtensTheory {
    public static void main(String[] args)
    {
        son s=new son();
        System.out.println(s.age);
        System.out.println(s.name);
        System.out.println(s.hobby);
    }
}
class Grandpa
{
    String name="大头爷爷";
    String hobby="旅游";
}
class Father extends Grandpa
{
    String name="大头爸爸";
    int age=39;
}
class son extends Father
{
    String name="大头儿子";
}

 继承super练习题

package com.extendss;

import java.awt.*;
public class ExtendsExercise{
    public static void main(String[] args)
    {
        PC pc=new PC("i5",100,1500,"联想");
        pc.printinfo();
        Notepad pad=new Notepad("ios15",100,500,"red");
        pad.printinfo();
    }
}
class Computer
{
    private String CPU;
    private int memory;
    private int disk;

    public Computer(String CPU, int memory, int disk) {//构造器
        this.CPU = CPU;
        this.memory = memory;
        this.disk = disk;
    }
    public String getDetail()
    {
        return "电脑cpu是"+CPU+" 内存是:"+memory+" 硬盘是:"+disk;
    }
}
class PC extends Computer//默认调用父类无参构造器但是父类没有无参,必须用super指定
{
    private String broad;
    public PC(String CPU, int memory, int disk, String broad) {//父类构造器通过super(参数)完成父类属性初始化,
        super(CPU, memory, disk);//PC里也可以没有这三个父类参数,直接在super指定值,因为父类构造器有三个参数。
        this.broad = broad;
    }
    public String getBroad() {
        return broad;
    }
    public void setBroad(String broad) {
        this.broad = broad;
    }
    public void printinfo()
    {

        System.out.println("电脑信息是 "+getDetail()+" "+getBroad());
        System.out.println();
    }
}
class Notepad extends Computer
{
    private String color;
    public Notepad(String CPU, int memory, int disk, String color) {
        super(CPU, memory, disk);
        this.color = color;
    }
    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public void printinfo()
    {
        System.out.println("pad信息是"+getDetail()+" "+getColor());
    }
}

3.3super用法

super代表父类引用,用于访问父类方法、属性、构造器,但是不能访问父类private的属性和方法。找方法会从本类找,有则调用,否则向上父类依次寻找,若方法存在不可以访问,报错,若没找到,显示方法不存在

访问父类构造器必须在自己构造器使用调用。如下演示

public class A {
    public int n1=100;
    protected  int n2=200;
    int n3=300;
    private int n4=400;
    public A()
    {
        System.out.println("调用A默认无参构造器");
    }
    public A(int n1, int n2, int n3,int n4) {
        this.n1 = n1;
        this.n2 = n2;
        this.n3 = n3;
        this.n4=n4;
    }
    public void test100(){
        System.out.println("调用Atest100");
    }
    protected void test200(){
        System.out.println("调用Atest200");
    }
    void test300(){
        System.out.println("调用Atest300");
    }
    private void test400(){
        System.out.println("调用Atest400");
    }
}

public class B extends A {
    public B()
    {
        super(400,500,600,700);//构造器可以访问私有属性
        System.out.println("调用B默认无参构造器");
    }
    public void hi()
    {
        System.out.println(super.n1+""+super.n2+""+super.n3);
       super.test100();
       super.test200();
       super.test300();
    }
}

 调用父类构造器的好处在于分工明确,父类属性由super父类构造器初始化,子类属性由子类构造器初始化。

 注意:在有继承关系的A,B类

找方法会从本类找,有则调用,否则向上父类依次寻找,若方法存在不可以访问,报错,若没找到,显示方法不存在。

在子类里this.方法()与方法()   一样作用,都会先从本类找再去父类爷爷类找

而是super.方法()。是直接去查找父类或者爷爷类找方法。不查找本类!!    (查找属性也是一样)

super的访问不仅仅局限于直接父类,如果条件允许,可以访问爷爷类中同名属性或者方法(查找遵循就近原则,先子再父。也要遵循访问权限相关规则)

 3.4方法重写、覆盖Override

在继承关系中,方法覆盖就是子类方法与父类方法的某一个方法名称、形参参数也要一样、返回类型完全一样。那么子类就是覆盖了父类的方法(这里不仅仅局限于子类与父类,爷爷也是。子与爷覆盖)

方法重写细节:

        子类的返回类型和父类的返回类型一样或者是父类返回类型的子类,也可以是方法重写

比如:父类返回类型是Object,子类返回类型是String。其他参数一样。那么这两个也是方法重载(Object是java所有类的父类)

在方法重写时,子类方法权限修饰符不可以比父类方法的访问权限还小,只能比父类大,在其他都一样的情况下可以构成方法重写

public class A {
}

public class B extends A{
}


public class Animal {
    public void cry()
    {
        System.out.println("Animals方法");
    }
    public Object getinfo()//Object是所有类的父类
    {
        return null;
    }
    public A get()//B是A子类
    {
        return null;
    }
    protected void gets()//父类方法访问权限小
    {
        System.out.println("Animals的gets方法");
    }
}

public class Dog extends Animal {
    public void cry()
    {
        System.out.println("Dog方法");
    }
    public String getinfo()
    {
        return "Dog方法的getinfo";
    }
    public B getB()
    {
        return null;
    }
    public void gets()//子类访问权限比父类大
    {
        System.out.println("Dog的gets方法");
    }
}


 3.5多态polymorphic

方法或对象具有多种形态,多态是建立在封装和继承之上的。重写与重载体现多态

对象的多态:1.一个对象的编译类型和运行类型可以不一致。例如Animal animal=new Dog():编译类型是animal,运行类型是Dog

2.编译类型在定义对象时就确定了,不可以改变

3.运行类型是可以改变的

4.编译类型看定义时=号左边,运行类型看=号右边 animal=new Cat()运行类型转为Cat,编译不变。

方法的执行主要是看运行类型,运行类型是什么,就执行哪个类的方法               

public class Animal {
    public Animal()
    {
        System.out.println("Animals类");
    }
    public void cry()
    {
        System.out.println("动物在叫");
    }
}

public class Dog extends Animal{
    public Dog()
    {
        System.out.println("Dog类");
    }
    public void cry() {
        System.out.println("cat cry()小狗叫");
    }
}

public class Cat extends Animal {
    public Cat()
    {
        System.out.println("猫类");
    }
    public void cry() {
        System.out.println("cat cry()小猫叫");
    }
}

public class PolyObject {
    public static void main(String[] args)
    {
        Animal animal=new Dog();//animal是编译类型,Dog是运行类型,先编译在运行,先执行animal构造方法再执行Dog
        animal.cry();//执行到该行时,运行类型是Dog,所以是以Dog的cry
        animal=new Cat();//编译类型还是animal,运行类型时Cat
        animal.cry();
    }
}

多态的前提是:两个对象或者类是存在继承关系

多态的向上转型:父类引用指向子类对象 ----> 父类类型   引用名=new  子类类型()

Object obj=new Cat()也可以。一切类都是Object子类。Object也是Cat父类

在定义方法时,形参时父类类型引用名,而在调用方法时实参是具体子类引用名

obj可以调用父类中所有成员(注意访问权限),因为在编译阶段能调用哪些成员是由编译类型决定。

不可以调用子类特有成员(允许子类没有父类有,会调用父类,但是父类没有子类有的不能调用)

最终运行效果看运行类型,先从子类,看子类具体实现,若子类没有去父类找方法

public class Animal {
    private String name;
    public Animal(String name)
    {
        this.name=name;
        System.out.println("Animal构造器");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class Dog extends Animal {
    public Dog(String name)
    {
        super(name);
    }
}
public class Cat extends Animal {
    public Cat(String name)
    {
        super(name);
    }
}

public class Food {
    private String name;

    public Food(String name) {
        this.name = name;
        System.out.println("Food构造器");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class Fish extends Food{
    public Fish(String name)
    {
        super(name);
    }
}
public class Bone extends Food {
    public Bone(String name)
    {
        super(name);
    }
}

public class Master {
    private String name;
    public Master(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void feed(Animal animal,Food food)//这里其实是涉及到动态绑定
    {
        System.out.println("主人名字"+name+" 给"+animal.getName()+" 吃"+food.getName());
    }
}

public class Poly01 {
    public static void main(String[] args)
    {
        Master master=new Master("汤姆");
        Dog dog=new Dog("小黑");
        Bone bone=new Bone("骨头");
        Cat cat=new Cat("小花");
        Fish fish=new Fish("小鱼");
        master.feed(dog,bone);//这里做的工作就相当于Animal animal=new Dog()==Dog dog
        master.feed(cat,fish);
    }
}

anminal编译类型是Animal,可以接收Animal子类的对象,然后以子类对象为运行类型,执行操作


多态的向下转型:(他的出现就是为了解决向上转型中不可以调用子类特有成员

语法:子类类型  子类引用名=(子类类型) 父类引用名

只能强转父类引用,不可以强转父类对象

要求父类的引用必须指向的是当前目标类型的对象(前面要有这句话Animal animal=new Cat(),animal才是指向Cat对象)

可以调用子类类型所有的成员

public class Animal {
    private String name;
    public Animal(String name)
    {
        this.name=name;
        System.out.println("Animal构造器");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void sleep()
    {
        System.out.println("睡");
    }
    public void run()
    {
        System.out.println("跑");
    }
}

public class Cat extends Animal {
    public Cat(String name)
    {
        super(name);
    }
    public void sleep()//重写
    {
        System.out.println("小猫睡");
    }
    public void catchMouse()
    {
        System.out.println("猫抓老鼠");
    }
}

public class PolyDetail {
    public static void main(String[] args)
    {
        Animal animal=new Cat("小黑");
        animal.sleep();//向上转型
        animal.run();
        ((Cat) animal).catchMouse();//(向下转型)把animal强转为子类类型,然后调用子类特有方法
    }
}

多态注意事项:属性没有重写的说法,属性的值看编译类型(左边),方法的值看运行类型右边

public class PolyDetail2 {
    public static void main(String[] args)
    {
        Base base=new Sub();//向上转型
        System.out.println(base.count);//20,属性的值看编译类型(左边)看编译类型
        Sub sub=(Sub)base;//向下转型
        System.out.println(sub.count);//30
    }
}
class Base
{
    int count=20;
}
class Sub extends Base
{
    int count=30;
}

instanceOf比较操作符,用于判断对象的运行类型是否是XX类型或者是否是XX类型的子类型

 多态练习题:

 4.动态绑定机制DynamicBinding

当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定

当调用属性时,没有动态绑定机制,哪里有申明属性那里就使用那个

动态绑定的经典应用是在于:在某一个方法里形参是父类引用,而在调用方法时,将一个子的引用传递给形参,(这里做到了向上转型)而这样实现了动态绑定,运行类型就是子类了,如同上面此方法public void feed(Animal animal,Food food),调用此方法时传入的是子类的 Cat cat= new Cat()的cat,而cat就是new Cat(),也就做了向上转型

 5.多态数组(多态的应用)

public class Person {
    private String name;
    private int age;
    public Person(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 String say()
    {
        return "姓名"+name+" 年纪"+age;
    }
}

public class Student extends Person{
    private int score;
    public Student(String name,int age,int score)
    {
        super(name,age);
        this.score=score;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public String say()
    {
        return super.say()+" 分数是"+score;//不仅仅重写say方法,也要用到父类say
    }
    public void study()
    {
        System.out.println("学生名字是:"+getName()+"正在学习"+" 考试分数是"+score);
    }
}

public class Teacher extends Person{
    private int salary;
    public Teacher(String name,int age,int salary)
    {
        super(name,age);
        this.salary=salary;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    public String say()
    {
        return super.say()+" 薪水是"+salary;
    }
    public void teach()
    {
        System.out.println("老师名字是:"+getName()+"正在授课"+" 薪水是:"+salary);
    }
}

public class PolyArr {
    public static void main(String[] args)
    {
        //要求创建1个Person对象、2个Teacher、2个Student,统一放在数组里
        //放在数组里,那么必须用父类来接收,父类引用可以指向子类对象
        Person[] person=new Person[5];//对象数组:person可以放Person对象,同时也就可以放子类对象
        person[0]=new Person("jack",20);//这里都是向上转型
        person[1]=new Teacher("mike",18,10000);
        person[2]=new Teacher("jone",22,13000);
        person[3]=new Student("小黑",10,60);
        person[4]=new Student("小明",8,70);
        for(int i=0;i<person.length;i++)
        {
            //person[i]的编译类型是Person,运行类型是根据实际的上面运行类型,由JVM判断
            System.out.println(person[i].say());//动态绑定机制
            //这里也可以使用类型判断和向下转型结合
            if(person[i] instanceof Student)
            {
                Student student=(Student)person[i];
                student.study();
            }
            else if(person[i] instanceof Teacher)
            {
                Teacher teacher=(Teacher)person[i];
                teacher.teach();
            }
            else if(person[i] instanceof Person){}
            else
            {
                System.out.println("输入有误");
            }

        }
        System.out.println("------------------");
        //向下转型,调用Student、Teacher类特有方法
        Student student1=(Student) person[3];
        student1.study();
        Student student2=(Student) person[4];
        student2.study();
        Teacher teacher1=(Teacher) person[1];
        teacher1.teach();
        Teacher teacher2=(Teacher) person[2];
        teacher2.teach();
    }
}

6.Object类详解

基本数据类型的比较只看值是否一样。

 查看源码:将光标放方法上,然后ctrl+b或者右击方法--goto---Declaration

6.1equals方法重写:

public class EqualsExercise01 {
    public static void main(String[] args)
    {
        Person1 p1=new Person1("jack",18,'男');
        Person1 p2=new Person1("jack",18,'男');
        //System.out.println(p1.equals(p2));//假,没有重写的equals只判断引用类型地址
        System.out.println(p1.equals(p2));
    }
}

class Person1
{
    private String name;
    private int age;
    private char gender;
    public Person1(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    //重写Object类的euqals方法
    public boolean equals(Object object)
    {//如果比较的是同一个对象,返回ture
        if(this==object)
        {
            return true;
        }
        else if(object instanceof Person1)
        {//向下转型,因为需要子类的属性
            Person1 p=(Person1)object;
            return this.name.equals(p.name) && this.age==p.age && this.gender==p.gender;
        }
        return false;
    }
    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 char getGender() {
        return gender;
    }
    public void setGender(char gender) {
        this.gender = gender;
    }
}

 6.2hashCode方法

hashCode()具有提高哈希结构容器的效率、两个引用,如果指向同一个对象,则哈希值肯定相同。哈希值是根据地址号来编写的,哈希值不完全等价于地址

6.3toString()方法

默认返回:全类名+@+哈希值的十六进制(查看Object类的toString())

 重写toString()方法

 public String toString() {
        return "Person1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }

 当直接输入一个对象时,toString()方法会被默认调用。比如System.out.println(person);就会自动调用person.toString()

 6.4finalize()方法

当对象被回收时,系统自动调用对象的finalize(),子类可以重写该方法,做一些释放资源的操作。

什么时候被回收,当某个对象没有任何引用时,jvm就认为这个对象是一个垃圾对象,会使用垃圾回收机制销毁对象,在销毁对象前,会调用finalize()。垃圾回收机制时系统决定的,也可以通过System.gc()主动触发垃圾回收机制

若不重写finalize,那么会调用Object类的finalize,默认处理

若重写finalize,就可以实现自己的逻辑——直接输入finalize会有提示

一般实际工作不会使用

 @Override
    protected void finalize() throws Throwable {
        System.out.println("销毁对象");
    }

7断点调试Debug

提示:在断点调试过程中,是运行状态,是对象的运行类型来执行的.

程序运行到断点会停止,然后一步一步往下调试。调试过程中,可以看到各个变量的值,出错的话,调试到出错代码会显示错误。分析找出bug

F5(跳入方法内)、Alt+Shift+F7强制进入方法内、F6逐行执行、F7跳出方法、F8执行到下一个断点

将光标放在变量上,会显示最新数据,

断点可以在Debug过程中,动态下断点,

下断点位置是没有执行到的。


总结

        以上就是Java中级语法要讲的内容,中级部分实践项目另写一篇。后续将写java高级部分

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值