面向对象(下)

1.关键字:static

1.1类属性(静态变量)和类方法(静态方法)的设计思想

类属性(静态变量)与类方法(静态方法):作为该类的各个对象之间共享的变量。在设计类时,那些不因对象的不同而改变的属性(方法)可设置为类属性(方法)。由于不需要创建对象就可以调用静态方法,简化的方法的调用。调用格式为:类名.方法名(形参列表)。

1.2static的使用范围

属性,方法,代码块,内部类。注意:构造器不可以。

1.3static修饰属性

<1>使用static修饰属性→静态变量(或称类变量,类属性)

<2>按是否有static修饰,属性分为静态属性和非静态属性(或称实例变量)

静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。当通过某一个对象a修改静态变量后,其他对象在调用此静态变量时,此静态变量的值为对象a修改后的值。

实例变量:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象中的非静态属性时,其他对象中同样属性的属性值不会改变。

静态变量实例变量
可以调用不可以调用
对象可以调用可以调用

<3>静态变量是随着类的加载而加载,其加载要早于对象的创建;且由于类只会加载一次,所以静态变量在内存中也只会存在一份→存在方法区的静态域内。

<4>访问权限允许时,可不创建对象,直接被调用:类名.静态变量名。

<5>Java中,static不可以用来修饰局部变量

1.4static修饰方法

<1>使用static修饰方法→静态方法(或称类方法)

<2>静态方法随着类的加载而加载,可通过“类名.静态方法名()”的方式进行调用

<3>

静态方法非静态方法
可以调用不可以调用
对象可以调用可以调用

<4>静态方法中,只能调用静态的方法或属性(可从类和对象的生命周期角度思考);

      非静态方法中,既可以调用非静态的方法和属性,也可以调用静态的方法和属性。

1.5static使用的注意点

<1>在静态的方法内,不能使用this关键字,super关键字;

<2>static修饰的方法不能被重写。

1.6何时将属性和方法声明为static的

<1>对于属性,若某属性是可以被多个对象所共享的,不会随着对象的不同而不同;

<2>对于方法,1)操作静态属性的方法,通常设置为static的,2)工具类中的方法,习惯上声明为static的。

1.7简单举例

public class Entity //Entity类
{
    private int id; //实体的编号
    private static int total; //静态属性,总的实体的个数
    private static int init; //静态属性,实体的编号要递增
    public Entity() //构造器
    {
        id=init++;
        total++;
    }
    public static int getTotal() //静态方法,返回总的实体个数
    {
        return total;
    }
}
public class EntityTest
{
    public static void main(String[] args)
    {
        Test a=new Entity();
        Test b=new Entity();
        System.out.println(b.getTotal()); //2
        System.out.println(Test.getTotal()); //也是2
    }
}

2.单例设计模型(Singleton)

2.1设计模式

是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。

2.2单例模型是什么以及实现方法

类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类提供一个取得其对象实例的方法。

要想让类在一个虚拟机中只产生一个对象,1)首先将类的构造器访问权限设置为private,这就无法在类外部产生该类的对象;2)再在类内部new一个当前类的实例;3)调用该类的静态方法返回类内部创建的对象。注意,由于静态方法只能访问类中的静态变量,所以指向类内部产生该类对象的变量也必须定义为静态的。

2.3代码实现

<1>饿汉式

public class Singleton //单例模式,饿汉式
{
    private Singleton () //声明构造器为private
    {}
    //声明当前类的对象,且为static
    private static Singleton singleton=new Singleton(); 
    //声明public static 返回当前类对象的方法
    public static Singleton getSingleton()
    {
        return singleton;
    }
}

<2>懒汉式

public class Singleton //单例模式,懒汉式
{
    private Singleton()
    {}
    private static Singleton singleton=null;
    public static Singleton getSingleton()
    {
        if(singleton==null)
            singleton=new Singleton();
        return singleton;
    }
}

饿汉式与懒汉式的对比:

