第六章 面向对象(中)

第六章 面向对象(中)

6.1 封装

6.1.1 封装的概念

  1. 适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。

    ​ 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改。封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。要访问该类的数据,必须通过指定的方式。

    ​ 方式:暴露该暴露的,隐藏需要隐藏

  2. 高内聚,低耦合

  • 高内聚:类的内部数据操作细节自己完成,不允许外部干涉;
  • 低耦合:仅对外暴露少量的方法用于使用
  1. 封装思想的应用
  • 类的封装:把属性和方法封装到类的内部,外部通过调用方法完成指定的功能,不需要了解类的内部实现
  • 组件的封装:例如支付宝等支付组件,对外只提供使用接口,我们不需要也无法了解内部的实现
  • 系统的封装:例如我们使用操作系统等,我们只需要知道怎么用,不需要了解内部的实现

6.1.2 属性的封装

  1. 原则

    属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

  2. 封装的目的

  • 隐藏类的实现细节
  • 让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里面加入控制逻辑,限制对成员变量的不合理访问。
  • 可以进行数据检查,从而有利于保证对象信息的完整性。
  • 便于修改,提高代码的可维护性。
  1. 实现步骤
  • 使用private修饰成员变量
private 数据类型 变量名 ;
  • 提供get/set方法,可以访问成员变量
//get方法的标准格式:
属性的类型	get属性名(){ //属性名首字母大写,因为它对于get方法来说是第二个单词
	return 属性;
}
//set方法的标准格式:
void set属性名(属性的类型 形参名){
	属性名 = 形参名;
}

6.1.3 权限修饰符

  1. 权限修饰符的可见性范围
权限修饰符本类本包其它包子类其它包非子类
privateY
缺省YY
protectYYY
publicYYYY
  1. 权限修饰符的说明
//类:
【修饰符】 class 类名{
}
//属性:
【修饰符】 数据类型  属性名;

//方法:
【修饰符】 返回值类型 方法名(【形参列表】){
}
//属性一般都是private,方法一般都是public
//用public修饰的类必须与源文件名相同
  • 对于类的成员:四种权限修饰符都可以使用;
  • 对于外部的类:只能使用public和缺省两种(目前的类都是外部类);
  1. 案例演示
  • 声明学生类

    有属性:姓名,年龄,成绩,并且私有化,

​ 声明姓名和成绩实例变量,私有化,提供get/set

​ getInfo()方法:用于返回学生对象的信息

  • 测试类的main中创建一个可以装3个学生对象的数组,并且按照学生成绩排序,显示学生信息
class Test22_Exer{
	public static void main(String[] args){
		//创建一个可以装3个学生对象的数组
		Student[] arr = new Student[3];//只是申明这个数组,可以用来装3个学生,此时里面没有学生对象
		
		//手工赋值
		arr[0] = new Student();
		arr[0].setName("张三");
		arr[0].setScore(78);
		
		arr[1] = new Student();
		arr[1].setName("李四");
		arr[1].setScore(96);
		
		arr[2] = new Student();
		arr[2].setName("王五");
		arr[2].setScore(56);
		
		//先显示一下目前的顺序
		for(int i=0; i<arr.length; i++){
			System.out.println(arr[i].getInfo());
		}
		
		System.out.println("------------------------------------------");
		//冒泡排序
		for(int i=1; i<arr.length; i++){
			for(int j=0; j<arr.length-i; j++){
				//arr[j] > arr[j+1]//错误的
				if(arr[j].getScore() > arr[j+1].getScore()){
					//交换两个元素,这里是两个学生对象,所以temp也得是Student类型
					Student temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
			}
		}
		//再显示一下目前的顺序
		for(int i=0; i<arr.length; i++){
			System.out.println(arr[i].getInfo());
		}
	}
}
class Student{
	private String name;
	private int score;//使用int或double都可以
	
	//get/set方法,
	public void setName(String n){
		name = n;
	}
	public String getName(){
		return name;
	}
	public void setScore(int s){
		score = s;
	}
	public int getScore(){
		return score;
	}
	
	public String getInfo(){
		return "姓名:" + name +",成绩:" + score;
	}
}

6.2 构造器(Constructor)

​ 构造器又称为构造方法,那是因为它长的很像方法。但是和方法还有有所区别的。

​ 要创建一个类的实例对象,必须调用一个对象的构造器,来完成类的实例初始化过程。实例初始化过程就是为实例变量赋初始值的过程。

​ 当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值

6.2.1 构造方法的定义格式

【修饰符】 构造器名(){
    // 实例初始化代码
}
【修饰符】 构造器名(参数列表){
	// 实例初始化代码
}

​ 注:

