深入类和对象

本文深入探讨Java中的类和对象,包括类变量与类方法、Main方法、代码块(普通和静态)、final关键字的使用、抽象类与接口的概念及应用。通过实例讲解了静态变量的生命周期、代码块的执行顺序以及final修饰符的作用。同时,对比了抽象类和接口的异同,展示了内部类(成员和静态)的使用,以及接口的多态性。此外,还讨论了局部内部类和匿名内部类在实际开发中的应用。
摘要由CSDN通过智能技术生成

大家好呀!我是小笙!我学习了韩顺平老师的类和对象的知识,收获颇丰!现在来和大家分享笔记!

深入类和对象

类变量和类方法

类变量也称作静态变量,类方法也称作静态方法

与成员变量的区别就是有无 static 关键字

注意细节

  1. 静态变量是同一个类所有对象共享
  2. 类变量在类加载的时候就生成了
  3. 类变量中不能使用和对象有关的关键字(比如:,this,super ),因为this或者super的产生需要创建对象,但是类变量在类加载的时候就出现了
  4. 类方法只能访问类变量或者类方法,但是反之普通成员方法既可以访问非静态成员,也可以访问静态成员
  5. 类变量的生命周期随着类的加载开始,随着类消亡而销毁
  6. 如果父类中含有一个静态方法,且在子类中也含有一个返回类型、方法名、参数列表均与之相同的静态方法,那么该子类实际上只是将父类中的该同名方法进行了隐藏,而非重写。换句话说,父类和子类中含有的其实是两个没有关系的方法,它们的行为也并不具有多态性

语法:访问修饰符 static 数据类型 变量名; (访问修饰符和static的顺序可以交换)

访问方式: 类名.类变量(推荐) 对象名.类变量名

// 举例类变量和类方法的使用
// Math类的源码
 public static final double PI = 3.14159265358979323846;
// 取绝对值
@HotSpotIntrinsicCandidate
public static int abs(int a) {
    return (a < 0) ? -a : a;
}
Main方法

解释main方法的形式; pubLic static void main(String[]args)

public class HelloMain {
    /*
     * 1.main方法时虚拟机调用
     * 2.java虚拟机调用类的main方法,所以该方法的访问权限必须是public
     * 3.java虚拟机在执行main()方法时不必创建对象,所以用static
     * 4.Java执行程序 参数1 参数2 参数3【举例说明: java HelloMain hello main !】 参数1:hello 参数2:main 参数3:!
     *
     * 特别提示:
     * 1.在main()方法中,我们可以直接调用main方法所在的类的静态方法和静态属性
     * 2.但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象访问非静态成员
     */
    public static void main(String[]args){
        // args 是如何传入 在idea上设置 Run ->  Edit Configurations  ->  program arguments:
        // 遍历显示
        for(int i=0;i<args.length;i++){
            System.out.println("第"+(i+1)+"个参数"+args[i]);
        }
    }
}
代码块
普通代码块

普通代码块又称初始化块,属于类中的成员部分,没有方法名,没有返回,没有形参,只有方法体

普通代码块不需要被调用,而是加载对象的时候隐式调用