饿汉式:好处:是线程安全的;坏处:对象加载时间过长

懒汉式:好处:延迟对象的创建;坏处:线程不安全(当前写法不安全,后面学了多线程再改)

2.4单例模式的优点

单例模式只生成一个实例,减少了系统的开销,当一个对象的产生需要较多的资源时,如读取配置,产生其他依赖对象时,则可以通过再应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

2.5单例模式的应用场景

1)网站的计数器,一般也是单例模式实现,否则难以同步。
2)应用程序的日志应用,一般都使用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
3)数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
4)项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,都生成一个对象去读取。
5)Application 也是单例的典型应用
6)Windows的Task Manager (任务管理器)就是很典型的单例模式
7)Windows的Recycle Bin (回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

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

3.1代码块的作用

用来初始化类、对象的信息

3.2代码块的修饰符

代码块如果使用修饰符,也只能使用static,所以有:静态代码块和非静态代码块

3.3静态代码块

<1>内部可有输出语句;

<2>随着类的加载而加载,而且只执行一次;

<3>作用:初始化类的信息;

<4>如果一个类中定义了多个静态代码块,则按声明的先后顺序执行;

<5>静态代码块优先于非静态代码块的执行;

<6>静态代码块内只能调用静态的属性、方法,不能调用非静态的。

3.4非静态代码块

<1>内部可有输出语句;

<2>随着对象的创建而执行,每创建一个对象就执行一次;

<3>作用:可在创建对象时,对对象的属性进行初始化;

<4>非静态代码块内可以调用静态和非静态的属性、方法。

3.5关于代码块的一些注意事项

<1>非静态代码块的执行先于构造器;

<2>对于存在父类,存在静态代码块,存在非静态代码块的程序,要由父及子,静态先行

<3>在类中,对于属性的显式初始化和代码块,按照代码顺序的前后依次执行。

3.6一个简单举例

class Root
{
    static//静态代码块
    {
        System.out.println("Root的静态初始化块");
    }
    {//非静态代码块
        System.out.println("Root的普通初始化块");
    }
    public Root(){
        System.out.println("Root的无参数的构造器");
    }
}

class Mid extends Root
{
    static
    {
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid(){
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg)
    {
        this();
        System.out.println("Mid的带参数构造器,其参数值:"+ msg);
    }
}

class Leaf extends Mid
{
    static
    {
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }
    public Leaf(){
        super("学Java");
        System.out.println("Leaf的构造器");
    }
}

public class LeafTest
{
    public static void main(String[] args)
    {
        new Leaf();
        System.out.println("**************************");
        new Leaf();
    }
}

//        输出结果如下:
//        Root的静态初始化块
//        Mid的静态初始化块
//        Leaf的静态初始化块
//        Root的普通初始化块
//        Root的无参数的构造器
//        Mid的普通初始化块
//        Mid的无参数的构造器
//        Mid的带参数构造器,其参数值:学Java
//        Leaf的普通初始化块
//        Leaf的构造器
//        **************************
//        Root的普通初始化块
//        Root的无参数的构造器
//        Mid的普通初始化块
//        Mid的无参数的构造器
//        Mid的带参数构造器,其参数值:学Java
//        Leaf的普通初始化块
//        Leaf的构造器

4.关键字:final

4.1final可修饰的结构

类,方法,变量

<1>final修饰类:此类就不能被其他类所继承 (格式:权限修饰符  final class A{ } )

eg:String类,System类,StringBuffer类

<2>final修饰方法:此方法就不能被重写 (格式:权限修饰符 final 返回值类型 B() {})

eg:Object类中的getClass(方法)

<3>final修饰变量:此时“变量”称为是一个常量,常量名需全部大写 (final 变量类型 a=10)

注意:当使用final修饰形参时,表明此形参是一个常量,当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能重新赋值。

4.2全局常量:static final

5.抽象类与抽象方法

5.1关键字:abstract

<1>abstract可以用来修饰的结构:类,方法

<2>abstract修饰类→抽象类

1)这个类不能被实例化;

2)抽象类中一定有构造器(即使没有显示的声明),便于子类实例化时调用;

