java学习记录十:接口、多态、内部类

一、接口

1.接口解释

接口是一个方法的集合,主要是用来定义方法,包含常量,抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8新加),私有方法(jdk9新加)。接口的定义,它与定义类方式相似,但是使用 interface 关键字。它也会被编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型。接口不能创建对象,所有需要被实现。通过创建这个类的对象,来实现接口的方法。否则不创建对象的话,实现的类必须是一个抽象类。接口就好像是对类的一个补充,所有不同的类都可以从从接口中获取同样的方法,节省代码量。类中的方法是一个类特有的,多个类需要实现某种功能就可以使用接口。

2.写法

public interface 接口名称 {
    // 常量(jdk7及其以前)
    // 抽象方法(jdk7及其以前)
    // 默认方法(jdk8)
    // 静态方法(jdk8)
    // 私有方法(jdk9)
// 常量(jdk7及其以前) 使用public static final关键字修饰,这三个关键字都可以省略
    public static final int NUM1 = 10;
    int NUM2 = 20;
        // 抽象方法(jdk7及其以前) 使用public abstract关键字修饰,这2个关键字都可以省略
    public abstract void method1();
    void method2();
// 默认方法(jdk8) 使用public default关键字修饰,public可以省略,default不可以省略
    public default void method3(){
        System.out.println("默认方法 method3");
    }
  // 静态方法(jdk8) 使用public static关键字修饰,public可以省略,static不可以省略
    public static void method4(){
        System.out.println("静态方法 method4");
    }
 // 私有方法(jdk9) 使用private关键字修饰,private不可以省略
    private static void method5(){
        System.out.println("私有静态方法  method5");
    }
//私有方法2
 private void method6(){
        System.out.println("私有非静态方法  method6");
    }

}

3.接口使用注意点

  • 接口是java语言中的一种引用数据类型
  • 接口中的成员:
    • 常量(jdk7及其以前)
    • 抽象方法(jdk7及其以前)
    • 默认方法和静态方法(jdk8额外增加)
    • 私有方法(jdk9额外增加)
  • 定义接口使用interface关键字—接口编译后产生class文件
  • 接口不能创建对象,需要使用实现类实现接口(类似于继承),实现接口的类叫做实现类(子类)
  • 创建接口文件时,idea需要定义是interface类型,不是interface后缀文件。

二、接口实现

1.接口实现解释

接口是不能创建对象,要实现接口的功能一般都是一个类实现接口,再创建对象,实现和继承类似。实现接口的类叫实现类,也可以叫接口的子类,实现的关键字是implements

2.写法


interface IA{
    public void show1();
}

interface IB{
    public void show2();
}
class Fu{}
//一个类可以同时实现多个接口,
public class Zi implements IA ,IB{
    public void show1(){
    }
    public void show2(){
    }
}
//类可以先继承再实现,一定要先继承。
public class Zi2 extends Fu implements IA,IB{//一定要先继承,后实现
}

3.接口实现注意点

  • 实现接口使用implements关键字
  • 一个类同时实现多个接口时,要用逗号隔开
  • 一个类可以同时继承和实现,但是继承一定要写在前面。
  • 实现接口时一定要重写接口的抽象方法。

三、接口中成员的访问

1.解释

外部想要访问接口中的成员需要遵循一定的规则

2.写法

//IA文件
public interface IA {
    // 常量
    public static final int NUM = 10;

    // 抽象方法
    public abstract void method1();

    // 默认方法
    public default void method2(){
        //method4();
        //method5();
        System.out.println("IA 接口中的默认方法method2");
    }

    // 静态方法
    public static void method3(){
        //method5();
        System.out.println("IA 接口中的静态方法method3");
    }

    // 私有方法
    private void method4(){
        System.out.println("IA 接口中的私有方法method4");
    }

    private static void method5(){
        System.out.println("IA 接口中的私有方法method5");
    }
}
//Imp文件
public class Imp implements IA {
    // 重写接口的抽象方法
    @Override
    public void method1() {
        System.out.println("实现类重写IA接口中的抽象方法");
    }