语法:{ // 方法体 }; 没有修饰符 ;分号可有可无

public class CodeBlock {
    /*
     * 代码块
     * 1.相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
     * 2.场景:如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性
     */
    public static void main(String[]args){
        new Movie("爱情神话");
    }
}
class Movie{
    private String name;
    private double price;
    private String director;

    /*
     * 下面的三个构造函数都有相同的语句,这样看起来重复
     * 代码块的使用就可以很好的解决这个问题
     */
    {
        System.out.println("电影开始~~");
    };
    public  Movie(){}
    public Movie(String name){
//        System.out.println("电影开始~~");
        this.name = name;
    }
    public Movie(String name,double price){
//        System.out.println("电影开始~~");
        this.name = name;
        this.price = price;
    }
    public Movie(String name,double price,String director){
//        System.out.println("电影开始~~");
        this.name = name;
        this.price = price;
        this.director = director;
    }
}

注意细节

  • 普通代码块是随着对象的创建而执行的,有几个对象就运行几次代码块
  • 如果不创建对象,只是使用类的静态成员,不会执行代码块
静态代码块

静态代码块,属于类中的成员部分,没有方法名,没有返回,没有形参,只有方法体和修饰符static

静态代码块不需要被调用,而是加载类的时候隐式调用

语法:static{ // 方法体 }; ;分号可有可无

类什么时候被加载?【重点】

  1. 创建对象化实例时,并且父类的也会被加载
  2. 使用类的静态成员时(静态属性,静态方法)
  3. 使用子类的静态成员时

静态代码块的例子

public class StaticCodeBlock {
    /*
     * 父类和子类的静态代码块和普通代码块执行顺序是什么呢?
     * 在父类和子类都有静态代码块和普通代码块时候,创建子类实例时候的执行顺序: 父类静态代码块 --> 子类静态代码块 --> 父类普通代码块 --> 子类普通代码块
     * 在父类和子类都有静态代码块和普通代码块时候,创建父类实例时候的执行顺序: 父类静态代码块 --> 父类普通代码块
     * 在父类和子类都有静态代码块和普通代码块时候,使用父类的静态成员时只调用父类的静态代码块
     * 在父类和子类都有静态代码块和普通代码块时候,使用子类的静态成员时候的执行顺+序: 父类静态代码块 --> 父类普通代码块
     *
     * 静态属性初始化,静态代码块,静态方法,构造器的优先级
     * 1.父类的静态属性初始化优先级 == 静态代码块优先级 (看代码的执行顺序)
     * 2.子类的静态属性初始化优先级 == 静态代码块优先级 (看代码的执行顺序)
     * 3.父类的成员变量初始化优先级 == 普通代码块优先级 (看代码的执行顺序)
     * 4.父类的构造器
     * 5.子类的成员变量初始化优先级 == 普通代码块优先级 (看代码的执行顺序)
     * 6.子类的构造器
     * 方法都需要调用才会执行
     * public 构造函数名(){
     *    1)super()  
     *    2)普通代码块
     *    3)构造函数内容
     * }
     */
    public static void main(String[]args){
        // 使用类的静态成员时(静态属性,静态方法)
        // AA.name = "念笙";
        // AA.show();

        // 创建对象实例时(new)
        // new AA();

        // 创建子类的对象实例,父类也会被加载
        // new BB();

        // 使用子类的静态成员时(静态属性,静态方法)
        // BB.sex = "男";
        // BB.show();

        // 静态初始化,静态代码块,静态方法的优先级
           new CC();
        //   CC.show();
    }
}

class AA{
    public static String name;

    static {
        System.out.println("AA静态代码块被调用");
    }
    {
        System.out.println("AA普通代码块被调用");
    }
    public static void show(){
        System.out.println("name:"+name);
    }
}

class BB extends AA{
    public static String sex;
    static {
        System.out.println("BB静态代码块被调用");
    }
    {
        System.out.println("BB普通代码块被调用");
    }
    public static void show(){
        System.out.println("sex:"+sex);
    }
}

class CC{
    public CC(){
        // 1)super()
        // 2)普通代码块
        System.out.println("构造器被调用");
    }
    // 静态属性初始化
    private static int age = getAge();

    // 静态方法
    public static void show(){
        System.out.println("age:"+age);
    }

    // 静态代码块
    static{
        System.out.println("CC静态代码块被调用");
    }

    public static int getAge(){
        System.out.println("age:"+age);
        return 18;
    }
}
final关键字

final 关键字可以用来修饰类,属性,方法和局部变量 不能修饰构造器

public class Final {
    /*
     * 使用final的情况
     * (1)当不希望类被继承时,可以用final修饰
     * (2)当不希望父类的某个方法被子类覆盖或者重写
     * (3)当不希望类的某个属性的值被修改,可以用final修饰 [例如:final double PI = 3.1415926] -> 常量
     * (4)当不希望某个局部变量被修改,可以用final修饰 -> 局部常量
     *
     * 使用final关键字的细节讨论
     * 1.final修饰的属性又叫常量,一般用 XXX_XXX_XXX来命名
     * 2.final修饰的属性在定义时,必须赋初始值,赋值可以加在如下的位置上
     *    属性定义时初始化 / 在构造器中 / 在代码块中
     *   final修饰的属性是静态的,则,赋值可以加在如下的位置上
     *    静态属性定义时初始化 / 在静态代码块中
     * 3.final类不能继承,但是可以实例化对象
     * 4.如果类不是final类,但是含有final方法,虽然该方法不能重写,但是该类可以被继承
     * 5.final 和 static 往往搭配使用效率更高,不会导致类加载,底层编译器做了优化 如下例子
     * 6.包装类(Integer,double,Float,Boolean等)不能继承
     */
    public static void main(String[] args) {
        /*
         * final 修饰基本数据类型
         * 基本数据类型的值不能发生变化
         */
        final int age = 30;
        // sge = 100; 报错

        /*
         * final修饰引用数据类型
         * 引用数据类型饿地址值不能发生改变,但是该地址上的内容可以发生改变
         */
        final FU fu = new FU();
        // fu.show4();
        // fu = new FU();  报错
        
        // final 和 static 往往搭配使用效率更高,不会导致类加载,底层编译器做了优化
        System.out.println(BB.name);
    }
}

class AA{
   // 静态属性定义时初始化
    public static final int NUMS1 = 12;
    public final int NUM1 = 12;

    public static final int NUMS2;
    public final int NUM2;

    public static final int NUMS3;
    public final int NUM3;
    
    // 在静态代码块中初始化
    static{
        NUMS2 = 12;
        NUMS3 = 12;
    }
    {
        NUM3 = 12;
    }
    // 在构造器中初始化
    public AA(){
        NUM2 = 12;
    }
}

// final 和 static 往往搭配使用效率更高,不会导致类加载,底层编译器做了优化
class BB{
    public static final String name = "yyds";
    static {
        System.out.println("类加载了");
    }
    // 运行效果:不会显示类加载了 说明类没有被加载
}

抽象类

引出:当父类的某些方法需要申明,但又不确定如何实现的时候,可以把这个类变成抽象类 添加 abstract关键字

抽象类的本质还是类可以有方法,属性,代码块,构造器,但是抽象类不能被实例化

语法:

  • 类:访问修饰符 abstract class 类名{}
  • 方法:访问修饰符 abstract 返回类型 方法名(参数列表); // 没有方法体
public class AbstractDemo {
    /*
     * 抽象类 ==> 简化父类方法的不确定代码
     * 抽象类会被继承,由自己的子类实现方法
     *
     * 注意事项: 
     * 1.抽象类不能被实例化,也不能直接通过类名.静态属性的方法来访问抽象类中的静态属性,可以被子类用super关键字调用构造器
     * 2.抽象方法对应抽象类或者接口;但是有抽象类,不仅可以没有抽象方法还可以有方法体的普通方法
     * 3.abstract 只能修饰类和方法
     * 4.如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract,但是如果子类实现抽象类的全部抽象方法,则子类的子类就不需要      *   实现了抽象方法
     * 5.抽象方法不能使用private,final和static来修饰,因为这些关键字都是和重写相违背的
     */
    public static void main(String[] args) {
        // 抽象类不能被实例化
        // Animal animal = new Animal(); 报错
    }
}

// 当一个类中存在抽象方法时候,需要将该类声明成为abstract类
abstract class  Animal{
    public String name;
    // 思考:有意义吗??  ==> 方法不确定性 ==> 考虑设计成抽象类方法(abstract)即是没有方法体 ==> 让子类继承实现
    //    public void eat(){
    //        System.out.println("吃撒");
    //    }
    public abstract void eat();
}
接口

概念:接口在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

语法:访问修饰符 interface 接口名{} 访问修饰符:public 和默认 ; class 类名 implements 接口{ // 必须实现的抽象方法 }

注意细节

  • 在jdk7之前都是没有方法体的抽象方法,在jdk8以后接口的方法可以有具体实现,但是必须是静态方法或者是默认方法

    // 接口中的所有方法都是public修饰的方法,接口中的抽象方法可以不用被abstract修饰
    // 可以通过接口名.静态方法名来调用静态方法 接口名.属性名来访问属性
    interface Interface{
        // 属性 默认是public  static final修饰
        int n1 = 10;
    
        // 抽象方法  默认是public abstract
         void method1();
    
        // 默认方法 添加default关键字  默认是public 
        default public void method2(){
            System.out.println("默认方法");
        }
    
        // 静态方法
        public static void  method3(){
            System.out.println("静态方法");
        }
    } 
    
  • 接口不能被实例化

  • 一个非抽象类实现了该接口就必须实现该接口上的所有抽象方法,抽象类去实现接口时候,可以不用实现接口的抽象方法

  • 一个类同时可以实现多个接口,一个接口不能继承其他的类,但是可以继承多个其他接口

    // 顶级接口
    interface top{}
    
    // 父级接口  一个接口不能继承其他的类,但是可以继承多个其他接口
    interface secondTop extends top{}
    
    //另外一个接口
    interface another{}
    
    // 实现类 一个类同时可以实现多个接口
    class imp implements secondTop,another{}
    

实现接口 Vs 继承类

  1. 接口和继承解决的问题不同
    继承的价值主要在于:解决代码的复用性和可维护性
    接口的价值主要在于:设计好各种规范(方法),让其他类去实现这些方法

  2. 接口比继承更加灵活
    继承满足is-a的关系,而接口只需满足like-a的关系

  3. 接口在一定程度上实现代码解耦[接口的规范性+动态绑定]

抽象类和接口的区别

  • 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
  • 抽象可以有普通方法(含有方法体),接口只能是默认方法(带有default关键字)

接口的多态性

// Usb接口
public interface UsbInterface {  
    // 规定相关接口的方法
    public void start();
    public void end();
}

// 相机实现了该接口
public class Camera implements UsbInterface{ 
    @Override
    public void start() {
        System.out.println("照相机开始运行了~");
    }

    @Override
    public void end() {
        System.out.println("照相机开始关机了~");
    }
}

// 手机实现了该接口
public class Phone implements UsbInterface{ // 实现接口
    @Override
    public void start() {
        System.out.println("手机开始运行了~");
    }

    @Override
    public void end() {
        System.out.println("手机开始关机了~");
    }
}

// 接口插入,分别实现不同功能
public class Computer {
    // 计算机工作
    public  void work(UsbInterface usbInterface){
        usbInterface.start();
        usbInterface.end();
    }
}

public class Interface01 {
    /*
     * 接口多态特性
     * 1)既可以接收手机对象,又可以接受相机对象,就体现了接口多态(接口引用可以指向实现了该接口的类的对象)
     * 2)多态数组
     * usbs[i] instanceof Phone 向下转型,判读Usb接口是否为Phone
     * 接口类型的变量可以指向实现了该接口的类的对象的实例
     */
    public static void main(String[]args){
        // 创建手机和相机对象
        Camera camera = new Camera();
        Phone phone = new Phone();
        // 创建电脑对象
        Computer computer = new Computer();
        // 插入接口,相机和手机分别运作
        computer.work(phone);
        computer.work(camera);
        // 多态数组
        UsbInterface[] UsbS = new UsbInterface[2]; 
        UsbS[0] = new Phone(); 
        UsbS[1] =  new Camera();
    }
}

内部类

概念:一个类的内部嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类称为外部类(注意类的五大成员:属性,方法,构造器,代码块,内部类)

class OuterClass{ // 外部类
    int n1 = 100; // 属性
    public OuterClass(int n3){} // 构造方法
    void n2(){} //方法
    {} // 代码块
    class InnerClass{} // 内部类
}

语法:class Outer{ // 外部类 class Inner{ // 内部类 } }

内部类的分类:

  • 定义在外部类局部位置(比如方法内)
    • 局部内部类(有类名)
    • 匿名内部类(没有类名,重点)
  • 定义在外部类的成员位置上
    • 成员内部类(没有static修饰)
    • 静态内部类(有static修饰)
局部内部类

局部内部类是定义在外部类的局部位置(比如:方法中),并且有类名

作用域:仅在定义它的方法或代码块中

class OuterClass02{ // 外部类
    private int n1 = 100;
    public void n2(){
        /*
         * 局部内部类
         * 1.局部内部类是定义在外部类的局部位置,通常在方法里或者代码块里
         * 2.局部内部类可以访问外部类的所有成员变量,包含私有的
         * 3.局部内部类不能添加访问修饰符,但是是可以被final修饰,可以不被继承
         * 4.作用域:仅在定义它的方法或代码块中
         * 5.外部类在方法中可以创建InnerPartClass对象,然后调用局部内部类的方法,不允许在方法外创建该对象
         * 6.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果就想访问外部类的成员,则可以使用(外部类名.this.成员)
         */
        class InnerPartClass{ 
            private int n1 = 20;
            public void n3(){
                // 7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)
                System.out.println(n1); // 20
                // 解读OuterClass02.this 本质就是外部类的对象即那个对象调用了n2方法,OuterClass02.this就是那个对象,这里是out对象调用的,因此					  OuterClass02.this指向out对象
                System.out.println(OuterClass02.this.n1); // 100
                System.out.println(OuterClass02.this); // com.Al_tair.innerClass_.OuterClass02@27d6c5e0
            }
        }
        // 5.外部类在方法中可以创建InnerPartClass对象,然后调用局部内部类的方法
        InnerPartClass innerPartClass = new InnerPartClass();
        innerPartClass.n3();
    }
}

public class InnerClass01 { // 外部其他类
    public static void main(String[] args) {
        OuterClass02 out = new OuterClass02();
        out.n2();
        System.out.println(out); // com.Al_tair.innerClass_.OuterClass02@27d6c5e0
    }
}
匿名内部类

概念:定义在外部类的局部位置,没有类名

作用域:仅仅在定义它的方法和代码块中

语法:new 类名或接口名(参数列表){ // 匿名内部类 }

public class AnonymousInnerClass {
    /*
     * 匿名内部类
     * 定义在外部类的局部位置<=>局部内部类(没有表露出来的类名)
     * 基本语法:new 类或接口(参数列表){}
     */
    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        outClass.meathod();
    }
}

class OutClass{
    private int n = 10;
    public void meathod(){
        /*
         * 使用匿名内部类简化开发
         * aa的编译类型 -- AA ; aa的运行类型 -- 匿名内部类OutClass$1 (外部类名$匿名内部类的序号)
         * 1.创建匿名内部类后马上创建该实例,并返回该地址给aa
         * 2.匿名内部类只能使用一次,但是该实例对象可以反复引用,就是不能用一个匿名内部类创建多个对象实例
         * 3.不能添加访问修饰符,因为它的就是一个局部变量
         * 4.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)
         */
        // 第一种调用匿名内部类的内部方法
        // 这里new的不是接口实例化,而是接口的匿名内部实现类
        AA aa = new AA(){ // 向上转型
            @Override
            public void cry() {
                System.out.println("嘤嘤嘤~~");
            }
        };
        aa.cry();
        System.out.println(aa.getClass()); // class com.Al_tair.innerClass_.OutClass$1

        // 第二种调用匿名内部类的内部方法
        System.out.println(
            new AA(){
                @Override
                public void cry() {
                    System.out.println("555~~");
                }
            }.getClass()
        ); // class com.Al_tair.innerClass_.OutClass$2
    }
}

interface AA{
    void cry();
}

实践

// 对比传统方式和匿名内部类的区别
public class Test {
    public static void main(String[] args) {
        // 当作实参直接传递,简洁高效
        show(new Paint() {
            @Override
            public void show() {
                System.out.println("最美油画!");
            }
        });

        // 传统方式
        new Picture().show();
    }

    public static void show(Paint paint){
        paint.show();
    }
}

// Paint接口
interface Paint{
    public void show();
}

class Picture implements Paint{
    @Override
    public void show() {
        System.out.println("最美油画!");
    }
}
成员内部类

概念:成员内部类是定义在外部类的成员位置,并且没有static修饰

作用域: 可以直接访问外部类的所有成员

public class MemberInnerDemo01 {
    public static void main(String[] args) {
        // 成员内部类的访问方式、
        // 1.创建外部类的对象来调用
        //   1.创建外部类的对象
        MemberOuterClass memberOuterClass = new MemberOuterClass();
        //   2.创建成员内部类的对象 需要加外部类名 (如: 外部类名.内部类名 对象引用名 = 外部类的对象名.new 内部类名();)
        MemberOuterClass.InnerClass innerClass = memberOuterClass.new InnerClass();

        // 2.调用外部类方法访问成员内部类
        MemberOuterClass.InnerClass innerClass2 = new MemberOuterClass().getInnerInstance();
    }
}

class MemberOuterClass{
    /*
     *  成员内部类(没有static修饰)
     *  1.作用域: 可以直接访问外部类的所有成员
     *  2.可以添加任意的访问修饰符: public 默认 protected private
     *  3.定义在外部类的成员位置上
     *  4.成员内部类的访问方式
     *    1.成员内部类 —> 外部类成员 [直接访问]
     *    2.外部类 -> 成员内部类 [创建成员内部类的对象,再访问]
     *    3.其他外部类 -> 成员内部类 [创建外部类的对象,创建成员内部类的对象,再访问如上第一点]
     *  5.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)
     */
    protected class InnerClass{}
    public InnerClass getInnerInstance(){
        return new InnerClass();
    }
}
静态内部类

概念:成员内部类是定义在外部类的成员位置,并且有static修饰

作用域: 可以直接访问内部类的所有静态成员,包含私有的,但是不能访问非静态成员

public class StaticInnerClass {
    public static void main(String[] args) {
        StaticOuterClass.StaticInner staticClass = new StaticOuterClass.StaticInner();
        staticClass.say();
    }
}

class StaticOuterClass{
   /*
    * 静态内部类 static修饰
    * 1.可以直接访问内部类的所有静态成员,包含私有的,但是不能访问非静态成员
    * 2.可以添加任何的访问修饰符: public 默认 protected private
    * 3.静态内部类的访问方式(2和3创建静态内部类的对象写法不一样)
    *   1.静态内部类 -> 外部类 [直接访问所有静态成员]
    *   2.外部类 -> 静态内部类 [创建静态内部类的对象,再访问]
    *   3.其他外部类 -> 静态内部类 [创建静态内部类的对象,再访问]
    *  4.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员)
    */
    static class StaticInner{
        public  void say(){
            System.out.println("StaticInner 在 saying");
        }
    }
}

相关面试题

1.请说明Java的接口和C++的虚类的相同和不同处

由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。
与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public,一个类可以实现多个接口。

2.接口和抽象类的区别是什么?

  1. 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
  2. 类可以实现很多个接口,但是只能继承一个抽象类
  3. 类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
  4. 抽象类可以在不提供接口方法实现的情况下实现接口。
  5. Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
  6. Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
  7. 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗念笙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值