3)开发中都会提供抽象类的子类,让子类对象实例化。

<3>abstract修饰方法→抽象方法

1)抽象方法只有方法的声明,没有方法体

eg:public abstract void eat();

2)包含抽象方法的类,一定是一个抽象类;反之,抽象类可以没有抽象方法;

3)若子类重写了父类中所有的抽象方法后,此子类方可实例化;只要存在有一个父类中的抽象方法没有被子类重写,这个子类就仍是一个抽象类。

<4>abstract不能用来修饰私有方法,静态方法,final的方法,final的类

5.2抽象类的匿名类

代码展示:

抽象类:Person类,含有两个抽象方法eat()和walk()

public abstract class Person
{
    int age;
    String name;
    public abstract void eat();
    public abstract void walk();
}
public class PersonTest
{
    public static void main(String[] args)
    {
        //创建了一个匿名子类的对象:p
        Person p=new Person()//这里还必须写成new Person()的形式
        {
         //里面要对Person类中所有的抽象方法进行重写
            @Override
            public void eat()
            {
                System.out.println("人吃饭");
            }
            @Override
            public void walk()
            {
                System.out.println("人走路");
            }
        };//这里还需要加个分号
        method(p);

//方法二
//        //方法一还创建匿名子类的匿名对象,前面的代码还有对象名p,方法二这里对象名都没有
//        method(new Person()
//        {
//            @Override
//            public void eat()
//            {
//                System.out.println("人吃饭");
//            }
//            @Override
//            public void walk()
//            {
//                System.out.println("人走路");
//            }
//        });
    }
    public static void method(Person p)
    {
        p.eat();
        p.walk();
    }
}

5.3模板方法设计模式(TemplateMethod)

<1>解决的问题:当功能内部一部分实现是确定的,一部分实现是不确定的,这时可以把不确定的部分暴露出去,让子类去实现。

换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变部分可以抽象出来,供不同子类实现,这就是一种模板模式。

<2>举例说明:代码展示

abstract class Template
{
    //计算某段代码执行所需要花费的时间
    public void spendTime()
    {
        long start = System.currentTimeMillis();
        this.code();//不确定的部分、易变的部分
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为:" + (end - start));
    }
    public abstract void code(); //不确定的部分,声明为abstract方法,让子类去实现
}

class SubTemplate extends Template
{
    @Override
    public void code() //一段输出1000以内质数的代码
    {
        for(int i = 2;i <= 1000;i++)
        {
            boolean isFlag = true;
            for(int j = 2;j <= Math.sqrt(i);j++)
            {
                if(i % j == 0)
                {
                    isFlag = false;
                    break;
                }
            }
            if(isFlag)
            {
                System.out.println(i);
            }
        }

    }
}

public class Test
{
    public static void main(String[] args)
    {
        SubTemplate a=new SubTemplate();
        a.spendTime();
    }
}

5.4一个简单例题

编写工资系统,实现不同类型员工(多态)的按月发放工资,如果当月出现某个Employee对象的生日,则将该员工的工资增加¥100.

说明:1)定义一个Employee类,该类包含:private成员变量name,number,birthday,其中birthdayMyDate类的对象;abstract方法earnings();toString()方法输出对象的name,numberbirthday。  2)MyDate类包含:private成员变量year,month,day;toDateString()方法返回日期对应的字符串:xxxxxxxx日 。  3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处理。该类包括:private成员变量monthlySalary;实现父类的抽象方法earnings(),该方法返回monthlySalary值;toString()方法输出员工类型信息及员工的namenumber,birthday。 4)定义HourlyEmployee类,实现按小时计算工资的 员工处理。该类包括:private成员变量wagehour;实现父类的抽象方法earnings(),该方法返回wage*hour值;toString()方法输出员工类型信息及员工的namenumber,birthday。 5)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各类雇员对象的引用。利用循环结构遍历数组元素,输出各个对象的类 型,name,number,birthday,以及该对象生日。当键盘输入本月月份值时,如果本月是某个Employee对象的生日,还要输出增加工资信息。