    // 重写接口的默认方法
    @Override
    public void method2() {
        System.out.println("实现类重写IA接口中的默认方法");
    }

}

//main文件
public class Test {
    public static void main(String[] args) {
        // 访问接口常量
        System.out.println(IA.NUM);// 10  推荐
        //System.out.println(Imp.NUM);// 10 不推荐 常量被实现类继承了

        // 创建实现类对象调用方法
        Imp imp = new Imp();

        // 访问抽象方法
        imp.method1();

        // 访问默认方法
        imp.method2();

        // 接口名访问静态方法
        IA.method3();
        //Imp.method3();// 编译报错,没有继承
    }
}

3.注意事项

  • 常量:主要是供接口名直接访问
  • 抽象类:就是用来给实现类重写的
  • 默认方法:只供实现类重写或者实现类对象直接调用,接口不能调用。
  • 静态方法:只供接口名直接调用,实现类不能访问,没有继承过来。
  • 私有方法:不管是静态还是非静态的,只能在本接口中调用,

四、多实现时的冲突

1.解释

即一个类实现多个接口时,几个接口中相同的成员会发生继承冲突。

2.写法


interface A{
     //公共常量
    public static final int NUM1 = 10;
        //公共私有方法
   public abstract void method();
   //公有默认方法
    public default void method(){
        System.out.println("A 接口的默认方法method");
    }
}
interface B{
     //公共常量
    public static final int NUM1 = 20;
    //单个常量
    public static final int NUM2 = 30;
    //公共私有方法
   public abstract void method();
     //公有默认方法
    public default void method(){
        System.out.println("A 接口的默认方法method");
    }
}
class Imp implements A,B{
 @Override
    public void method() {
        System.out.println("实现类重写");
    }
      @Override
    public void method() {
        System.out.println("实现类重写的默认方法");
    }

}
public class Test {
    public static void main(String[] args) {
        /*
            公有静态常量的冲突: 如果多个接口中有相同的常量,那么实现类就无法继承,会报错
            公有抽象方法的冲突:实现类只需要重写一个 
            公有默认方法的冲突:实现类必须重写一次最终版本 
            公有静态方法的冲突:静态方法是直接属于接口的,不能被继承,所以不存在冲突
            私有方法只能在本接口中直接使用,不存在冲突
         */
        //System.out.println(Imp.NUM1);// 编译报错,无法访问
        System.out.println(Imp.NUM2);// 30
          Imp imp = new Imp();
        imp.method();
    }
}

3.注意点

  • 公有静态常量的冲突: 如果多个接口中有相同的常量,那么实现类就无法继承,会报错
  • 公有抽象方法的冲突:实现类只需要重写一个
  • 公有默认方法的冲突:实现类必须重写一次最终版本
  • 公有静态方法的冲突:静态方法是直接属于接口的,不能被继承,所以不存在冲突
  • 私有方法只能在本接口中直接使用,不存在冲突

五、接口多继承的冲突

1.解释

接口与接口之间的关系是继承,接口可以实现多继承,不同于类与类之间只能实现单继承。

2.写法

interface A{
    public static final int NUM1 = 10;
    public abstract void method();
     public default void method(){
        System.out.println("A 接口中的默认方法method");
    }
}
interface B{
    public static final int NUM1 = 20;
    public static final int NUM2 = 30;
    public abstract void method();
     public default void method2(){
        System.out.println("A 接口中的默认方法method");
    }
}
interface C extends A,B{
 @Override
    public void method() {
        System.out.println("实现接口的抽象方法");
    }
     @Override
    public default void method2() {
        System.out.println("重写父接口中的method方法");
    }
}
public class Test {
    public static void main(String[] args) {
        /*
            公有静态常量的冲突: 子接口无法继承父接口中冲突的常量,alt+回车可以解决冲突
            公有抽象方法的冲突:子接口只会继承一个有冲突的抽象方法
            公有默认方法的冲突:子接口中必须重写一次有冲突的默认方法
            面试题:
                实现类重写接口中的默认方法,不需要加default
                子接口重写父接口中的默认方法,必须加default
           公有静态方法和私有方法:不存在冲突,因为静态方法是直接属于接口的,只供本接口直接调用

         */
        //System.out.println(C.NUM1);// 编译报错,说明无法继承
        System.out.println(C.NUM2);// 30
         Imp imp = new Imp();
        imp.method();
         imp.method2();
    }
}