  1. 构造器名必须与它所在的类名必须相同
  2. 它没有返回值,所以不需要返回值类型,甚至不需要void
  3. 如果你不提供构造器,系统会给出无参数构造器,并且该构造器的修饰符默认与类的修饰符相同
  4. 如果你提供了构造器,系统将不再提供无参数构造器,除非你自己定义。
  5. 构造器是可以重载的,既可以定义参数,也可以不定义参数。
  6. 构造器前面的修饰符:public,protected,缺省,private,不能被static、final、synchronized、abstract、native修饰
class Test08Constructor{
	public static void main(String[] args){
		//调用无参构造创建对象
		Student stu1 = new Student();
		
		//调用有参构造创建对象
		Student stu2 = new Student("张三",23);
		
		System.out.println(stu1.getInfo());
		System.out.println(stu2.getInfo());
		
		//Student stu3 = Student();//错误的调用无参构造
		//System.out.println(Student());//错误的调用无参构造
	}
}

class Student{
	private String name;
	private int age;
	//无参构造
	public Student(){
		System.out.println("一个学生对象被创建");
		//无参构造中,将属性初始化为默认值
	}
	//有参构造
	public Student(String n, int a){
		name = n;
		age = a;
	}
	public String getInfo(){
		return "姓名:" + name + ",年龄:" + age;
	}
}

6.3 this关键字

​ this代表当前对象的引用(地址值),即对象自己的引用。

  • this可以用于构造器中:表示正在创建的那个实例对象,即正在new谁,this就代表谁
  • this用于实例方法中:表示调用该方法的对象,即谁在调用,this就代表谁。

6.3.1 使用格式

  1. this.成员变量名

    ​ 当方法的局部变量与当前对象的成员变量重名时,就可以在成员变量前面加this.,如果没有重名问题,就可以省略this.

this.成员变量名;
  1. this.成员方法

    调用当前对象自己的成员方法时,都可以加"this.",也可以省略,实际开发中都省略

【变量=】this.成员方法(【实参列表】);
  1. this()或this(实参列表)

    ​ 当需要调用本类的其他构造器时,就可以使用该形式。

    要求:

    • 必须在构造器的首行

    • 如果一个类中声明了n个构造器,则最多有 n - 1个构造器中使用了"this(【实参列表】)",否则会发生递归调用死循环

6.4 static

​ static是一个成员修饰符,可以修饰类的成员:成员变量、成员方法、成员内部类(后面讲)、代码块(后面讲)。被修饰的成员是属于类的,而不是单单是属于某个对象的。也就是说,既然属于类,就可以不靠创建对象来调用了。

​ 它可以修饰:属性、方法、成员内部类、代码块.

6.4.1 静态方法

  • static修饰的成员方法,称为类方法、静态方法。

  • 什么情况下可以声明静态方法?

​ 当这个方法的调用和运行和“对象”无关,这样的方法才可以声明为静态的。

  1. 语法格式:
【其他修饰符】 static 返回值类型 方法名 (【形参列表】){ 
	// 执行语句 
}
  1. 说明
  • 在本类中,静态方法可以直接访问静态方法和静态变量;

  • 在其他类中:可以使用“类名.方法"进行调用;

  • 在静态方法中,不能出现:this,也不能直接使用本类的非静态的成员。相反,非静态的实例成员方法可以直接访问静态的类变量或静态方法。

    注:静态方法只能访问静态成员。

public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	s.fun();//有警告,没错误
    	Son.fun();
    }
}

class Son{
	private int a;	
	public static void fun(){
//		method();//错误的
//		System.out.println(a);//错误
//		System.out.println(this.a);//错误

		System.out.println("Son:fun()");
	}
	public void method(){
		System.out.println("Son:method()");
	}
}

6.4.2 静态变量

  • 静态变量的值是该类所有对象**“共享的”**,不单独属于某一个对象。如果其中一个对象修改了静态变量,所有对象都会受到影响。因此,为了可读性,静态变量建议使用“类名.”进行访问,而不是通过“对象.”;
  • 静态变量的get/set方法也是静态的;
  • 静态变量的值,一般不在构造器中进行初始化;
  • 当静态变量与局部变量同名时,我们可以使用“类名.”进行区别;
  • 特别要强调,在静态方法中,绝对不能出现“this”等;
  • 静态变量的值不是在堆的对象中,而是在“方法区”中;
