Java第三周学习总结

day_12

一、Object

1、Object是所有类的父类

        声明一个类没有指定父类的时候,默认这个类就是继承于Object的
        这个类存放与:java.lang包中

2、toString方法()

        Object类提供的toString()方法,所有的类都拥有toString方法
        作用:将对象以字符串的形式进行处理

3、getClass()方法

        作用:返回正在运行的类是哪一个(第一次学习的同学,在这里不要纠结,只做了解,因为后面的        学习中会使用一个内容叫:反射,反射的前提就是要先找到当前执行的类)

Object o = new Object();
        System.out.println(o.toString());
        //getClass():获取到当前正在执行的是哪个类
        //getName():获取到当前的类的名称是什么
        String classPath = o.getClass().getName();
        System.out.println(classPath);

        People people = new People("张三",20);
        System.out.println(people.getClass().getName());
     System.out.println(people.toString());

4、equals(Object obj)方法

用于判断两个对象是否相等

 

public class People extends Object{
    private String name;
    private int age;
    
@Override
    public boolean equals(Object o) {
        //两个对象完全相同
        if (this == o) return true;
        //如果对象为空或者两个执行的对象不属于同一个类
        if (o == null || getClass() != o.getClass()) return false;
        //两个类存在继承关系,然后大的数据类型转小的数据类型,判断属性是否相同
        //如果属性相同就返回为true
        People people = (People) o;
        return age == people.age &&
                name.equals(people.name);
    }
}
    
public class Test_03 {
    public static void main(String[] args) {
        People p1 = new People("张三",20);
        People p2 = new People("李四",20);

        System.out.println(p1.equals(p2));

        People p3 = new People("abc",33);
        Emp emp = new Emp("abc",20);

        System.out.println(p3.getClass().getName());
        System.out.println(emp.getClass().getName());

        System.out.println(p3.equals(emp));
    }
}

5、instanceof:比较两个对象是否相同

当两个类之间存在继承关系,或者类与接口之间存在实现关系,我们可以使用instanceof来判断一个对象是否属于某一个类型。
public void menuDept(){
        System.out.println("***************");
        System.out.println("1、部门添加信息");
        System.out.println("2、修改部门信息");
        System.out.println("3、删除部门信息");
        System.out.println("4、查询单个部门信息");
        System.out.println("5、查询所有部门信息");
        System.out.println("***************");
        System.out.println("输入你的操作:");
        int num = sc.nextInt();
        switch (num){
            case 1:
                Dept dept = new Dept("10001","销售部","45678955");
                Emp emp = new Emp("1111","张三","男",30,"后勤部",3000);
                //方法的参数默认需要一个Object类型的元素,Object是所有类的父类
                //所以在这里的话,虽然Dept没有去写继承Object,但是已经默认继承
                boolean flag = deptDao2.add(emp);
                if(flag){
                    System.out.println("添加成功");
                }else{
                    System.out.println("添加失败");
                }
                menuDept();
                break;
                }
}
public boolean add(Object o) {
        //举个栗子:
        //  int a = 100;
        //  double b = a;
        //  int c = b;
        //判断o是不是Dept类型的元素
        if(o instanceof Dept){
            //如果是就强制转换
            //强制转换之后就可以将o的信息转换为Dept类的信息,转换完成之后可以存储到集合中
            depts.add((Dept)o);
            System.out.println(depts.toString());
            return true;
        }
        return false;
 }

6、finalize()

当一个对象没有任何引用执行它的时候,它就会满足垃圾回收机制的要求,被垃圾回收机制回收,会自动调用finalize()方法。不是开发人员自己主动调用的,是由虚拟机自己调用的

public class Test_04 {
    //重写这个方法
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("-----正在回收对象-----");
    }

    public static void main(String[] args) {
        Test_04 test_04;//创建一个对象但是没有对这个对象进行实例化 这是一个引用
        for(int i = 1; i <= 1000000000; i++) {
            //不断创建新的对象
            //每创建一个对象,前一个对象,就没有引用执行它
            //之前创建的对象一直都没有使用,直接被后面的对象给覆盖了
            //没有引用指向这个对象的时候,就已经满足了垃圾回收机制的条件
            //当java虚拟机中的内存已经快要存满的时候,后面的对象还在不断的创建,
            //为了让后面的元素继续执行,java虚拟就会回收掉之前创建的对象
            //一旦某一个对象被回收了,那么就会自动的调用finalize这个方法
            test_04 = new Test_04();//地址赋值
        }
    }
}