3.注意点

  • 公有静态常量的冲突:子接口无法继承父接口中冲突的常量
  • 公有抽象方法的冲突:子接口只会继承一个有冲突的抽象方法
  • 公有默认方法的冲突:子接口中必须重写一次有冲突的默认方法(注意要加default)
  • 公有静态方法和私有方法的冲突:
    不冲突,因为静态方法是直接属于接口的,只能使用本接口直接访问,而私有方法只能在接口中访问,也没有冲突

六、实现类继承父类又实现接口时的冲突

1.解释

即在继承父类和实现接口时,父类和父接口中的成员发生的冲突

2.写法

class Fu{
    public static final int NUM1 = 10;
    public static final int NUM2 = 100;
     public void method(){
        System.out.println("Fu 类中的默认方法method");
    }
     public static void method(){
        System.out.println("Fu 类中的静态方法method");
    }
}
interface A{
    public static final int NUM1 = 20;
    public abstract void method();
    public default void method(){
        System.out.println("A 接口中的默认方法method");
    }
     public static void method(){
        System.out.println("A 接口中的静态方法method");
    }

}
//抽象方法一定定义在抽象类中
abstract class Fu2{
    public abstract void method();
}
class Zi extends Fu2 implements A{
    public abstract void method();
}
class Zi2 extends Fu implements A{

}
public class Test {
    public static void main(String[] args) {
        /*
            公有静态常量的冲突:子类无法继承有冲突的常量
              公有抽象方法的冲突:子类必须重写一次有冲突的抽象方法
              公有默认方法的冲突:优先访问父类的
               公有静态方法的冲突:只会访问父类的静态方法
               父类和接口的私有方法:不存在冲突,因为子类不会继承
         */
        //System.out.println(Zi.NUM1);// 编译报错
        System.out.println(Zi.NUM2);
         Zi zi2 = new Zi2();
        zi2.method();
         Zi zi = new Zi();
        zi.method();// Fu 类中的默认方法method

    }
}

3.注意点

  • 公有静态常量的冲突:子类无法继承有冲突的常量
  • 公有抽象方法的冲突:子类必须重写一次有冲突的抽象方法
  • 公有默认方法的冲突:优先访问父类的
  • 公有静态方法的冲突:只会访问父类的静态方法
  • 私有方法的冲突: 不存在冲突

七、多态

1.解释

多态是面向对象三大特征之一:封装,继承,多态。
同一行为,可以通过不同的事物,来体现出不同的形态,多态,描述的就是这样的状态。比如跑的动作,小猫、小狗和大象,跑起来是不一样的。比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。要出现多态,一定要有继承或实现,方法要重写,且父类引用指向子类对象.多态就是指同一行为,不同对象具有不同的表现形式.

2.写法


//父类 变量名  =  new 子类()
//这就是父类引用指向子类对象.
class Animal{
    public void eat(){
        System.out.println("吃东西");
    }
}

class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
}
public class Test1 {
    public static void main(String[] args) {
        // 父类引用指向子类对象
        Animal anl = new Dog();// 多态
        anl.eat();// 狗吃骨头...
    }
}

3.注意点

多态出现的前提

  1. 继承或者实现【二选一】
  2. 父类引用指向子类对象\接口引用指向实现类对象【格式体现】
  3. 方法的重写【意义体现:不重写,无意义】

4.多态访问成员