代码展示:

MyDate类:

public class MyDate
{
   private int year;
   private int month;
   private int day;
    /**
     构造器
     */
   public MyDate(int year,int month,int day)
   {
       this.year=year;
       this.month=month;
       this.day=day;
   }
   /**
   输出年月日
    */
   public String toDateString()
   {
       return year+"年 "+month+"月 "+day+"日 ";
   }
   public int getMonth()
   {
       return month;
   }
}

Emplyee类:

public abstract class Employee
{
    private String name;
    private int number;
    private MyDate birthday;
    public Employee()
    {}
    /**
     构造器
     */
    public Employee(String name,int number,MyDate birthday)
    {
        this.name=name;
        this.number=number;
        this.birthday=birthday;
    }
    /**
     抽象方法
     */
    public abstract double earnings();
    /**
     重写toString方法
     */
    @Override
    public String toString()
    {
        return "Employee{" +
                "name='" + name + '\'' +
                ", number=" + number +
                ", birthday=" + birthday.toDateString() +
                '}';
    }
    public MyDate getBirthday()
    {
        return birthday;
    }
    public String getName()
    {
        return name;
    }
    public int getNumber()
    {
        return number;
    }
}

SalariedEmployee类:

public class SalariedEmployee extends Employee
{
    private double monthlySalary;
    public SalariedEmployee(String name,int num,MyDate birthday,double monthlySalary)
    {
        super(name,num,birthday);
        this.monthlySalary=monthlySalary;
    }
    @Override
    public double earnings()
    {
        return monthlySalary;
    }
    @Override
    public String toString()
    {
        return "SalariedEmployee["+super.toString()+"]";
    }
}

HourlyEmployee类:

public class HourlyEmployee extends Employee
{
    private double wage;
    private double hour;
    public HourlyEmployee(String name,int num,MyDate birthday,double wage,double hour)
    {
        super(name,num,birthday);
        this.wage=wage;
        this.hour=hour;
    }
    @Override
    public double earnings()
    {
        return wage*hour;
    }
    @Override
    public String toString()
    {
        return "HourlyEmployee["+super.toString()+"]";
    }
}

 PayrollSystem类:

public class PayrollSystem
{
    public static void main(String[] args)
    {
        Employee[] emps=new Employee[]{
                new SalariedEmployee("Tom",1,new MyDate(1998,12,3),1900),
                new SalariedEmployee("Jay",2,new MyDate(1997,1,23),2000),
                new SalariedEmployee("Lei",3,new MyDate(1996,5,12),1950),
                new HourlyEmployee("Eason",4,new MyDate(1999,10,12),90,12)};
        for(int i=0;i<emps.length;i++)
        {
            System.out.println(emps[i].toString());
            if(emps[i] instanceof SalariedEmployee && emps[i].getBirthday().getMonth()==5)//5月生日的员工工资加100
                System.out.println("员工"+emps[i].getName()+"本月工资额外加100");
        }
    }
}

6.接口(interface)

6.1接口的使用

<1>接口使用interface来定义;

<2>Java中,接口和类是并列的两个结构;

<3>如何定义接口,定义接口中的成员:

1)jdk7之前,只能在接口内定义全局变量和抽象方法

全局变量:public static final (具体code时,可省略public static final,因为系统会自动默认)

抽象方法:public abstract (具体code时,可省略public abstract)

2)jdk8:除了定义全局常量和抽象方法外,还可以定义静态方法和默认方法

<4>接口不能定义构造器:意味着接口无法实例化

<5>接口通过让类去实现(implements)的方式来使用

eg:class Plane implements Flyable {}

若实现类覆盖了接口中的所有抽象方法,则此实现类就可实例化;

若实现类没有覆盖接口中的所有抽象方法,则此实现类仍为一个抽象类。