7、clone()方法

只要是实现了Cloneable()这个接口的类就可以调用这个方法,这个方法会产生一个新的对象
这个接口的实现是调用方法的前提,否则会抛出异常
protected Object clone() throws CloneNotSupportedException

public class CloneNotSupportedException
extends 异常抛出,表明该clone类方法Object被称为克隆对象,但该对象的类无法实现Cloneable接口。 
覆盖clone方法的应用程序也可以抛出此异常以指示对象无法或不应被克隆。

//只要实现这个接口就可以调用clone这个方法
public class Sheep extends Object implements Cloneable{
    private String name;

    public Sheep(String name) {
        this.name = name;
    }

    public static void main(String args[]) throws CloneNotSupportedException {
        //创建对象
        Sheep s1 = new Sheep("喜羊羊");
        //当你调用一个方法的时候,如果这个方法本身已经抛出了异常,那么你调用它的时候也要抛出异常
        Object obj = s1.clone();//新的羊的对象
        //如果你想要知道两个对象的地址是否相同就不要toString输入内容,输出的就是地址
        System.out.println(s1);//com.softeem.dto.Sheep@4554617c
        System.out.println(obj);//com.softeem.dto.Sheep@74a14482

        //==:比较两个类的地址是否相同
        //equals:首先比较两个字符串的内容是否相同
        //如果不是字符串,是两个对象,那么重写equals底层会先判断两个对象是不是相同的
        //然后再判断两个对象的类型是否相同,最后再判断对象的属性内容是否相同
        //在判断的过程中,我们发现equals底层判断两个对象是否相同的时候使用的是==
        System.out.println(obj == s1);//false
        System.out.println("s1 = " + s1.name);
        
        Sheep s4 = (Sheep) obj;
        System.out.println("obj = " + s4.name);

        Sheep s2 = new Sheep("沸羊羊");
        Sheep s3 = s2;
        System.out.println(s2);//com.softeem.dto.Sheep@1540e19d
        System.out.println(s3);//com.softeem.dto.Sheep@1540e19d
    }
}

day_13

一、基本数据类型的封装类型

1、在java中8种基本数据类型都有一个与之相对应的封装类,因为基本数据类型不能调用方法和属性。其实基本数据类型你可以将其理解为一个名称,其具体的功能和特点都是封装在封装类型中的。
我们可以通过封装类型去访问数据类型的属性和方法
2、            基本数据类型                    封装类型
                byte                        Byte
                short                        Short
                int                            Integer
                long                        Long
                float                        Float
                double                        Double
                char                        Character
                boolean                        Boolean

二、String <------->基本数据类型

1、String 转基本数据类型

static修饰的方法,可以并且建议使用类名进行直接调用
public static int parseInt(String s) throws NumberFormatException
除了char类型,.其余的数据类型都满足
基本数据类型 自定义变量名 = 封装类型.parseXXXX("值");
比如:
    static byte parseByte(String s) 
    将字符串参数解析为带符号的十进制 byte  
    
    static long parseLong(String s) 
    将字符串参数解析为带符号的十进制 long 。 
    
    static double parseDouble(String s) 
    返回一个新 double初始化为指定的代表的值 String ,如通过执行 valueOf类的方法 Double 。  
    
    static boolean parseBoolean(String s) 
    将字符串参数解析为布尔值。

2、基本数据类型转String类型的方法

        1、直接使用""进行连接 34 + "" ----> 变为一个字符串
        2、调用String类中的重载方法valueOf()
            //其余的方法请参考String类的api中,关于valueOf的使用
            static String valueOf(int i) 
            返回 int参数的字符串 int形式。 
    
            static String valueOf(char[] data) 
            返回 char数组参数的字符串 char形式。
    
        3、调用对应的基本数据类型中的toString方法,一般格式是:
            static String toString(XXX 变量名)
            static String toString(int i) 
            返回一个 String指定整数的 String对象。

三、Integer类

1、静态常量

static int BYTES 
    用于表示二进制补码二进制形式的 int值的字节数。  