class Animal{
    int num = 10;
    public void method1(){
        System.out.println("Animal 非静态method1方法");
    }
    public static void method2(){
        System.out.println("Animal 静态method2方法");
    }
}
class Dog extends Animal{
    int num = 20;

    public void method1(){
        System.out.println("Dog 非静态method1方法");
    }
    public static void method2(){
        System.out.println("Dog 静态method2方法");
    }
}

public class Test {
    public static void main(String[] args) {
        // 父类的引用指向子类的对象
        Animal anl = new Dog();
        System.out.println(anl.num);// 10

        anl.method1();// Dog 非静态method1方法,必须父类要有这个方法,不然会报错。因为编译的时候是看左边

        anl.method2();// Animal 静态method2方法

    }
}

成员变量:编译看父类,运行看父类(编译看左边,运行看左边),即访问的是父类的
成员方法:
非静态方法:编译看父类,运行看子类(编译看左边,运行看右边),即调用的是子类的非静态方法
静态方法: 编译看父类,运行看父类(编译看左边,运行看左边),即调用的是父类的静态方法
结论:除了非静态方法是编译看父类,运行看子类,其余都是看父类,即多态时子类调用的方法,父类一定要有。因为编译的时候是看父类。

5.多态出现的情况

1.普通父类多态

public class Fu{}
public class Zi extends Fu{}
public class Demo{
    public static void main(String[] args){
        Fu f = new Zi();//左边是一个“父类”
    }
}

2.抽象父类多态

public abstract class Fu{}
public class Zi extends Fu{}
public class Demo{
    public static void main(String[] args){
        Fu f = new Zi();//左边是一个“父类”
    }
}

3.父接口多态

public interface A{}
public class AImp implements A{}
public class Demo{
    public static void main(String[] args){
        A a = new AImp();
    }
}

6.多态使用场景

1. 变量多态

  1. 解释
    父类类型的变量指向子类类型的对象, 如果变量的类型为父类类型,该变量就可以接收该父类类型的对象或者其所有子类对象
  2. 写法