public class TestStatic {
	public static void main(String[] args) {
		//建议静态的属性通过类名.进行赋值,因为它不单独属于某一个对象,而是这个类的所有对象“共享”
		//Chinese.country = "中国人民共和国";
		Chinese.setCountry("中国人民共和国");
		//创建对象
		Chinese c1 = new Chinese();
		c1.setName("张三");
		c1.setAge(23);
//		c1.setCountry("中华人民共和国");
		System.out.println(c1.getInfo());
		
		Chinese c2 = new Chinese();
		c2.setName("李四");
		c2.setAge(24);
		System.out.println(c2.getInfo());
		
		c1.setCountry("中国");
		System.out.println(c1.getInfo());
		System.out.println(c2.getInfo());
	}
}
class Chinese{//中国人
//	public static String country;//国籍
	private static String country;//国籍
	private String name;//姓名
	private int age;//年龄
	
	public Chinese() {
	}

	public Chinese(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public static String getCountry() {
		return country;
	}

	public static void setCountry(String country) {
		Chinese.country = country;
	}

	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 getInfo(){
		return "国籍:" + country + ",姓名:" + name + ",年龄:" + age;
	}
}

6.4.3 变量的分类与区别

1、变量按照数据类型分:

(1)基本数据类型的变量,里面存储数据值

(2)引用数据类型的变量,里面存储对象的地址值

2、变量按照声明的位置不同:

(1)成员变量

(2)局部变量

3、成员变量与局部变量的区别

(1)声明的位置不同

​ 成员变量:类中方法外

​ 局部变量:(1)方法的()中,即形参(2)方法体的{}的局部变量(3)代码块{}中

(2)存储的位置不同

​ 成员变量:

​ 如果是静态变量(类变量),在方法区中

​ 如果是非静态的变量(实例变量),在堆中

​ 局部变量:栈

(3)修饰符不同

​ 成员变量:4种权限修饰符、static等多种修饰符

​ 局部变量:不能有任何修饰符

(4)作用域

​ 成员变量:

​ 如果是静态变量(类变量),在本类中随便用,在其他类中使用“类名.静态变量"

​ 如果是非静态的变量(实例变量),在本类中只能在非静态成员中使用,在其他类中使用“对象名.非静态的变量"

​ 局部变量:有作用域,出了作用域就不能使用

(5)生命周期

​ 成员变量:

​ 如果是静态变量(类变量),和类相同,随着类的加载而分配,随着的类的卸载才消亡。

​ 如果是非静态的变量(实例变量),和所属的对象相同,每一个对象是独立。对象创建时,才在堆中分配内存,随着对象被垃圾回收而消亡。

​ 局部变量:每次方法调用执行都是新的,而且仅在作用域范围内有效。

6.5 继承

​ 继承:就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。

​ 继承别人的类称为子类(subclass),被继承的的类称为父类(superclass)。子类又称为派生类,父类又称为超类、基类。

6.5.1 继承的好处

  • 提高代码的复用性
  • 提高代码的扩展性
  • 类与类之间产生了关系,是学习多态的前提

6.5.2 继承的格式

​ 通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

【修饰符】 class 父类 {
	...
}
【修饰符】 class 子类 extends 父类 {
	...
}

6.5.3 继承的特点一:成员变量

1. 私有化
  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的公有方法(get/set)进行访问。

[外链图片转存失败(img-BcBguciC-1568520084839)(E:\02-课堂笔记\day11\img\继承私有成员1.jpg)]

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    // 定义name属性
	private String name; 
    // 定义age属性
    public int age;
	// 定义动物的吃东西方法
	public void eat() {
		System.out.println(age + "岁的" + name + "在吃东西");
	}
}
/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
	// 定义一个猫抓老鼠的方法catchMouse
	public void catchMouse() {
		System.out.println("抓老鼠");
	}
}
/*
 * 定义测试类
 */
public class ExtendDemo01 {
	public static void main(String[] args) {
        // 创建一个猫类对象
		Cat t = new Cat();
        // 为该猫类对象的name属性进行赋值
		//t.name = "Tom";// 编译报错
      	// 为该猫类对象的age属性进行赋值
		t.age = 2;
        // 调用该猫的catchMouse()方法
		t.catchMouse();
      	// 调用该猫继承来的eat()方法
      	t.eat();
	}
}
2. 成员变量的重名问题