<6>Java类可以实现多个接口→弥补了Java单继承的局限性

格式: class AA extends BB implements CC,DD,EE

<7>接口与接口之间可以继承,且可以多继承

格式:interface AA extends BB,CC

<8>接口的具体使用,体现了多态性

<9>创建接口实现类的匿名对象

针对<8>和<9>,有个简单举例,见代码如下:

public class InterfaceTest
{
    public static void main(String[] args)
    {
        Computer computer=new Computer();
        Flash flash=new Flash();
        computer.transferDate(flash);

//下面代码为非匿名实现类的匿名对象
//computer.transferDate(new Flash());

//下面代码为匿名实现类的非匿名对象
//USB usb=new USB(){
//  public void start()
//     {
//         System.out.println("start");
//     }
//  public void stop()
//     {
//         System.out.println("stop");
//     }
// }
//computer.transferDate(usb);
        
//下面的代码为匿名实现类的匿名对象的代码
//        computer.transferDate(new USB(){
//            public void start()
//            {
//                System.out.println("start");
//            }
//            public void stop()
//            {
//                System.out.println("stop");
//            }
//        });
    }
}

interface USB
{
    void start();
    void stop();
}

class Flash implements USB
{
    public void start()
    {
        System.out.println("U盘开始工作");
    }
    public void stop()
    {
        System.out.println("U盘停止工作");
    }
}

class Printer implements USB
{
    public void start()
    {
        System.out.println("打印机开始工作");
    }
    public void stop()
    {
        System.out.println("打印机停止工作");
    }
}

class Computer
{
    public void transferDate(USB usb)
    {
        usb.start();
        System.out.println("数据传输中.....................");
        usb.stop();
    }
}

<10>接口上实际上是一种规范

<11>开发中,体会面向接口编程

6.2接口应用之——代理模式

代理设计:就是为其它对象提供一种代理以控制对这个对象的访问。

代码展示:这个ProxyServer就是Server的代理,通过ProxyServer来访问Server对象。

public class ProxyTest
{
    public static void main(String[] args)
    {
        Server server=new Server();
        ProxyServer pro=new ProxyServer(server);
        pro.brower();
    }
}

interface Network
{
    public abstract void brower();
}

class Server implements Network
{
    public void brower()
    {
        System.out.println("真实服务器的浏览");
    }
}

class ProxyServer implements Network
{
    private Network network; //这一步和下一步是关键
    public ProxyServer(Network network)
    {
        this.network=network;
    }
    public void check()
    {
        System.out.println("做好网络检查");
    }
    public void brower()
    {
        check();
        network.brower();
    }
}

6.3接口应用之——工厂模式

6.4jdk8中接口的新特性

接口中还可以定义静态方法和默认方法

<1>格式:

静态方法:public static 权限修饰符 AA { }

默认方法:public default 权限修饰符 BB { }

<2>一些说明:

1)接口中定义的静态方法,只能通过接口来调用;

2)接口中定义的默认方法,通过实现类的对象来调用;

3)如果实现类(假如存在父类)继承的父类和实现的接口中声明了同名同参的默认方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参的方法。称作类优先原则(属性不可以)。

4)如果实现类实现了多个接口,而且这多个接口定义了同名同参的默认方法,那么在实现类没有重写此方法的情况下,将会报错。称作接口冲突(这就需要我们必须在实现类中重写此方法)

5)如果在实现类的方法中调用接口中被重写的默认方法,使用:接口名.super.方法名(),对于静态方法依旧为,使用:接口名.方法名()

<3>代码展示:

CompareA接口:

public interface CompareA
{
    public static void method1() //静态方法
    {
        System.out.println("CompareA:北京");
    }
    public default void method2() //默认方法
    {
        System.out.println("CompareA:上海");
    }
    default int method3() //默认方法
    {
       return 3;
    }
}

以下为基于该接口的其他代码:

