Java寒假作业——问答题

Java寒假作业

 

一、问答题(76-100题)

76 sleep() 和 wait() 有什么区别?

1)相同点
sleep()和wait()都可以暂停线程的执行。
2)不同点
所在类不同
sleep()是Thread类的静态方法。
wait()是Object类的方法。

锁释放不同
sleep()是不释放锁的。
wait()是释放锁的。

用途不同
sleep()常用于一定时间内暂停线程执行。
wait()常用于线程间交互和通信。

用法不同
sleep()方法睡眠指定时间之后,线程会自动苏醒。
wait()方法被调用后,可以通过notify()或notifyAll()来唤醒wait的线程。
原文链接:https://blog.csdn.net/qiuchaoxi/article/details/79837568

77 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

当一个线程进行一个对象的synchronized方法之后,其他线程完全有可能再次进入该对象的其他方法。不过要分几种情况来看:

1)如果其他方法没有使用synchronized关键字修饰,则可以进入。

2)如果当前线程进入的synchronized方法是static方法,其他线程可以进入其他synchronized修饰的非静态方法;如果当前线程进入的synchronized方法是非static方法,其他线程可以进入其他synchronized修饰的静态方法。

3)如果两个方法都是静态方法、或者都是非静态方法,并且都使用了synchronized修饰,但只要在该方法内部调用了同步监视器的wait(),则其他线程依然可以进入其他使用synchronized方法修饰的方法。

4)如果两个方法都是静态方法、或者都是非静态方法,并且都使用了synchronized修饰,而且没有在该方法内部调用了同步监视器的wait(),则其他线程不能进入其他使用synchronized方法修饰的方法。

78 线程的基本状态以及状态之间的关系是什么?

在这里插入图片描述

一个线程是进程的一个顺序执行流,

同类的多个线程共享一块内存空间和一组系统资源,线程本身有一个供程序执行时的堆栈。线程在切换时负荷小,因此,线程也被称为轻负担进程,一个进程可以包含多个线程。

1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。
该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。
直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
①等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,
则JVM会把该线程放入锁池中。
③其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,
JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止
或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
原文链接:https://blog.csdn.net/weixin_52953111/article/details/110202553

79 List、Map、Set三个接口,存取元素时,各有什么特点?

存放时:
1、List存放元素可以重复,存放元素是有序的(按插入顺序)。

ArrayList、vector(线程安全),根据特定的索引来存放元素;
LinkedList,是队列的实现,元素总是存于尾部。
方法:add(E e) :将指定的元素添加到此列表的尾部。add(int index, E element) :将指定的元素插入此列表中的指定位置。offer(E e) :将指定元素添加到此列表的末尾(最后一个元素)等。

2、Set 存放元素不可重复。

HashSet存放元素是无序的,根据元素hashcode存放元素;
LinkedHashSet存放元素是有序的,根据元素hashcode存放元素,但在HashSet的基础上同时使用链表,保存插入顺序;
TreeSet存放元素是有序的,根据指定数据内容存放,利用红黑树进行排序。
方法:add(E e):如果此 set 中尚未包含指定元素,则添加指定元素等。
3、Map存放键值对,键不可重复,值可重复。

HashMap、HashTable(线程安全)存放元素无序,根据键的hashcode存放键值对;
LinkedHashMap存放键值对有序,根据键的hashcode存放键值对,但在HashMap的基础上同时使用链表,保存插入顺序;
TreeMap存放键值对是有序的,根据键的指定数据内容存放,利用红黑树进行排序。
方法:put(K key, V value) :在此映射中关联指定值与指定键等。

取出时:
1、List取出元素:
(1)get(index)、poll()、peek()等方法;
(2)for循环;
(3)foreach循环;
(4)Iterator迭代器迭代。
2、Set取出元素:
(1)foreach循环;
(2)Iterator迭代器迭代。
3、Map取出元素:
(1)get(key)方法;
(2)entrySet()获得Set<Map.Entry<K,V>>,然后进行Set集合迭代;
(3)keySet()获得Set,然后结合get(key)方法,进行Set集合迭代;
(4).foreach(new BiConsumer(){}),进行迭代。
原文链接:https://blog.csdn.net/Lanerxx/article/details/120430536

80 两个对象值相同(x.equals(y) == true),但却可有不同的hashcode,这句话对不对?

不对,若是两个对象x和y知足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:
1)若是两个对象相同(equals方法返回true),那么它们的hashCode值必定要相同;
2)若是两个对象的hashCode相同,它们并不必定相同。