​ 如果子类父类中出现不重名的成员变量,这时的访问是没有影响的;如果子类父类中出现重名的成员变量,这时的访问是有影响的

  • 子父类中出现了同名的成员变量时,在子类中需要访问父类中非私有成员变量时,需要使用super 关键字,修饰父类成员变量,类似于之前学过的 this

    • 格式:
    super.父类成员变量名
    
    • 案例演示
    class Zi extends Fu {
    	// Zi中的成员变量
    	int num = 6;
    	public void show() {
    		//访问父类中的num
    		System.out.println("Fu num=" + super.num);
    		//访问子类中的num
    		System.out.println("Zi num=" + this.num);
    	}
    }
    演示结果:
    Fu num = 5
    Zi num = 6
    

6.5.4 继承的特点二:成员方法

1. 成员方法重名——重写(Override)
  • 如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写 (Override)。
class Fu {
	public void show() {
		System.out.println("Fu show");
	}
}
class Zi extends Fu {
	//子类重写了父类的show方法
	public void show() {
		System.out.println("Zi show");
	}
}
public class ExtendsDemo05{
	public static void main(String[] args) {
		Zi z = new Zi();
     	// 子类中有show方法,只执行重写后的show方法
		z.show();  // Zi show
	}
}
  • 说明

    • 在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
      创建的对象是谁,就优先用谁,如果没有则向上找。
  • 注意事项:
    无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。

​ 方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。

1) 重载和重写的区别

A. 方法的重载(Overload)

​ 同一个类中,出现方法名称相同,形参列表不同的两个或多个方法。和返回值类型无关。

B. 方法的重写(Override)

​ 当子类继承了父类时,子类会继承父类所有的方法,但是有的时候,父类的某个方法功能的“实现”(即方法体的代码)它不适用于子类,此时,子类可以选择对父类的这个方法的方法体进行“重写、覆写”,即重新实现。

class Phone {
	public void sendMessage(){
		System.out.println("发短信");
	}
	public void call(){
		System.out.println("打电话");
	}
	public void showNum(){
		System.out.println("来电显示号码");
	}
}

//智能手机类
class NewPhone extends Phone {
	
	//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
	public void showNum(){
		//调用父类已经存在的功能使用super
		super.showNum();
		//增加自己特有显示姓名和图片功能
		System.out.println("显示来电姓名");
		System.out.println("显示头像");
	}
}

public class ExtendsDemo06 {
	public static void main(String[] args) {
      	// 创建子类对象
      	NewPhone np = new NewPhone();
        
        // 调用父类继承而来的方法
        np.call();
      
      	// 调用子类重写的方法
      	np.showNum();

	}
}
2) 注意事项
  1. 必须保证父子类之间方法的名称相同,参数列表也相同。
    @Override:写在方法前面,用来检测是不是有效的正确覆盖重写。
    这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

  2. 子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类)。
    小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

    注意:如果返回值类型是基本数据类型和void,那么必须是相同

  3. 子类方法的权限必须【大于等于】父类方法的权限修饰符。
    小扩展提示:public > protected > 缺省 > private
    备注:缺省不是汉字缺省,而是什么都不写,留空。

  4. 几种特殊的方法不能被重写

    • 静态方法不能被重写
    • 私有等在子类中不可见的方法不能被重写
    • final方法不能被重写

6.5.5 继承的特点三:构造方法

  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中必须先执行父类的初始化动作。子类的构造方法中默认有一个super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。代码如下:
//子类的初始化过程中,必须先执行父类的初始化动作
class Fu {
  private int n;
  Fu(){
    System.out.println("Fu()");
  }
}
class Zi extends Fu {
  Zi(){
    // super(),调用父类构造方法
    super();
    System.out.println("Zi()");
  }  
}
public class ExtendsDemo07{
  public static void main (String args[]){
    Zi zi = new Zi();
  }
}
输出结果:
Fu()
Zi()

6.5.6 继承的特点四:单继承限制

  1. Java只支持单继承,不支持多继承;

    即 :一个类只能有一个父类,不可以有多个父类。

  2. Java支持多层继承(继承体系);

    一个父类可以有多个子类。(顶层父类是Object类,所有的类默认继承Object,作为父类。)

6.6 super关键字

6.6.1 概念

  1. 父类空间优先于子类对象产生

    在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。

  2. 只能通过它访问父类在子类中可见的成员(属性、方法、构造器)

    • 不能通过它访问父类的私有的属性、方法、构造器

    • 如果跨包,还不能访问父类中缺省的属性、方法、构造器

6.6.2 super的用法

  1. super.属性

    ​ 当子类中声明了与父类中同名的属性时,在子类的某个方法中,需要区别是父类的,还是子类的属性时,可以加super.父类的属性。

  2. super.方法

    ​ 当子类重写了父类的方法,但是又想要在子类中调用父类被重写的方法,可以加"super."。