static int MAX_VALUE 
    一个持有最大值一个 int可以有2 31 -1。  
static int MIN_VALUE 
    的常量保持的最小值的 int可以具有,-2 31。  
static int SIZE 
    用于表示二进制补码二进制形式的 int值的位数。  
static 类<Integer> TYPE 
    类原始类型 int的 类实例。 

public static void main(String[] args) {
        //使用静态常量进行获取
        int max = Integer.MAX_VALUE;
        int min = Integer.MIN_VALUE;
        int size = Integer.SIZE;//32位
        int bytes = Integer.BYTES;//4个字节
        //获取基本数据类型是哪一个
        System.out.println(Integer.TYPE);
    }

2、构造方法

构造方法
Integer(int value) 
    构造一个新分配的 Integer对象,该对象表示指定的 int值。  
Integer(String s) 
    构造一个新分配 Integer对象,表示 int由指示值 String参数。 
只能写能够转换为int类型的字符串,如果不是int类型NumberFormatException

3、静态方法

//将i转换为2进制,然后统计二进制数中1的个数
        int count = Integer.bitCount(11);
        System.out.println("11的二进制数中1的个数:" + count);//11的二进制数中1的个数:3

        //十进制转二进制
        String s1 = Integer.toBinaryString(11);
        System.out.println("11的二进制数为:" + s1);//11的二进制数为:1011
        //使用for循环将10进制转换成2进制

        //十进制转十六进制
        System.out.println(Integer.toHexString(20));//14

        //十进制转八进制
        System.out.println(Integer.toOctalString(20));//24

        //将前面字符串的元素以后面第二个参数radix的进制进行转换
        Integer x = Integer.valueOf("24",8);
        System.out.println(x);

        //将两个数进行比较之后将最大值拿出来
        int m = Integer.max(20,50);
        System.out.println(m);

4、非静态方法

/**
 * 非静态方法
 */
public class Demo_05 {
    public static void main(String[] args) {
        Integer m1 = new Integer(20);
        Integer m2 = new Integer(20);
        int m3 = m1.compareTo(m2);
        System.out.println("m3 = " + m3);

        //思考一个问题?
        //Integer是否继承于Object?
        //Integer是否重写了Object中的toString方法
        Integer n1 = new Integer(30);
        System.out.println(n1.toString());

        Integer n2 = new Integer(40);
        System.out.println(n1 == n2);

        //覆盖了Object中的equals方法,比较的是两个对象的值
        boolean flag = n1.equals(n2);
        System.out.println(flag);
        
        Object o = new Object();
        o.toString();
    }

5、int <--------> Integer类型之间的转换

1、int类型转Integer类型
        //int转换成Integer方法

        //1、通过构造方法
        int a = 10;
        Integer x = new Integer(a);
        Integer y = new Integer(a + "");

        //2、通过Integer类中的静态方法
        //  参数是int类型返回值是Integer类型
        //  使用valueOf()
        Integer z = Integer.valueOf(a);
        //底层自动装箱操作的时候会自动调用这个方法
2、Integer类型转int类型
        //int转换成Integer方法

        //1、通过构造方法
        int a = 10;
        Integer x = new Integer(a);
        Integer y = new Integer(a + "");