81 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化(将对象转换成二进制)。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间,序列化是为了解决在对对象流进行读写操作时所引发的问题。把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

原文链接:https://blog.csdn.net/m0_37450089/article/details/78542825

82 什么是构造函数?

构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载

1.构造函数的命名必须和类名完全相同。在java中普通函数可以和构造函数同名,但是必须带有返回值;

2.构造函数的功能主要用于在类的对象创建时定义初始化的状态。它没有返回值,也不能用void来修饰。这就保证了它不仅什么也不用自动返回,而且根本不能有任何选择。而其他方法都有返回值,即使是void返回值。尽管方法体本身不会自动返回什么,但仍然可以让它返回一些东西,而这些东西可能是不安全的;

3.构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用;而一般的方法是在程序执行到它的时候被调用的;

4.当定义一个类的时候,通常情况下都会显示该类的构造函数,并在函数中指定初始化的工作也可省略,不过Java编译器会提供一个默认的构造函数.此默认构造函数是不带参数的。而一般的方法不存在这一特点;

5.构造函数有回滚的效果,构造函数抛出异常时,构造的是一个不完整对象,会回滚,将此不完整对象的成员释放(c++)

6.当一个类只定义了私有的构造函数,将无法通过new关键字来创建其对象,当一个类没有定义任何构造函数,C#编译器会为其自动生成一个默认的无参的构造函数。

7.在Python中构造函数必须通过重写__init__方法实现

83 内部类有哪些?

内部类可以分为四种: 成员内部类、局部内部类、匿名内部类和静态内部类 。

在java语言中,可以把一个类定义到另外一个类的内部,在类里面的这个类就叫内部类,外面的类就叫外部类。在这情况下,这个内部类可以看做外部类的一个成员。还有一种类被称为顶层类,指的是类定义代码不嵌套在其他类定义中的类。

静态内部类是指被声明为static的内部类,他可以不依赖内部类而实例,而通常的内部类需要实例化外部类,从而实例化。静态内部类不可以有与外部类有相同的类名。不能访问外部类的普通成员变量,但是可以访问静态成员变量和静态方法(包括私有类型)
一个 静态内部类去掉static 就是成员内部类,他可以自由的引用外部类的属性和方法,无论是静态还是非静态。但是不可以有静态属性和方法、

局部内部类 就是定义在一个代码块的内类,他的作用范围是所在代码块,是内部类中最少使用的一类型。局部内部类跟局部变量一样,不能被public ,protected,private以及static修饰,只能访问方法中定义final类型的局部变量。

匿名内部类是一种没有类名的内部类,不使用class,extends,implements,没有构造函数,他必须继承其他类或实现其他接口。匿名内部类的好处是使代码更加简洁,紧凑,但是带来的问题是易读性下降。他一般应用于GUI编程来实现时间处理等 。
在使用匿名内部类时,需要牢记以下几个原则。
1》内部类没有构造方法
2》匿名内部类不能定义静态成员,方法和类
3》匿名内部类不能是public protected private static
4》只能创建匿名内部类的一个实例
5》一个匿名内部类可以在new后面,这个匿名类必须继承一个父类或实现接口
6》因为匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效

84 instanceof有什么用?

instanceof是Java语言中的一个二元运算符,它的作用是:判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例,即它左边的对象是否是它右边的类的实例,该运算符返回boolean类型的数据。

85 什么是GC?