public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	s.test(30);
    }
}
class Father{
	int a = 10;
}
class Son extends Father{
	int a = 20;
	public void test(int a){
		System.out.println(super.a);//10
		System.out.println(this.a);//20
		System.out.println(a);//30
	}
}
  1. super()或super(实参列表)
    • super():表示访问父类的无参构造.

      • 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super();

      • 如果父类有无参构造,那么在子类的构造器中想要表示调用父类的无参构造器时,可以写super(),也可以省略;

      • 如果父类“没有”无参构造,那么在子类的构造器中不能写super(),必须使用下面的super(实参列表),而且还不能省略

    • super(实参列表):表示访问父类的有参构造.

    • super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现.

6.6.3 super和this的区别

  1. super :代表父类的存储空间标识(可以理解为父亲的引用)。
    • 通过super找成员变量和成员方法时,直接从父类空间(包含父类的父类继承的)找

    • super()或super(实参列表)只能从直接父类找

    • 通过super只能访问父类在子类中可见的(非private,跨包还不能是缺省的)

  2. this :代表当前对象的引用
  • 通过this找成员变量和成员方法时,先从当前类中找,没有的会往上找父类的。
  • 但是this()或this(实参列表)只会在本类中找
this(...)    	--    本类的构造方法
super(...)   	--    父类的构造方法
  1. 关于变量(就近原则,起点不同,要注意可见性)
    • 没有this.的:先从局部变量开始找,如果有就是局部变量

      ​ 如果没有,再从本类的成员变量找,

      ​ 再没有,从直接父类找

      ​ 再没有,从间接父类找,

      ​ 再没有,报错

    • 有this.的,先从本类的成员变量开始找,如果有就是本类的成员变量

      ​ 再没有,从直接父类找,

      ​ 再没有,从间接父类找,

      ​ 再没有,报错

    • 有super.的,先从直接父类的成员变量开始找,如果有就是直接父类的成员变量

      ​ 再没有,从间接父类找,

      ​ 再没有,报错

public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	s.test();
    }
}
class Father{
	public void method(){
		System.out.println("aa");
	}
}
class Son extends Father{
	public void method(){
		System.out.println("bb");
	}
	public void test(){
		method();//bb
		this.method();//bb
		super.method();//aa
	}
}

6.6.4 this关键字(复习)

  1. this代表的是当前对象:
    • 在构造器中,this()代表的是正在new的那个对象
    • 在成员方法中,this代表的是调用当前方法的对象;
  2. this.属性

    当局部变量与成员变量同名时,在成员变量的前面加"this.

6.7 final关键字

  1. 概念
    • final意思是最终的,不可更改的;

    • 它可以修饰:类(包括外部类和内部类)、方法(静态方法和非静态方法)、变量(静态变量,实例变量、局部变量) ;

    • 不能用来修饰构造器,构造器的修饰符只能是4个权限修饰符(public,protected,缺省,private);

  2. final修饰类

    ​ 表示这个类不能被继承,没有子类。

  3. final修饰方法

    ​ 表示这个方法不能被子类重写。

  4. 声明常量
     	再没有,从间接父类找,
    

    ​ 再没有,报错

public class Test{
    public static void main(String[] args){
    	Son s = new Son();
    	s.test();
    }
}
class Father{
	public void method(){
		System.out.println("aa");
	}
}
class Son extends Father{
	public void method(){
		System.out.println("bb");
	}
	public void test(){
		method();//bb
		this.method();//bb
		super.method();//aa
	}
}

6.6.4 this关键字(复习)

  1. this代表的是当前对象:
    • 在构造器中,this()代表的是正在new的那个对象
    • 在成员方法中,this代表的是调用当前方法的对象;
  2. this.属性

    当局部变量与成员变量同名时,在成员变量的前面加"this.

6.7 final关键字

  1. 概念
    • final意思是最终的,不可更改的;

    • 它可以修饰:类(包括外部类和内部类)、方法(静态方法和非静态方法)、变量(静态变量,实例变量、局部变量) ;

    • 不能用来修饰构造器,构造器的修饰符只能是4个权限修饰符(public,protected,缺省,private);

  2. final修饰类

    ​ 表示这个类不能被继承,没有子类。

  3. final修饰方法

    ​ 表示这个方法不能被子类重写。

  4. 声明常量

    ​ 某个变量如果使用final修饰,那么它的值就不能被修改,即常量,并且被final修饰的常量名称也必须遵循常量的书写规范,即:所有单词全部大写,单词间用下划线隔开;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值