public class SubclassTest
{
    public static void main(String[] args)
    {
        Subclass a=new Subclass();
        CompareA.method1();
        //a.method1(); 这样错误,因为接口中的静态方法,只能通过接口调用
        System.out.println(a.method3()); //返回的是10,因为类优先原则
        a.show();
    }
}

class Adf
{
    public int method3()
    {
        return 10;
    }
}

class Subclass extends Adf implements CompareA
{
        public void show()
        {
            CompareA.super.method2();
        }
}

//输出结果为:
//CompareA:北京
//10
//CompareA:上海

7.类的成员之无——内部类

7.1定义

Java允许将一个类A声明在一个类B中,则类A就是内部类,类B为外部类。

7.2内部类的分类

<1>成员内部类(又可分为静态成员内部类,非静态成员内部类)

<2>局部内部类(定义在方法内、代码块内、构造器内)

注意:成员内部类和局部内部类编译后都会生成字节码文件,其中,成员内部类:外部类$内部类名.class;局部内部类:外部类$数字 内部类名.class

7.3成员内部类

<1>成员内部类的理解

▲一方面,作为外部类的成员

1)可以调用外部类的结构;

2)可以被static修饰,此时就不能在调用外部类中非static的成员变量;

3)可以被四种权限修饰符所修饰;

▲另一方面,作为一个类

1)类内可以定义属性,方法,构造器

2)可以被final修饰,表示此类不能被继承,也就是说不使用final,就可以被继承;

3)可以被abstract修饰;

<2>一些注意事项:

1)非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员;

2)外部类访问成员内部类的成员,需要”内部类.成员(对静态成员内部类而言)“或”内部类对象.成员(对非静态成员内部类而言)“的方式;

3)成员内部类可以直接使用外部类的所有成员,包括私有的数据;

4)当想要在外部类的静态成员部分使用内部类时,可以考虑将内部类声明为静态的。

<3>成员内部类的使用

1)如何创建成员内部类的对象(以类Person为例,其含有一个静态内部类Brain,一个非静态内部类Hands)

▲创建静态的Brain内部类的实例(静态的成员内部类的对象)

Person.Brain brain=new Person.Brain();

▲创建非静态的Hands内部类的实例(非静态的成员内部类的对象)

Person p=new Person();

Person.Hands hands=p.new Hands();
2)如何在成员内部类中调用外部类的结构

class Animal
{
    String name = "小白";
public void eat()
{
   System.out.println("动物都吃东西");
}
//非静态成员内部类
    class Bird
    {
        String name = "杜鹃";
        public void display(String name)
        {
            System.out.println(name);//方法的形参
            System.out.println(this.name);//内部类的属性
            System.out.println(Animal.this.name);//外部类的属性(注意这里的格式)
            Person.this.eat();//也可以直接写成eat(),前提是内部类中没有重名的方法
        }
    }
}

public class InnerclassTest
{
   public static void main(String[] args)
   {
      Animal animal=new Animal();
      Animal.Bird bird=animal.new Bird();
      bird.display("黄鹂");
   }

//输出结果为:
//黄鹂
//杜鹃
//小白
//动物都吃东西

7.4局部内部类的使用

1)只能在类的方法和代码块中声明;

2)与局部变量类似,不能使用四种权限修饰符,不能用static修饰,因此不能包含静态成员;

3)在局部内部类的方法中(比如show()),如果调用局部内部类所在的方法(比如method())中的局部变量的值,要求此局部变量声明为final(jdk8之后,final可省略,默认为常量);

public void method
{ 
  int num=10;//默认为final
  class AA //局部内部类
  {
    public void show()
    {
      System.out.println("show");
    }
  }

4)开发中一般这样用,局部内部类的对象可以通过外部方法的返回值返回使用,返回值类型设置为局部内部类的父类或者父接口类型,如下:

public Comparable getComparable() //这个Comparable是一个接口类型
{
  class MyComparable implements Comparable
  {
    @override
    public int compareTo(Object o)
    {
      ............
    }
  }
  return new MyComparable
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值