class Animal{
    public void eat(){
        System.out.println("吃东西...");
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
public class Test {
    public static void main(String[] args) {
    //这就是变量多态,可以使用父类的方法,其实完全可以使用继承,意义不大
        Animal anl = new Dog();
        anl.eat();
    }
}

2.形参多态

  1. 解释
    参数类型为父类类型,该参数就可以接收该父类类型的对象或者其所有子类对象,这样就可以把不同的子类的对象作为实参来传进方法中,形参多态就是扩大了传参类型。
  2. 写法
class Animal{
    public void eat(){
        System.out.println("吃东西...");
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Test {
    public static void main(String[] args) {
        // 形参多态:参数类型为父类类型,该参数就可以接收该父类类型的对象或者其所有子类对象
        Dog d = new Dog();
        method(d);
       Cat c = new Cat();
        method(c);
    }

    // 需求: 定义一个方法,带有一个参数,该参数可以接收Animal类对象以及Animal类的所有子类对象
    //可以通过这个方法来调用不同子类对象里的方法。
    //这里就可以传Dog类型和Cat类型了。放大了参数类型,不再限于某个类型了。以前都是String和int之类的。
    public static void method(Animal anl){
        anl.eat();
    }

}

3.返回值多态

  1. 解释
    如果返回值类型为父类类型,那么就可以返回该父类类型的对象或者其所有子类对象,返回值多态即扩大了返回类型。可以返回多种类型的对象,但都是在一个父类里的。
  2. 写法
class Animal{
    public void eat(){
        System.out.println("吃东西...");
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Test {
    public static void main(String[] args) {
        // 返回值多态:如果返回值类型为父类类型,那么就可以返回该父类类型的对象或者其所有子类对象
        Animal anl = method();
        anl.eat();
    }

    public static Animal method(){
        //return new Animal();
        //return new Dog();
        return new Cat();
    }

    public static Animal method1(){
        if (1==1){
            // 条件1成立
            return new Animal();
        }else if (2==2){
            // 条件2成立
            return new Dog();
        }else{
            // 否则
            return new Cat();
        }
    }
}

7.多态的好处和弊端

1.好处

  • 提高了代码的复用性,子类能共用父类功能

2.弊端

  • 无法访问子类特有功能,因为必须父类有的成员,子类才能有。
class Animal{
    public void eat(){
        System.out.println("吃东西...");
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
    // 特有的功能
    public void lookHome(){
        System.out.println("狗在看家...");
    }
}
public class Test {
    public static void main(String[] args) {
        // 父类的引用指向子类的对象
        Animal anl = new Dog();
        anl.eat();//可以访问,因为父类有这个方法,编译不会报错。
        //anl.lookHome();// 编译报错,因为多态成员访问的特点是,编译看父类,而父类中没有子类独有的功能
    }
}

八、引用类型转换

1.解释

基本类型之间可以转换,引用类型之间也可以转换,父类转子类,是向下转型,需要手动强制转换,而子类转为父类,是默认的。从右往坐看,什么类型转什么类型,转型可以使多态下的子类转型为自己的类型,这样可以调用自己的特有方法了。

2.写法

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

    // 特有的功能
    public void lookHome(){
        System.out.println("狗在看家...");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}
class Person{}
public class Test {
    public static void main(String[] args) {
        // 向上转型:
        Animal anl = new Dog();
        // 向下转型:Animal 类转Dog类
        Dog dog = (Dog)anl;

        System.out.println("===================================");
        // 注意:右边父类类型的变量一定要指向要转型的子类类型的对象,即一定要存在多态,
        //Animal anl1 = new Animal(); //不存在转型
        //Dog d1 = (Dog)anl1;// 运行报错,类型转换异常ClassCastException
        
        //Animal anl2 = new Cat(); //Cat类不能转Dog类
        //Dog d2 = (Dog)anl2;// 运行报错,类型转换异常ClassCastException

        //Animal anl3 = new Person();// 编译报错,因为Animal和Person不是父子关系
        //Animal anl3 = (Animal) new Person();// 编译报错,因为Animal和Person不是父子关系

    }
}

3.使用注意点

  • 向下转型的时候:右边父类类型的变量一定要指向要转型的子类类型的对象
  • 不管是向上转型还是向下转型,一定满足父子类关系或者实现关系
  • 转型是为了让多态子类对象使用自己的特有方法,这样即使父类的成员不存在的,也不会报错了, 解决了多态的弊端。

九、instanceof关键字

1.解释

在引用类型转换的时候很容易出现类型转换异常,所以为了提高代码的严谨性,转型之前得先判断一下,防止转型失败报错。
判断前面变量指向的对象类型是否是后面的数据类型:
如果前面变量指向的对象类型是属于后面的数据类型,那么就返回true
如果前面变量指向的对象类型不是属于后面的数据类型,那么就返回false

2.写法


          // 向上转型
          Animal anl = new Cat();
         // 向下转型
        //Dog  d = (Dog)anl;// 运行的时候会出现类型转换异常,因为anl属于cat类型
        // 先判断,再转型
       if (anl instanceof Dog){
            Dog  d = (Dog)anl;
        }
         System.out.println("正常结束");

五、内部类

1.解释

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类

比如,汽车类Car 中包含发动机类Engine ,这时,Engine就可以使用内部类来描述,定义在成员位置。

2.写法

class Car { //外部类
    class Engine { //内部类

    }
}

3.访问特点

1.外部类访问内部类成员

public class Body {
    public void methodW1(){
        // 访问内部类的成员,
        //Body.Heart bh = new Body().new Heart();
        //也要先创建内部类对象
        Heart bh = new Heart();
        //然后直接访问即可
        System.out.println(bh.numN);// 10
        bh.methodN1();// 内部类的成员方法 methodN1
    }
    // 成员变量
    private int numW = 100;
    // 成员方法
    private void methodW2(){
        System.out.println("外部类的成员方法 methodW2");
    }

    // 内部类
    public class Heart{
        // 成员变量
        int numN = 10;
        // 成员方法
        public void methodN1(){
            System.out.println("内部类的成员方法 methodN1");
        }
        public void methodN2(){
            // 访问外部类的成员
            System.out.println(numW);
            methodW2();
        }
    }

}

2.其他类访问内部类成员
首先要创建内部类对象,然后直接方法成员即可

public class Test {
    public static void main(String[] args) {
        // 创建内部类的对象
        Body.Heart bh = new Body().new Heart();
        System.out.println(bh.numN);// 10
        bh.methodN1();// 内部类的成员方法 methodN1
        System.out.println("=======================");
        // 创建外部类对象
        Body b = new Body();
        b.methodW1();
        System.out.println("=======================");
        bh.methodN2();// 100    外部类的成员方法 methodW2
    }
}

3.总结
成员内部类的访问特点:

  • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须要建立内部类的对象。

六、匿名内部类

1.解释

匿名内部类是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象,就是一个类的匿名子类的对象,比如一个抽象类,要调用其中的抽象方法,首先需要创建一个类继承这个抽象方法,然后在子类种重写这个抽象方法,在main中先创建一个子类对象,然后通过这个对象来调用这个方法。必须一步一步来才能调用,比较繁琐,而这时候就可以使用匿名内部类,它是一个类的匿名子类的对象,就是这个已经继承抽象方法的类,且创建好了对象,匿名内部类可以看作是个对象。这样就能直接调用这个抽象方法了。在不创建子类的情况下,可以直接得到一个子类对象。

2.写法

abstract class Animal{
    public abstract void eat();
}

public class Test {
    public static void main(String[] args) {
    //new Animal() {}就是匿名内部类,就是Animal的子类对象。
    Animal anl = new Animal() {
            //在匿名内部类中重写抽象方法。
            @Override
            public void eat() {
                System.out.println("匿名内部类");
            }
        };// 是Animal类的子类的对象
        //anl就是子类对象
        anl.eat();

   }
}

//要是不用匿名内部了调用eat方法
//先要创建一个子类继承抽象类
class Dog extends Animal{
//重写抽象方法
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
}
public class Test {
    public static void main(String[] args) {
       Dog d = new Dog();// 创建Animal子类对象
        d.eat();// d---->是Animal类的子类的对象
   }
}
//综上:匿名内部了省略了创建子类

3.注意点

  • 接口和类的匿名内部类同样的实现过程。
  • 要注意匿内部类一个对象,是一个类的子类的对象,而且改子类继承或实现了这个接口。
  • 匿名内部类就是用来简化代码的,没有其他的功能
  • 要是一个方法的形参是抽象类或者接口类型,为了简化代码,就可以直接传入该抽象类或者接口的匿名内部类,这时候就形成了多态,父类引用指向了子类对象
    比如
abstract class Animal{
    public abstract void eat();
}
public class Test {
    public static void main(String[] args) {

       method(new Animal(){
         @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
})//这里调用的时候就传入了子类对象,形参了多态

 public static void method(Animal an){}//这里的形参是抽象类,又由于抽象类不能创建对象,所以传入的一定是抽象类的子类对象,这里形成了多态,这时候可以使用匿名内部类了
}}

七、引用类型使用总结

  • 只要用在数据类型的地方,引用类型都可以使用
  • 类名作为方法参数和返回值:可以直接传入该类的对象;返回该类的对象
  • 抽象类作为方法参数和返回值:只能传入该类的子类对象;返回该类的子类对象
  • 接口作为方法参数和返回值:只能传入该接口的实现类对象;返回该接口的实现类对象
  • 类作为成员变量: 赋该类的对象
  • 抽象类作为成员变量 :赋该类的子类对象
  • 接口作为成员变量 : 赋该接口的实现类对象
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值