04_Java类及类的成员

1、Java面向对象学习的三条主线

  1. Java类及类的成员:属性、方法、构造器;代码块、内部类
  2. 面向对象的三大特征:封装性、继承性、多态性、(抽象性)
  3. 其它关键字:this、super、static、final、abstract、interface、package、import等

2、面向对象与面向过程

  • 面向过程(pop)与面向对象(oop)

    二者都是一种思想,面向对象是相当于面向过程而言的。面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做

2.1 面向对象和面向过程的区别

  • 面向过程:

    1. 把冰箱门打开
    2. 抬起大象,塞进冰箱
    3. 把冰箱门关闭
  • 面向对象:

    1. 人{

      ​ 打开(冰箱){

      ​ 冰箱.打开();

      ​ }

      ​ 抬起(大象){

      ​ 大象.进入(冰箱);

      ​ }

      ​ 关闭(冰箱){

      ​ 冰箱.闭合();

      ​ }

      }

    2. 冰箱{

      ​ 打开(){}

      ​ 闭合(){}

      }

    3. 大象{

      ​ 进入(冰箱){

      ​ }

      }

2.2 面向对象的三大特征

  • 封装性
  • 继承性
  • 多态性

3. Java语言的基本元素

3.1 类和对象

  • 类(Class)对象(Object)是面向对象的核心概念

    1. 类是对一类事物的描述,是抽象的、概念上的定义
    2. 对象是实际存在的该类事物的每个个体,因而也被称为实例(instance)
  • 可以理解为:类 = 抽象概念的人

    ​ 对象 = 实实在在的某个人

  • 面向对象程序设计的重点是类的设计

  • 类的设计,其实就是类的成员的设计

3.2 类的结构–属性和方法

  • 常见类的成员有:

    1. 属性:对应类中的成员变量
    2. 行为:对应类中的成员方法

    Field = 属性 = 成员变量,Method = (成员)方法 = 函数

    field(域、字段)

3.3 类和对象的创建

  • 创建类的对象 = 类的实例化 = 实例化类
  • 调用对象的结构:属性、方法
  • 调用属性:“对象.属性”

3.4 类和对象的使用(面向对象思想落地的实现)

  1. 创建类,设计类的成员
  2. 创建类的对象(类的实例化)
  3. 通过"对象.属性" 或 "对象.方法"调用对象的结构

3.5 体会类的多个对象的关系

//测试类
public class PersonTest{
    public static void main(String[] args){
        //创建Person类的对象
        Person p1 = new Person();
        
        //调用对象的结构:属性、方法
        //调用属性:"对象.属性"
        p1.name = "Tom";
        p1.isMale = true;
        System.out.println(p1.name);
        
        //调用方法:"对象.方法"
        p1.eat();
        p1.sleep();
        p1.talk("中文");
        
        //***********************************
        //创建类的另外一个对象
        Person p2 = new Person();
        System.out.println(p2.name);//null,不报错,说明属性有默认初始化值
        System.out.println(p2.isMale);//false
        
        //将p1变量保存的地址值赋给p3,导致p1和p3指向了堆空间中的同一个对象实体。
        Person p3 = p1;
        System.out.println(p3.name);
        
        p3.age = 10;
        System.out.println(p1.age);//10
    }
}
class Person{
    //属性有默认初始化值
    String name;
    int age = 1;
    boolean isMale;
    
    //方法
    public void eat(){
        System.out.println("人可以吃饭");
    }
    public void sleep(){
        System.out.println("人可以睡觉");
    }
    public void talk(String language){
        System.out.println("人可以说话,使用的是:" + language);
    }
}
  • 如果创建了一个类的对象,每个对象都独立的拥有一套类的属性(非static的),意味着,如果我们修改一个对象的属性a,则不影响另外一个对象属性a的值

3.6 对象的内存解析

  • 堆(heap):存放实例对象(即我们创建的真实的结构的实体)
  • 栈(stack):是指虚拟机栈,用于存储局部变量等。局部变量表存放了编译期可知长度的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用类型,它不同于对象本身,是对象在堆内存的首地址。方法执行完,自动释放
  • 方法区(Method Area),用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