GC是垃圾收集的意思(Garbage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

所以,Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。

对于Java程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。

通过这种方式确定哪些对象是可达的,哪些对象是;不可达的。当GC确定一些对象为不可达时,GC就有责任回收这些内存空间。

但是,为了保证GC能够在不同平台实现的问题,Java规范对GC的很多行为都没有进行严格的规定。

例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。

因此,不同的JVM的实现者往往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。本文研究了几个与GC工作相关的问题,努力减少这种不确定性给Java程序带来的负面影响。
原文链接:https://blog.csdn.net/weixin_30131185/article/details/114872388

86 Java中是否存在内存泄漏的问题,并举例说明?

会。java导致内存泄露的原因很明确:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景。

1.集合类,集合类仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。这一点其实也不明确,这个集合类如果仅仅是局部变量,根本不会造成内存泄露,在方法栈退出后就没有引用了会被jvm正常回收。而如果这个集合类是全局性的变量(比如类中的静态属性,全局性的map等即有静态引用或final一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减,因此提供这样的删除机制或者定期清除策略非常必要。

2.单例模式。不正确使用单例模式是引起内存泄露的一个常见问题,单例对象在被初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部对象的引用,那么这个外部对象将不能被jvm正常回收,导致内存泄露
原文链接:https://blog.csdn.net/weixin_39735509/article/details/114654667

87 Java中的堆内存与栈内存有什么区别?

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存。

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。
原文链接:https://blog.csdn.net/weixin_29895109/article/details/114179680

栈:是运行时单位,代表逻辑,内含基本数据类型和堆中的对象引用,所在区域连续,没有碎片;

堆:是存储单元,代表着数据,可以被多个栈共享,所在区域不连续,有碎片;

区别:

1、功能不同:栈内存用来存储局部变量和方法调用,而堆内存用存储Java中的对象;无论是成员变量、局部变量、还是类变量他们指向的对象都存储在堆内存中;

2、共享性不同:栈是线程私有,而堆是线程共享;

3、异常错误不同:当内存不足时;栈抛出的是StackOverFlowError异常,而堆抛出的是OutOfMemoryError;

4、空间大小不同:堆空间大小远远大于栈的内存空间。
原文链接:https://blog.csdn.net/qq_44944221/article/details/126692973

88 什么是栈内存溢出?

栈内存溢出:
对于一台服务器而言,每一个用户请求,都会产生一个线程来处理这个请求,每一个线程对应着一个栈,栈会分配内存,此时如果请求过多,这时候内存不够了,就会发生栈内存溢出。

栈溢出:
栈溢出是指不断的调用方法,不断的压栈,最终超出了栈允许的栈深度,就会发生栈溢出,比如递归操作没有终止,死循环。

帮助记忆:
可以把内存比作是一个大箱子,栈是一个小箱子,栈溢出是指小箱子装不下了;而栈内存溢出是大箱子在也装不下小箱子了。
原文链接:https://blog.csdn.net/wshlchl/article/details/106521654

栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。

89 什么是堆内存溢出?

堆里有垃圾回收机制。
当你这个对象不被使用了,它就可以成为所谓垃圾被回收掉,也就是它占用的内存会被释放掉。
这样怎么还可能出现这个堆内存耗尽呢?

哎,那么大家可以这样想啊。
那我们对象。可以当做垃圾被回收的一个条件是这个对象没人在使用它。
但是如果我不断的产生对象,而产生的这些新对象,仍然有人在使用它们,是不是就意味着这些对象不能作为垃圾?这样的对象达到一定的数量,就会导致你的堆内存被耗尽啊,也就是咱说的这个堆内存溢出。
原文链接:https://blog.csdn.net/tgbyhn31/article/details/125361145

90 什么是整数溢出?

由于整数在内存里面保存在一个固定长度的空间内,它能存储的最大值和最小值是固定的,如果我们尝试去存储一个数,而这个数又大于这个固定的最大值时,就会导致整数溢出。

91 同步和异步有什么区别?

同步:所有的操作都做完,才返回给用户。这样用户在线等待的时间太长,给用户一种卡死了的感觉(就是系统迁移中,点击了迁移,界面就不动了,但是程序还在执行,卡死了的感觉)。这种情况下,用户不能关闭界面,如果关闭了,即迁移程序就中断了。

异步:将用户请求放入消息队列,并反馈给用户,系统迁移程序已经启动,你可以关闭浏览器了。然后程序再慢慢地去写入数据库去。这就是异步。但是用户没有卡死的感觉,会告诉你,你的请求系统已经响应了。你可以关闭界面了。
原文链接:https://blog.csdn.net/weixin_42347778/article/details/114039208

92 终止线程的方法有哪些?

1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。

3.  使用interrupt方法中断线程。

原文链接:终止线程的三种方法 - 走看看

93 什么是单例模式?

单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)

通常单例模式在Java语言中,有两种构建方式:

  • 懒汉式—线程不安全:最基础的实现方式,线程上下文单例,不需要共享给所有线程,也不需要加synchronize之类的锁,以提高性能。

  • 懒汉式—线程安全:加上synchronize之类保证线程安全的基础上的懒汉模式,相对性能很低,大部分时间并不需要同步

  • 饿汉方式。指全局的单例实例在类装载时构建。 [2] 

  • 双检锁式。在懒汉式基础上利用synchronize关键字和volatile关键字确保第一次创建时没有线程间竞争而产生多个实例,仅第一次创建时同步,性能相对较高

  • 登记式。作为创建类的全局属性存在,创建类被装载时创建

  • 枚举。java中枚举类本身也是一种单例模式

94 什么是工厂模式?

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

原文 + 参考链接:什么是工厂模式?_Hell_potato777的博客-CSDN博客_什么是工厂模式?

95 什么是适配器模式?

在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的。一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

共有两类适配器模式:

对象适配器模式:

-- 在这种适配器模式中,适配器容纳一个它包裹的类的实例。在这种情况下,适配器调用被包裹对象的物理实体

类适配器模式:

-- 这种适配器模式下,适配器继承自已实现的类(一般多重继承)。

应用实例: 1、美国电器 110V,中国 220V,就要有一个适配器将 110V 转化为 220V。 2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,则要将以前系统的 Enumeration 接口转化为 Iterator 接口,这时就需要适配器模式。 3、在 LINUX 上运行 WINDOWS 程序。 4、JAVA 中的 jdbc。

原文链接:https://blog.csdn.net/Hell_potato777/article/details/126911120

96 什么是观察者模式?

观察者模式又叫发布者订阅者模式,它定义了一对多的关系,让多个观察者对象同时监听某一个主体对象,这个主体对象发生变化时就会通知所有的观察者对象,使得他们能够自己更新自己
如:你订阅游戏主播,当主播开播的时候他就会给你推送开播消息;
使用观察者模式的好处:
1.1支持简单的广播通信,自动通知所有已订阅的对象。
1.2页面载入后目标元素容易和观察者者存在一种动态关联,增加了灵活性。
1.3目标对象与观察者之间的抽象耦合关系能够单独扩展及运用。
原文链接:https://blog.csdn.net/qq_58982380/article/details/123711184

97 什么是代理模式?

代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式

所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网上连接、存储器中的大对象、文件或其它昂贵或无法复制的资源。

代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

98 什么是NIO?

NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。

NIO和IO最大的区别是数据打包和传输方式。IO是以的方式处理数据,而NIO是以的方式处理数据。

面向流的IO一次一个字节的处理数据,一个输入流产生一个字节,一个输出流就消费一个字节。为流式数据创建过滤器就变得非常容易,链接几个过滤器,以便对数据进行处理非常方便而简单,但是面向流的IO通常处理的很慢。

面向块的IO系统以块的形式处理数据。每一个操作都在一步中产生或消费一个数据块。按块要比按流快的多,但面向块的IO缺少了面向流IO所具有的有雅兴和简单性。

原文链接:什么是NIO_学习使我可乐的博客-CSDN博客_什么是nio

99 迭代器的实现原理是什么?

迭代器是我们常用的一种遍历集合的方法,每个集合通过实现Iterator<T>这个接口来达到遍历集合的目的。

迭代器遍历集合的样例,最关键的两个方法就是:

        iterator.hasNxet();//判断是否有下一个元素

        iterator.Next();//获取下一个元素

通过while循环来判断集合是否有下一个元素,如果有就接收,如果没有就结束。我们要搞清楚迭代器的实现原理,最关键的就是要明白它是如何来判断是否有下一个元素。

在ArrayList类下有一个成员内部类Itr,它实现了Iterator接口,内部类中定义了一个cuesor(游标)成员变量,通过hasNext方法来判断游标后是否有下一个元素,如果有就把元素添加到Object数组中(cursor++),然后继续下一个判断;如果没有就结束 。
原文链接:https://blog.csdn.net/LX_1234567/article/details/125591410

100 垃圾回收有哪些算法并详细阐述原理

(1)引用计数算法
比较古老的回收算法。原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数。垃圾回收时,只用收集计数为0的对象。此算法最致命的是无法处理循环引用的问题。

(2)复制算法
从根集合节点进行扫描,标记出所有的存活对象,并将这些存活的对象复制到一块儿新的内存(图中下边的那一块儿内存)上去,之后将原来的那一块儿内存(图中上边的那一块儿内存)全部回收掉

(3)标记清除算法

标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。

在标记阶段首先通过根节点(GC Roots),标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

(4)标记整理(压缩)算法

复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。

这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。

标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。

首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

(5)分代收集算法
分代收集算法就是目前虚拟机使用的回收算法,

它解决了标记整理不适用与新生代的问题,将内存分为各个年代。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),在堆区之外还有一个代就是永久代(元空间)(Permanet Generation)。

在不同年代使用不同的算法,从而使用最合适的算法,新生代存活率低,可以使用复制算法。而老年代对象存活率高,没有额外空间对它进行分配担保,所以只能使用标记清除或者标记整理算法。
原文 + 参考链接:https://blog.csdn.net/m0_50370837/article/details/119851042

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值