        //2、通过Integer类中的静态方法
        //  参数是int类型返回值是Integer类型
        //  使用valueOf()
        Integer z = Integer.valueOf(a);
        //底层自动装箱操作的时候会自动调用这个方法

6、自动装箱和自动拆箱

自动装箱    int    -----> valueOf(int n) -----> Integer
自动拆箱    Integer ----> intValue()     -----> int

①自动装箱

Integer x = 10;   在java的源文件中
Integer localInteger = Integer.valueOf(10); //自动将int转换成为Integer,自动装箱

②自动拆箱

Integer x = 4;//默认的4是int类型的值而不是Integer
x = x + 5;


Integer localInteger = Integer.valueOf(4);//将int类型转换成Integer类型
//在进行运算的时候,我们需要拿int类型进行运算
//所以先将Integer类型转换为int类型使用了intValue()方法
//然后和5进行运算,运算完成之后的结果因为我们还是将值赋值给了x
//x是Integer,还是需要将最终的结果转换成为Integer
localInteger = Integer.valueOf(localInteger.intValue() + 5);

当你定义的整型数据在-128 ~ 127之间的时候,这个数据没有进入到内存中,在缓存中进行处理,在缓存中,两个变量指向了相同的地址,并没有新建对象,没有产生新的地址.
当不在这个范围内的时候,底层重新新建了变量.新建之后就在内存中开辟了新的空间,产生了新的地址.
==比较两个元素的内存地址是否相同,如果比较的是基本数据类型的元素,那么比较的就是值

day_14

一、String类型创建对象的过程

public static void main(String[] args) {
        String s1 = "abc";//将对象信息放在常量池里面
        String s2 = "abc";//当第二个字符串创建的时候首先到常量池中去找,如果没有的话就创建,有的话直接引用地址
        String s3 = new String("abc");//在堆中直接新建一个地址存储"abc"信息
        String s4 = new String("abc");
        String s5 = s3.intern();//先去常量池里面进行寻找,有的话就返回,没有的话就创建

        //使用+进行连接的时候怎么处理?
        //m1和m2是同一个地址
        //m2是纯字符串常量进行累加,只会在String常量池中进行寻找
        String m1 = "ab";
        String m2 = "a" + "b";
        System.out.println(m2 == m1);//true


        //如果像x2中这样,表达式中包含了一个变量,不仅会去常量池中进行寻找
        //而且还会在堆中新建一个新的字符串,因为字符串x1虽然放在了x2中但是,
        //字符串String是不可以改变的,一旦改变就会产生新的地址
        String x1 = "a";
        String x2 = x1 + "b";
        System.out.println(x2 == m2);//false


        //String类型的p就是一个常量了,是常量就会放在常量池中,纯字符串常量累加,只会在常量池中进行搜索
        final String p = "a";
        String q = p + "b";
        System.out.println(q == m2);//true

        String k = "ab";
        //链式调用,链式编程
        //只会去常量池中进行检查搜索
        String s = new String("ab").intern();
        System.out.println(k == s);//true

二、字符串(String,StringBuffer,StringBuilder)

只细讲StringBuffer,后面用的相对比较多
String:字符串常量
    String类型不可以改变的,每次改变的时候都会产生新的对象,然后将调用信息的索引指向最新的元素。性能相对来说比较差,经常要改变内容的话,不建议使用String
StringBuffer:字符串变量(线程安全,适用于多线程的情况下)
    字符串变量,对它进行操作的时候,不会产生新的变量,直接对原来的元素进行修改,性能比较好
StringBuilder:字符串变量(线程不安全,适用于单线程情况下)
    不能保证线程的安全性,所以在操作的时候速度最快,性能最好,但是安全性比较低.如果是单线程可以使用StringBuilder
性能上排序:
    StringBuilder > StringBuffer > String
总的来说:
    String:适用于少量的字符串操作
    StringBuffer:适用于多线程下在字符串缓冲区里面进行大量的字符串操作
    StringBuilder:适用于单线程下,在字符串缓冲区里面进行字符串的操作

三、StringBuffer类

在学习String类的时候String类是不可以改变的,StringBuffer类的API中说字符串缓冲区支持可变的字符串,什么是字符串缓冲区?
    字符串缓冲区:就像一个String类型的变量,但是长度可以改变,不会产生新的地址,API中也提供了一些方法来对这些信息进行更改
       你可以将其理解为之前的ArrayList与数组的关系,数组的长度是已经确定的,但是ArrayList可以根据添加元素的个数来进行自动的扩容操作

1、构造函数

StringBuffer() 
    构造一个没有字符的字符串缓冲区,初始容量为16个字符。  
StringBuffer(CharSequence seq) 
    构造一个包含与指定的相同字符的字符串缓冲区 CharSequence 。  
StringBuffer(int capacity) 
    构造一个没有字符的字符串缓冲区和指定的初始容量。  
StringBuffer(String str) 
    构造一个初始化为指定字符串内容的字符串缓冲区

四、多态

1、多态的概念

多态:多种状态
在面向对象的语言中,接口的不同的实现方式就是多态
多态性:
    允许你将你的父类引用设置成为一个或者更多的子类对象

2、多态的格式

1>普通类中
    父类 自定义变量名 = new 子类();
    比如:
        class F{}
        class Z extends F{}
        F f = new Z();
2、抽象类中 
    抽象类 自定义变量名 = new 抽象类的子类();
    比如:
        public abstract class Hero {

        public abstract void normalAttack();//普通攻击
        }
        public class YaSuo extends Hero{
            //一个类继承于一个抽象类,就必须实现抽象类中的抽象方法
            @Override
                public void normalAttack() {
                System.out.println("闪现");
            }
            public void m(){
                System.out.println("功击");
                }
        }
            public abstract class Hero {
                public abstract void normalAttack();//普通攻击
            }
        public class HeroTest {
            public static void main(String[] args) {
                //抽象类不可以创建对象
                //我们只能通过子类进行创建对象并且完成方法的重写和调用
                Hero hero = new YaSuo();
                hero.normalAttack();
            }
        }
3、接口的多态的格式
    接口名 自定义变量名 = new 实现类名称();
    比如:
        public interface Skill {
            public void useSkill();//使用技能的抽象方法
            }            
        public class ChengJie implements Skill{
            @Override
            public void useSkill() {
                System.out.println("使用惩戒的技能");
            }
        }
        public class SkillTest {
            public static void main(String[] args) {
            //接口不能创建对象,我们就创建实现类的对象
            Skill skill = new ChengJie();
            }
        }

4、引用数据类型的转换

多态的前提:
    类和类之间存在继承关系(直接或者间接继承都可以)
    类和接口之间存在实现关系
类型转的时候:
    向上转型(自动类型转换,小的转大的)
    向下转型(强制类型转换,大的转小的,存在风险!!!比如数据丢失)
向上转型
    当有子类对象赋值给一个父类的引用的时候,就是向上转型
    父类类型    自定义变量名 = new 子类类型();
向下转型
    重要的要求:只有一个已经向上转型的子类对象才能向下转型(为了防止转型的时候出现异常:ClassCastException,为了防止这种事情的出现,我们一般要使用instanceof关键字,先来判断这个对象是否是可以转型子类对象)
            F f1 = new S();
            if(f1 instanceof S){
                S s = (s)f1;
            }

day_15

一、多态

1、多态的好处和弊端

父类的引用指向子类对象时F f = new S();就会发生向上转型,即把子类类型的对象转换成父类类型,向上转型的好处是隐藏了子类类型,提高了代码的可扩展性。
但向上转型也有弊端,只能使用父类共性的内容,无法使用子类特有的功能,功能有所限制。
//描述动物类,抽取共性的方法
abstract class Animal{
    abstract void eat();
}
//描述狗类,继承动物类,重写eat方法,增加一个看门lookHome的方法
class Dog extends Animal{
    void eat(){
        System.out.println("吃骨头");
    }
    
    void lookHome(){
        System.out.println("看家");
    }
}
//描述猫的类
class Cat extends Animal{
    void eat(){
        System.out.println("吃鱼");
    }
    
    void catchMouse(){
        System.out.println("抓老鼠");
    }
}

public class Test{
    public static void main(String[] args) {
        Animal a = new Dog();//多态的形式,创建狗类的对象
        a.eat();//调用对象中的方法的时候只能调用重写的
        //a.lookHome();子类特有的方法,需要进行向下转型,不能直接使用
        
        //为了使用狗类中的看门的方法,需要进行下次转型
        //向下转型的时候可能会出现:ClassCastException异常
        //需要在转换之前,判断所属的类型
        if(a instanceof Dog){
            //相同就会返回为true.就可以直接进行转换
            //不相同就不可以使用
        }
        //向下转型
        Dog d = (Dog)a;
        d.lookHome();
    }
}

什么时候向上转型?
    当不需要面对子类类型的时候,通过提供扩展性,或者使用父类的功能就能完成响应的操作的时候,就可以使用向上转型。
什么时候向下转型?
    当需要使用过子类特有的功能的时候,就需要向下转型
    好处:可以使用子类特有的功能
    弊端:需要面对子类对象的时候,可能会出现异常
    
多态的优势:
    1、降低了类之间的耦合度
    2、面向抽象编程
    3、提高了扩展性

封装:把独享的属性与方法的描述细节隐藏起来,仅仅对外提供调用这个功能的访问的方式
继承:子类会自动拥有父类的所有可以继承的属性和方法。非私有的
多态:配合继承于方法重写提高代码的可复用性和可扩展性,如果没有方法重写,多态就没有意义

多态里面的成员变量:
当父子类中出现了同名的变量的时候,多态调用变量的时候:
    简单记:编译和运行都参考的是等号的左边
多态里面的成员方法:
    编译时期:参考引用变量所属的类,如果没有类能够调用的方法,那么就编译失败
    运行时期:参考引用变量所指向的对象所属的类,并运行对象所属的类中的成员方法
    简单记:编译的看左边,运行的时候看右边
          编译的时候要到接口或者抽象类或者父类中去看,有没有你要调用的这个方法,如果有我们就直接执行子类中重写的这个方法,然后将内容进行处理。
          编译失败的情况就是,你调用一个方法,这个方法是属于子类或者实现类自己的,那么现在在等号的左边就找不到这个方法,找不到就会出现编译失败.

二、匿名对象

1、匿名对象的概念

匿名对象是指创建的时候只有创建对象的语句,没有把对象的地址给到某一个变量
public class Test {
    public static void main(String[] args) {
        People people = new People();
        people.setName("张三疯");
        people.setAge(100);
        People people1 = new People("张无忌",20);
        System.out.println(people.toString());
        System.out.println(people1.toString());
        people.eat();
        people1.eat();

        //创建一个匿名对象
        //只能使用一次,使用完成之后就没有了
        new People("宋青书",22).eat();
        System.out.println(new People("韦一笑",50).toString());
        System.out.println(new People("谢逊",60).getName());

        ArrayList<People> list = new ArrayList<People>();
        list.add(people);
        list.add(people1);
        list.add(new People("周芷若",20));
    }
}

2、匿名对象的特点

1、创建匿名对象直接使用没有对象名
    new People().eat();//eat方法被一个没有名字的对象调用了
2、匿名对象在没有指定其引用变量的时候只能使用使用一次
  如果想要再次使用这个方法,必须重新创建一个匿名对象
3、匿名对象可以作为方法接收的参数,方法的返回值使用
    public class Test {
    public static void main(String[] args) {
        People people = new People();
        people.setName("张三疯");
        people.setAge(100);
        People people1 = new People("张无忌",20);
        System.out.println(people.toString());
        System.out.println(people1.toString());
        people.eat();
        people1.eat();

        //创建一个匿名对象
        new People("宋青书",22).eat();
        System.out.println(new People("韦一笑",50).toString());
        System.out.println(new People("谢逊",60).getName());

        ArrayList<People> list = new ArrayList<People>();
        list.add(people);
        list.add(people1);
        list.add(new People("周芷若",20));
        }
    }
4、当对象使用完毕之后就消失,无法再次调用,内存中也没有了

三、内部类

1、内部类概念

什么是内部类?
    将类写在其他类的内部,可以写在其他类的成员的位置,也可以写在局部的位置,这时写在其他类内部的类称为内部类。其他类叫外部类。
什么时候使用内部类?
    在描述事物的时候,如果一个事务内部还包含了其他可能包含的事物,比如:在描述汽车的时候,汽车内部还包含了发动机,这时发动机类就可以作为汽车类的内部类。
    
内部类的分类:
    成员内部类 局部内部类
    我们定义内部类的时候,就是一个正常的定义类的过程,同样包含了修饰符,继承以及实现关系。在内部类中可以直接访问外部类中的所有成员。

2、成员内部类(静态内部类 和 非静态内部类)

成员内部类:定义在外部类中成员的位置,与类中成员变量是相似的,可以通过外部类对象进行访问
<1>定义的格式
    public class 外部类{
        public class 内部类{//非静态内部类
            //其他代码
        }
    }
<2>创建成员内部类对象
    外部类名.内部类名 变量名 = new 外部类名().new 内部类名();

<3>成员内部类代码
        public class Body {//外部类
            private boolean life = true;//生命状态

            public class Heart{//内部类 心脏  (非静态内部类)
                public void jump(){
                    System.out.println("心扑通扑通的跳");
                    System.out.println("生命状态" + life);//内部类可以直接访问外部类中的成员
                }
            }

            public void eat(){
                System.out.println("身体需要吃来保证生命状态");
            }

            public static void main(String[] args) {
                //访问内部类
                Body.Heart bh = new Body().new Heart();
                //调用内部类中的方法
                bh.jump();
            }
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值