3.7 属性与局部变量的对比

1. 类中属性的使用

属性(成员变量) VS 局部变量

  • 相同点:

    1. 定义变量的格式:数据类型 变量名 = 变量值
    2. 先声明 后使用
    3. 变量都有其对应的作用域
  • 不同点

    1. 在类中声明的位置不同

      属性(成员变量):直接定义在类的一对{}内

      局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量

    2. 关于权限修饰符的不同

      (1)对于属性来讲:可以在声明属性时,指明其权限,使用权限修饰符。

      常用的权限修饰符:private、public、缺省、protected,权限影响了结构被调用时可见性的大小,即有的可以被调用,有的不可以

      (2)局部变量:不可以使用权限修饰符(它们的权限相当于用public代替了,方法是public,里面的局部变量就是public)

    3. 默认初始化值的情况:

      属性:类的属性,根据其类型,都有默认初始化值

      局部变量:没有默认初始化值

      意味着:我们在调用局部变量之前,一定要显式赋值

      特别地:形参在调用时,我们赋值即可

    4. 在内存中加载的位置:

      属性:加载到堆空间中(非static)

      局部变量:加载到栈空间

    public class UserTest{
        public static void main(String[] args){
            
        }
    }
    
    class User{
        //属性(或成员变量)
        String name;
        int age;
        boolean isMale;
        
        public void talk(String language){//language形参,局部变量
            System.out.println("我们使用" + language);
        }
        public void eat(){
            String food = "烙饼";//局部变量
            System.out.println("北方人喜欢吃:" + food);
        }
    }
    
2. 方法举例与声明的格式
  • 方法的声明:权限修饰符 返回值类型 方法名(形参列表){

​ 方法体

​ }

  • 说明:

    1. 关于权限修饰符:

      Java规定的4中权限修饰符:private、public、缺省、protected

    2. 返回值类型:

      有返回值 VS 没有返回值

      (1)如果方法有返回值,则必须在方法声明时指定返回值类型。同时,需要使用return关键字来返回指定类型的变量和常量

      (2)如果方法没有返回值,则方法声明时,使用void来表示。通常,没有返回值的方法中,就不需要使用return。但是如果使用的话,只能"return;"表示结束此方法的意思。

      (3)我们定义方法是该不该有返回值?

      题目要求

      看经验:具体问题具体分析

      (4)方法名:属于标识符,遵循标识符的规则和规范,同时,“见名知意”

      (5)形参列表:方法可以声明0个,1个,或多个形参

      格式:数据类型1 形参1,数据类型2 形参2,…

      定义方法时,要不要定义形参?

      (6)方法体:方法功能的体现

/*
类中方法的声明和使用

方法:描述类应该具有的功能
比如:Math类:sqrt()\random()\...
Scanner类:nextXXX()...
*/
public class CustomerTest{
    
}
//客户类
class Customer{
    String name;
    int age;
    boolean isMale;
    
    //方法
    public void eat(){
        System.out.println("客户吃饭");
    }
    public void sleep(int hour){
        System.out.println("休息了" + hour + "小时");
    }
    public String getName(){
        renturn name;
    }
    public String getNation(String nation){
        String info = "我的国籍是:" + nation;
        return info;
    }
}
  • 方法的分类:按照是否有形参及返回值

    无返回值有返回值
    无形参void 方法名(){}返回值类型 方法名(){}
    有形参void 方法名(形参列表){}返回值类型 方法名(形参列表){}
3. return关键字的使用
  • 适用范围:使用在方法体中

  • 作用:(1)结束方法

    ​ (2)针对于有返回值类型的方法,使用"return 数据"方法返回所要的数据。

  • 注意:return后面不能声明执行语句。

4.方法使用的注意点:
  • 可以调用当前类的属性或方法

    特殊的:方法a中又调用了方法a:递归方法

  • 方法中不可以定义方法

3.8 练习

class Person{
    String name;
    int age;
    /**
    sex: 1表明是男性
    sex: 0表明是女性
    */
    int sex;
    public void study(){
        System.out.println("studying");
    }
    public void showAge(){
        System.out.println("年龄为:" + age);
    }
    public int addAge(int i){
        age += i;
        //返回值
        return age;
    }
}

public class PersonTest{
    public static void main(String[] args){
        //创建对象
        Person p1 = new Person();
        p1.name = "Tom";
        p1.age = 18;
        p1.sex = 1;
        
        p1.study();
        p1.showAge();
        int newAge = p1.addAge(2);
        System.out.println(p1.name + "的新年龄为:" + newAge);//20
        
        Person p2 = new Person();
        p2.showAge();//0
        //哪个对象调用方法,属性就是谁的
    }
}

4. JVM内存结构与对象内存解析

编译完源程序以后,生成一个或多个字节码文件。

我们使用JVM中的类的加载器和解释器对生成的字节码文件进行解释运行。意味着,需要将字节码文件对应的类加载到内存中,涉及到内存解析。

在这里插入图片描述

  • 虚拟机栈:即为栈结构。我们将局部变量存储在栈结构中

  • 堆,我们将new出来的结构(比如:数组、对象)加载在堆空间中。

  • 补充:对象的属性(非static)加载到堆空间中

  • 方法区:类的加载信息、常量池、静态域

5. 万事万物皆对象

  • 在Java语言范畴中,我们都将功能、结构等封装到类中,通过类的实例化,来调用具体的功能结构

    Scanner,String等

    文件:File

    网络资源:URL

  • 涉及到Java语言与前端HTML、后端的数据库交互时,前后端的结构在Java层面交互时,都体现为类、对象

6. 对象数组的内存解析

  1. 引用类型的变量,只可能存储两类值:null 或 地址值(含变量的类型)

在这里插入图片描述

7. 匿名对象

7.1 匿名对象的使用

  • 理解:我们创建的对象 ,没有显式的赋给一个变量名。即为匿名对象
  • 特征:匿名对象只能调用一次
public class PhoneTest{
    public static void main(String[] args){
        Phone p = new Phone();
        System.out.println(p);
        
        p.sendEmail();
        
        //匿名对象
        //new Phone();就是对象没有名
        //用法
        new Phone().sendEmail();
        new Phone().playGame();//与new Phon().sendEmain()不是同一个对象
        
    }
}
class Phone{
    double price;
    public void sendEmail(){
        System.out.println("发送邮件");
    }
}
  • 使用:

    class Phone{
        double price;
        public void sendEmail(){
            System.out.println("发送邮件");
        }
    }
    
    class PhoneFactory{
        public void show(Phone phone){//方法的形参是Phone类型
            phone.sendEmail();
        }
    }
    public class PhoneTest{
        public static void main(String[] args){
            PhoneFactory factory = new PhoneFactory();
            //匿名对象的使用
            factory.show(new Phone());
    }
    

8. 自定义数组的工具类

public class ArrayUtil{
    //求数组的最大值
    public int getMax(int[] arr){
        
    }
    //求数组的最小值
    
    //求数组的总和
    
    //求数组的平均值
    
    //反转数组
    
}
public class ArrayTest{
    public static void main(String[] args){
        //调用方法
    }
}

9. 构造器(或构造方法、constructor)

  • 任何一个类都有构造器,且默认构造器的权限和类的权限相同

9.1 构造器的作用

  • 用来创建对象

    public class PersonTest{
        public static void main(String[] args){
            //创建类的对象:new + 
            Person p = new Person();
            
            p.eat();
        }
    }
    class Person{
        //属性
        String name;
        int age;
        
        //构造器
        public Person(){
            sout("Person()...");//在new Person()的时候执行
        }
        
        //方法
        public void eat(){
            sout("人吃饭");
        }
        
        public void sleep(){
            sout("人睡觉");
        }
    }
    
//构造器
public class PersonTest{
    Person p1 = new Person("Tom");
    sout(p1.name);
}
class Person(String n){
    this.name = n;
}

9.2 说明:

  • 如果没有显式的定义类的构造器的话,则系统默认提供一个空参的构造器

  • 定义构造器的格式:权限修饰符 类名(形参列表){}

  • 构造器不等同于方法

    (1)格式不一样

    (2)功能不一样:

    方法,有了对象之后去调方法;

    构造器,来造对象的。

9.3 细节说明

  • 构造器的特征

    (1)它具有与类形同的名称

    (2)它不声明返回值类型(与声明为void不同)

    (3)不能被static、final、synchronized、abstract、native、修饰,不能有return语句返回值

  • 构造器的作用

    (1)创建对象

    (2)给对象进行初始化

  • 在一个类中可以定义多个构造器,这些构造器彼此构成重载

  • 一旦我们显式的定义了类的构造器之后,系统就不再提供默认的空参构造器

  • 一个类中,至少会有一个构造器

9.4 构造器练习

  • 利用构造器设置所有人的age属性初始值都为18
public Person(){
    age = 18;
}
  • 三角形

    TriAngle类

    public class TriAngle{
        //属性
        private double base;
        private double height;
        //构造器
        public TriAngle(){
            
        }
        public TriAngle(double b,double h){
            base = b;
            height = h;
        }
        //方法
        public void setBase(double b){
            base = b;
        }
        public double getBase(){
            return base;
        }
        
        public void setHeight(double h){
            height = h;
        }
        public double getHeight(){
            return height;
        }
    }
    
  • 测试类

    public class TriAngleTest{
        public static void main(String[] args){
            TriAngle t1 = new TriAngle();
            sout("base:" + t1.getBase() + ", height:" + t1.getHeight());
        }
        
        TriAngle t2 = new TriAngle(5.1, 5.6);
        sout("base:" + t2.getBase() + ", height:" + t2.getHeight());
    }
    

10. 属性赋值过程

10.1 总结:属性赋值先后过程

  • 几种赋值方式:

    (1)默认初始化值

    (2)显式初始化

    (3)构造器中初始化

    (4)通过"对象.方法" 或 “对象.属性” 的方式,赋值(操作可以反复执行)

    以上操作的先后顺序:(1)—> (2)—> (3)—> (4)

11. 拓展—JavaBean的使用

  • JavaBean是一种Java语言写成的可重用组件

  • 所谓JavaBean,是指符合如下标准的Java类:

    (1)类是公共的

    (2)有一个无参的公共构造器

    (3)有属性,且有对应的get、set方法

    public class Customer{
        private int id;
        private String name;
        
        public Customer(){ 
        }
        public void setId(int i){
            id = i;
        }
        public int getId(){
            return id;
        }
        public void setName(String n){
            name = n;
        }
        public String getName(){
            return name;
        }
    }
    
  • 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关系任何改变。

12. 拓展:UML类图

  • (1)+表示 public 类型,- 表示 private 类型, # 表示protected类型

    (2)方法的写法:

    方法的类型(+、-) 方法名(参数名:参数类型): 返回值类型

在这里插入图片描述

13. 类的成员之四—代码块

类的成员之四:代码块(或初始化块)

  • 代码块的作用:通常是用来初始化当前类、或者对象的

  • 代码块如果有修饰的话,只能使用static

  • 分类:

    (1)静态代码块

    (2)非静态代码块

  • 静态代码块:

    static{
        sout("hello, static block");
    }
    

    (1)内部可以有输出语句

    (2)随着类的加载而执行(非加载,加载只是加载到内存中,需要调用才能执行)

    (3)且只执行一次

    (4)作用:初始化类的一些信息

    (5)在一个类中,可以定义多个静态代码块;并且按照声明的先后顺序执行

    (6)静态代码块的执行要优先于非静态代码块的执行

    实际使用中,没有必要造多个

    (7)静态代码块内只能调用静态的属性、静态的方法,不能调用非静态的结构

  • 非静态代码块

    {
        sout("hello, blocks")
    }
    

    (1)内部可以有输出语句
    (2)随着对象的创建而执行

    (3)且每创建一个对象就执行一次非静态代码块

    (4) 作用:可以在创建对象时,对对象的属性进行初始化

    (5)如果一个类中定义了多个非静态代码块按照声明的先后顺序执行

    (6)非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法

public class BlockTest{
    
}
class Person{
    //属性
    String name;
    int age;
    static String desc = "我是一个人";
    
    //构造器
    public Person(){
        
    }
    
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
    
    //代码块
    {
        
    }
    
    //方法
    public void eat(){
        sout("吃饭");
    }
    //提供一个toString的方法
    public String toString(){
        return "Person [name = " + name + ", age = " + age + "]";
    }
}
  • 小总结:对象可以赋值的位置

    1. 默认初始化
    2. 显式初始化
    3. 构造器中初始化
    4. 有了对象以后,可以通过"对象.属性" 或 "对象.方法"的方式,进行赋值
    5. 在代码块中赋值

13.1 属性赋值的先后顺序

a — b/e — c — d

b 、 e先写谁 谁就先执行

14. 类的内部成员之五 — 内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类—即这个类在没必要在外面定义,只是自己去用

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。

Inner class 一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称

Inner class 的名字不能与包含外部类类名相同

分类:成员内部类(static成员内部类和非static成员内部类)

​ 局部内部类(不谈修饰符)、匿名内部类

14.1 使用

  1. Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
  2. 内部类的分类:成员内部类(静态的、非静态的) VS 局部内部类(方法内、代码块内、构造器内)
public class InnerClassTest{
    
}
class Person{
    String name;
    public void eat(){
        sout("人:吃饭");
    }
    //静态成员内部类
    static class Brain {
        String name;
        int year;
        public void show(){
            sout("...");
        }
    }
    //非静态成员内部类
    class Body {
        String name;
        public Body(){
            
        }
        public void action(){
            sout("身体的一些行为是健康状态的预警");
            Person.this.eat();//调用外部类的非静态属性。
        }
    }
    public void method(){
        //局部内部类
        class AA {
            
        }
    }
    
    {
        //局部内部类
        class BB {
            
        }
    }
    
    public Person(){
        //局部内部类
        class CC{
            
        }
    }
}

14.2 成员内部类的特点

  1. 一方面:作为外部类的成员

  2. 另一方面,作为一个类:

    (1)类内可以定义属性、方法、构造器等

    (2)可以被final修饰,表示此类不能被继承。言外之意:不使用final,就可以被继承

    (3)可以被abstract修饰(表示此类不能被实例化)。

14.3 如何实例化成员内部类

  1. 如何实例化成员内部类的对象

    //创建Brain实例(静态的成员内部类):
    Person.Brain brain = new Person.Brain();
    brain.show;
    //创建Body实例:(非静态的成员内部类)
    //要先有外部类的实例
    Person p = new Person();
    Person.Body body = p.new Body();
    body.action();
    
  2. 如何在成员内部类中区分调用外部类的结构

    class Body {
        String name;
        public Body(){
            
        }
        public void action(){
                sout("身体的一些行为是健康状态的预警");
                Person.this.eat();//调用外部类的非静态属性。
        }
        public void display(String name){
            sout(name);//方法形参name
            sout(this.name);//Body内部类的name属性
            sout(Person.this.name);//Person外部类的name属性
        }
    }
    
  3. 开发中局部内部类的使用

public class InnerClassTest1{
    //开发中很少见
    public void method(){
        //局部内部类
        class AA{
            
        }
    }
    
    //返回一个实现了Comparable接口的类的对象
    public Comparable getComparable(){
        //创建一个实现了Comparable接口的类:局部内部类
        //方式一:
        class Mycomparable implements Comparable{
            @Override
            public int compareTo(Object o){
                return 0;
            }
        }
        
        return new MyComparable();
        
        //方式二:
        return new Comparable(){
            @Override
            public int compareTo(Object o){
                return 0;
            }
        };
    }
}

14.4 局部内部类使用的一个注意点

在局部内部类的方法中(比如:show),如果调用局部内部类所声明的方法(比如:method)中的局部变量的话,要求此局部变量声明为final的

public class InnerClassTest {
    public void method(){
        //局部变量:在JDK7及以前的版本中,需要明确的加上final--->final int num = 10;
        int num = 10;
        class AA {
            public void show(){
                //报错:Local variable num defined in an enclosing scope must be final or effectively final
                //num = 20;
                sout(num);
            }
        }
    }
}

外部类生成一个字节码文件,内部类也生成一个独立的字节码文件,method方法本身存在于外部类的结构里,num变量正常来讲出了方法就失效了,要想在另一个字节码文件中能用,加上final可以理解为:在另一个字节码文件中可以用,相当于给它传了一个副本(意味着能用不能改)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 静态嵌套是指在一个中定义的静态,它可以直接通过外部名访问,不需要先创建外部的实例。静态嵌套可以访问外部的静态成员和方法,但不能访问外部的非静态成员和方法。静态嵌套通常用于封装一些与外部相关的工具或常量。 ### 回答2: 嵌套是一种被定义在另一个中的Java语言中有两种型的嵌套:静态嵌套和非静态嵌套(内部)。本篇主要探讨静态嵌套的概念和使用。 静态嵌套是指被定义为静态的内部,它可以像其他静态成员一样独立使用,无需依赖于外围的实例。静态嵌套可以访问外围的静态成员和方法,但不能直接访问外围的非静态成员和方法,因为它没有外围的实例。 静态嵌套的定义语法如下: ``` class OuterClass { static class NestedClass { // ... } } ``` 在外围中,静态嵌套可以通过以下语法来创建实例: ``` OuterClass.NestedClass nestedObj = new OuterClass.NestedClass(); ``` 静态嵌套的主要作用是组织和管理代码,使得代码结构更加清晰和简洁。它可以被用来实现一些复杂的算法和数据结构,也可以被用来封装私有和接口。 值得注意的是,静态嵌套和普通的一样,可以被继承和实现接口。它的主要区别在于它定义在另一个中,并且没有对外围实例的依赖。 总的来说,静态嵌套是一种非常有用和灵活的编程技术,可以帮助我们更好地组织代码和实现复杂的功能。在实际应用中,我们可以根据具体的需求来灵活使用嵌套的不同形式,以提高代码的可读性和可维护性。 ### 回答3: Java中的嵌套是指在一个的内部定义另一个。嵌套可以分为静态嵌套和非静态嵌套,本文将重点介绍静态嵌套。 静态嵌套也被称为静态内部,是在一个内部定义并且被static修饰的嵌套。静态嵌套可以像普通一样访问外部的所有静态成员,但不能访问外部的非静态成员。另外,静态嵌套与外部没有继承关系,它们之间的关系就像是两个独立的。 静态嵌套的语法格式如下: ``` public class Outer { //外部中的静态变量 private static int num = 10; //静态嵌套 public static class Inner { //内部中的静态变量 private static int innerNum = 20; //内部中的静态方法 public static void innerMethod() { System.out.println("innerNum: " + innerNum); System.out.println("num: " + num); } } public static void main(String[] args) { Outer.Inner.innerMethod(); //调用静态嵌套中的静态方法 } } ``` 从上述代码可以看出,在Outer中定义了一个静态嵌套Inner,Inner中可以访问Outer的静态成员num,同时Inner中也可以定义自己的静态成员innerNum。在main方法中,可以直接通过Outer.Inner.innerMethod()的方式调用Inner中的静态方法。 静态嵌套不同于内部,它无需依赖外部的实例就可以实例化,因此它的生命周期不受外部实例的影响。此外,静态嵌套也可以用于代码的组织和模块化,在一个内部定义一些只用于该内部的辅助或数据结构等。 总之,静态嵌套Java中一种很有用的语言特性,可以提高代码的可读性、可维护性和模块化程度。在实际开发中,可以根据需求合理使用静态嵌套,以达到更好的代码设计效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值