测试题13-17汇总(答案解析)

文章目录

day13测试

1. SpringMVC的执行流程
Dispatcher->HandlerMapping->HanderAdapter->Handler->ViewResolver->View
2. Integer a= 128 与 Integer b = 128相等吗?

不相等,两个不同的对象

3. Mybatis的一级、二级缓存
  1. 一级缓存
    Mybatis的一级缓存是指Session缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。
    也就是在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后是直接去缓存中取。
    当执行SQL查询中间发生了增删改的操作,MyBatis会把SqlSession的缓存清空。
    一级缓存的范围有SESSION和STATEMENT两种,默认是SESSION,如果不想使用一级缓存,可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper中的语句后都会将一级缓存清除。
  2. 二级缓存
    Mybatis的二级缓存是指mapper映射文件。二级缓存的作用域是同一个namespace下的mapper映射文件内容,多个SqlSession共享。Mybatis需要手动设置启动二级缓存。
    二级缓存是默认启用的(要生效需要对每个Mapper进行配置),如想取消,则可以通过Mybatis配置文件中的元素下的子元素来指定cacheEnabled为false。
4. 列举工作中常用的几个git命令?
	git init
	git add
	git commit
	git push
	git pull
	git clone
	git checkout
	git branch 分支名称
5. 提交时发生冲突,你能解释冲突是如何产生的吗?你是如何解决的?
  1. 冲突是如何产生的
    我们都知道,Git的实现途径是1棵树。比如有一个节点树(point1),
    我们基于point1进行开发,开发出了结点point2;
    我们基于point1进行开发,开发出了结点point3;
    如果我们在point2和point3内操作了同一类元素,那么势必会导致冲突的存在。
  2. 冲突是如何解决的?
    解决冲突通常使用如下的步骤即可:
    情况1 无冲突
    先拉取远端的代码,更新本地代码。然后提交自己的更新代码即可。
    情况2 有冲突
    拉取远端代码。存在冲突,会报错。
    此时我们需要将本地代码暂存起来 stash;
    更新本地代码,将本地代码版本更新和远端的代码一致即可;
    将暂存的代码合并到更新后的代码后,有冲突解决冲突(需要手动进行解决冲突);
    提交解决冲突后的代码。
6. Git中如果代码出现bug,你们是如何解决的?

开启一个bug分支

7. 项目中常见的分支 有哪些?

master:主分支,对外发布
dev:开发分支
test:测试分支
bug:修复bug分支
feature:特性分支
hotfixes:热线分支

8. String a = “ab”; String b = “a” + “b”; a == b 是否相等,为什么?

相等,string 性能优化
String a =“a”+“b”+“c”+“d”;

9. volatile作用?

a、防止执行指令重排序
b、内存可见性

10. Java 中,Comparator 与Comparable 有什么不同?
  1. Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。
  2. Comparable是在集合内部定义的方法实现的排序,位于java.lang下。
    Comparator是在集合外部实现的排序,位于java.util下。

day14测试

1. CAS原理及作用
AtomicInteger
 public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
  }
//var1:当前对象
//var2:原有内存值
//var4:需要自增的值
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);//获取当前内存值
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
		if(var2 == var5){
			var5 = var5+var4;
			return true;
		}
		return false;
	
        return var5;
    }

CAS原理:获取旧的内存值V,获取当前内存值A, 只有当V==A,才将内存值修改成B
原子变量都是基于CAS实现的
AtomicInteger,AtomitLong
问题:ABA问题,通过版本号

A   a -> b->a
B	a->a->c
public class MyTest1  {
    public static void main(String[] args) {
        AtomicDemo demo = new AtomicDemo();
        for(int i=0; i<8; i++){
            new Thread(demo).start();
        }
    }
}

class AtomicDemo implements Runnable{
    //private int num = 0;
    private AtomicInteger num = new AtomicInteger(0);//原子变量

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(num.getAndIncrement());//原子操作
        //int temp;
        //temp = num;
        //temp = temp + 1;
        //num = temp

    }

}
2. 如何实现Ajax的跨域?
  1. 用代理服务器代理
  2. 使用jsonp
  3. 服务端设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
3. String内部如何实现equals方法
  1. 首先是和自己比;
  2. 被比较的对象是否是String类型的;
  3. 再看它的长度是否相等;
  4. 比较它里面的每一个字符串;
4. ArrayList如何实现线程安全
  1. 使用synchronized关键字
  2. 使用Collections.synchronizedList();

​ 假如你创建的代码如下:List<Map<String,Object>> data=new ArrayList<Map<String,Object>>();

​ 那么为了解决这个线程安全问题你可以这么使用Collections.synchronizedList(),如:

​ List<Map<String,Object>> data=Collections.synchronizedList(new ArrayList<Map<String,Object>>());

5. 冒泡排序算法
    //简单选择排序算法
    private void selectSort(int[] datas){
        int length = datas.length;
        for(int i=0;i<length;i++){
            int min = i;
            for(int j=i+1;j<length;j++){
                int a = datas[min];
                int b = datas[j];
                if(a>b){//这里为升序,如果要降序则直接这里改成小于即可
                    min = j;
                }
            }
            int temp = datas[min];
            datas[min] = datas[i];
            datas[i] = temp;
            Log.i("sort", Arrays.toString(datas)+"  i:"+i);
        }
    }
    //冒泡排序算法
    private void bubbleSort(int[] datas) {
        int length = datas.length;
        boolean flag;
        for (int i = 0; i < length - 1; i++) {
            flag = false;//使用flag对冒泡排序进行优化
            for (int j = 0; j < length - i-1; j++) {
                if (datas[j] > datas[j+1]) {//这里为升序,如果要降序则直接这里改成小于即可
                    int temp = datas[j];
                    datas[j] = datas[j+1];
                    datas[j+1] = temp;
                    flag = true;
                }
                Log.i("sort", Arrays.toString(datas) + "  j:" + j + "  length-i:" + (length - i));
            }
            if(!flag){//如果这里flag为false,表示现在数据已经是有序的了,则可以直接退出for循环了
                break;
            }
        }
    }
6. Spring中事务在什么情况下回失效。

​ a、try,catch
​ b、抛出检测异常
​ c、数据库引擎MyISAM

7. 主键索引和普通索引的区别,为什么主键要比普通快?

​ 数据库的引擎是Innodb
​ 主键索引:索引的叶子节点中存储行数据
​ 普通索引:索引的叶子节点存储的是主键值,存在二次索引过程
​ 主键索引建议用自增

8. 什么是脏读、幻读、不可重复读?
问题描述
脏读 (Dirty Read)一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止
不可重复读(Non-repeatable Read)一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于 repeatable-read 可防止
幻读(Phantom Read)一个事务内多次读取一张表中的相同内容,其结果不一致。serialized-read 可防止
9. 如何防止表单重复提交

1、JavaScript防止表单重复提交(主要用于网络延迟情况下用户点击多次submit按钮导致表单重复提交)

在jsp页面中,添加JavaScript代码来防止表单的重复提交。主要是针对在网络延迟情况下用户有时间点击多次submit按钮导致表单重复提交,使用javascript控制Form表单只能提交一次。

2、**将提交按钮设置为不可用,**让用户点击第一次提交之后,没有机会点击第二次提交按钮的机会。(也可以将提交按钮隐藏起来,在点击第一次之后,将提交按钮隐藏起来)

3、利用Session防止表单重复提交(主要用于表单提交之后,点击浏览器刷新按钮导致表单重复提交,以及点击浏览器返回按钮退回到表单页面后进行再次提交)

(1)表单页面由servlet程序(服务器端)生成,servlet为每次产生的表单页面分配一个唯一的随机标识号(Token令牌),并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。
(2)当用户提交FORM表单时,负责处理表单提交的serlvet得到表单提交的标识号,并与session中存储的标识号比较,如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。如果不一致,就是重复提交了,此时服务器端就可以不处理重复提交的表单了。
(3)服务器程序将拒绝用户提交的表单请求情况如下:
1):存储Session域中的表单唯一的标识号与表单提交的标识号不同
2):当前用户的Session中不存在表单标识号
3):用户提交的表单数据中没有标识号字段

(4)创建标识号

String token = TokenProccessor.getInstance().makeToken();

(5)在服务器端使用Session保存标识号

request.getSession().setAttribute(“token”,token);

(6)、在form表单中也就是JSP页面中,使用隐藏域来存储标识号(Token令牌)

10. 原生js ajax请求有几个步骤?分别是什么?
//第一步,创建XMLHttpRequest对象
var xmlHttp = new XMLHttpRequest();
function CommentAll() {
    //第二步,注册回调函数
    xmlHttp.onreadystatechange =callback1;
    //{
    //    if (xmlHttp.readyState == 4)
    //        if (xmlHttp.status == 200) {
    //            var responseText = xmlHttp.responseText;

    //        }
    //}
    //第三步,配置请求信息,open(),get
    //get请求下参数加在url后,.ashx?methodName = GetAllComment&str1=str1&str2=str2
    xmlHttp.open("post", "/ashx/myzhuye/Detail.ashx?methodName=GetAllComment", true);

    //post请求下需要配置请求头信息
    //xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    //第四步,发送请求,post请求下,要传递的参数放这
    xmlHttp.send("methodName = GetAllComment&str1=str1&str2=str2");//"

}
//第五步,创建回调函数
function callback1() {
    if (xmlHttp.readyState == 4)
        if (xmlHttp.status == 200) {
            //取得返回的数据
            var data = xmlHttp.responseText;
            //json字符串转为json格式
            data = eval(data);
            $.each(data,
                function(i, v) {
                    alert(v);
                });       
        }
}



//后台方法
 private  void GetAllComment(HttpContext context)
        {

            //Params可以取得get与post方式传递过来的值。
            string methodName = context.Request.Params["methodName"];

            //QueryString只能取得get方式传递过来的值。
            string str1 = context.Request.Form["str1"];

            //取得httpRequest传来的值,包括get与post方式
            string str2 = context.Request["str2"];

            List<string> comments = new List<string>();

            comments.Add(methodName);

            comments.Add(str1);

            comments.Add(str2);


            //ajax接受的是json类型,需要把返回的数据转给json格式
            string commentsJson = new JavaScriptSerializer().Serialize(comments);
            context.Response.Write(commentsJson);
        }

day15测试

1. ArrayList和Vector的区别

区别:

​ ArrayList非安全,Vector安全
​ 扩容ArrayList 1.5倍 Vector 2倍

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

​ List:有序
​ Set:无序
​ Map:key->value(key 不可以重复;value 可以重复)

3. Collection 和 Collections的区别
  1. Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
  2. Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作
4. HashMap的实现原理

​ 数组+链表+红黑树

5. volatile关键字的作用?能否保证线程安全?

不能保证线程安全

  1. 保持可见性

禁止进行指令的重排序(volatile关键字能确保变量在线程中的操作不会被重排序而是按照代码中规定的顺序进行访问) 有序性

  1. 并不能保证原子性

在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。

6. 高并发应该使用什么Map?

Hashtable
ConcurrentHashMap

7. 什么是乐观锁和悲观锁?

简单理解下悲观锁:当一个事务锁定了一些数据之后,只有当当前锁提交了事务,释放了锁,其他事务才能获得锁并执行操作。

乐观锁是首先假设数据冲突很少,只有在数据提交修改的时候才进行校验,如果冲突了则不会进行更新。

8. 数据库的三大范式

1NF:一个表中每个字段都是独立

2NF:表中的每一行数据都是唯一的,所有非主键字段都和主键字段关联,不能存在间接依赖

3NF:表中不能存在传递依赖

9. synchronized锁是公平锁还是非公平锁

非公平锁

10. 十进制数12的二进制表示应该是?

1100

day16测试

1. ConcurrentHashMap在JDK1.8之后结构做了哪些改进?

HashMap
Hashtable
CocurrentHashMap->分段锁segement(RetreenLock)->synchronized+cas+红黑色

改进一:取消segments字段,直接采用transient volatile HashEntry<K,V> table保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。

改进二:将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。如果hash之后散列的很均匀,那么table数组中的每个队列长度主要为0或者1。但实际情况并非总是如此理想,虽然ConcurrentHashMap类默认的加载因子为0.75,但是在数据量过大或者运气不佳的情况下,还是会存在一些队列长度过长的情况,如果还是采用单向列表方式,那么查询某个节点的时间复杂度为O(n);因此,对于个数超过8(默认值)的列表,jdk1.8中采用了红黑树的结构,那么查询的时间复杂度可以降低到O(logN),可以改进性能。

2. Spring Bean作用域的有哪些?
singleton
prototype
request
session
application
3. Spring中Bean的注入方式有哪些?

​ set注入
​ 构造注入
​ 自动注入

4. 如何获取自动生成的(主)键值?
last_insert_id()
5. 了解过哪些JDK8的新特性,举例描述下相应的特性?

​ 接口中定义Default和static
​ 函数式接口@FunctionInterface
​ lambda表达式 ()->{}
​ stream流
​ 日期时间
​ Optional

6. hashCode的作用?
  1. Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。 要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。但是,如果每增加一个元素就检查一 次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它 就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。如果这个位置上没有元素,它就可以 直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了;不相同,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。所以这里存在一个冲突解决的问题(很少出现)。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。 所以,Java对于eqauls方法和hashCode方法是这样规定的:
    1、如果两个对象相等,那么它们的hashCode值一定要相等;
    2、如果两个对象的hashCode相等,它们并不一定相等。
    上面说的对象相等指的是用eqauls方法比较。
7. 深拷贝和浅拷贝区别

深拷贝和浅拷贝都是对象拷贝

  1. 深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
  2. 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
8. JAVA遍历Map的方式有几种
        for(String key :map.keySet()){
            System.out.println(key+":"+map.get(key));
        }

        for(String val : map.values()){
            System.out.println(val);
        }

        for(Map.Entry<String,String> e : map.entrySet()){
            System.out.println(e.getKey()+":"+e.getValue());
        }

        Set<Map.Entry<String, String>> set =   map.entrySet();
        Iterator<Map.Entry<String, String>> iterator = set.iterator();
        while(iterator.hasNext()){
            Map.Entry<String, String> next = iterator.next();
            System.out.println(next.getKey()+":"+next.getValue());
        }
9. 怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?

String newStr = new String(str.getBytes(“GB2312”), “ISO-8859-1”);

10. forward 和 redirect 的区别?
(1). 从地址栏显示来说
  1. forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器.浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
  2. redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
(2). 从数据共享来说
  1. forward:转发页面和转发到的页面可以共享request里面的数据.
  2. redirect:不能共享数据.
(3). 从运用地方来说
  1. forward:一般用于用户登陆的时候,根据角色转发到相应的模块.
  2. redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等.
(4). 从效率来说
  1. forward:高.
  2. redirect:低.

day17测试

1. Shiro认证和授权的流程?

​ 主体-》SecurityManager-》认证器(Authentication)-》Realm实现具体认证过程
​ 主体-》SecurityManager-》授权器(Authorization)-》Realm实现具体的授权过程

2. 传递一个集合作为参数给函数时,如何能确保函数将无法对其进行修改?
  1. final
  2. Collections.unmodifiableCollection(Collection);
  3. 如何修改集合则抛出UnsupportedOperationException
3. 哪一个List实现了最快插入?

LinkedList

4. Java的concurrent包中的有哪些API?

​ Lock
​ 原子变量:AtomicInteger
​ ConcurrentHashMap
​ Executor

5. 怎么判断对象是否可以被回收?
  1. 可达性分析
  2. 引用计算
6. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?

​ InnoDB->内存->6
​ MyISAM->文件->8

7. AQS是什么?

AQS:AbstractQueuedSynchronizer

抽象队列同步器,实现锁机制(CAS+FIFO)
ReentrantLock

8. java的基础类型和字节大小
1. 基本数据类型(布尔)
类型字节取值范围描述
boolean1字节true/false仅可描述“真”或者“假”
  1. 可直接赋值true/false

  2. 也可以直接赋值一个结果为true/false的表达式

    boolean result = 3 > 2;
    //注:Java中的boolean不能参与算术运算
    
2. 基本数据类型(字符)
类型字节取值范围(无符号数)字符编码
char2字节0~65535Unicode字符集(万国码)
  1. char :character

    1). 应额嗯对应的ASCCI编码,中文或者其他国家语言对应Unicode编码。

     2). 每个字符都有对应的整数变现形式。
    
     3). 赋值:char c1 = 'A';  或者   char c2 = 65;    或者     char c3 = '\u0041';
    
  2. Unicode 字符集支持ASCII编码(美国标准信息交换码)。

  3. Unicode中每个字符都对应一个十进制整数,从而可以使用多种方式赋值。

  4. 字符赋值:char c1 = ‘A’;(通过’'描述字符赋值)

  5. 整数赋值:char c2 = 65;(通过十进制65在字符集中对应的字符赋值)

  6. 进制赋值:char c3 = ‘\u0041’;(通过十六进制数41在字符集中对应的字符赋值)

3. 转义字符
  1. 如果需要在程序中输出一个单引号字符,该如何完成?

  2. package demo;
    
    public class TestChar {
    	public static void main(String[] args) {
    		char c = '\'';
    		System.out.println(c);
    	}
    }
    
转义字符描述
\n换行符
\t缩进(制表符)
\\反斜线
\’单引号
\’’双引号
class Demo {
	public static void main(String[] args) {
		
		char c1 = 'A';
		
		char c2 = 'B';
		
		char c3 = 67;
		
		char c4 = '好';
		
		//char c5 = "K";
		
		/*  Demo.java:12: 错误: 不兼容的类型: String无法转换为char
                char c5 = "K";
                          ^
			1 个错误
		*/
		
		char c6 = '\u0041';
		
		char c7 = '\'';//转义字符
		
		System.out.println(c1);
		
		System.out.println(c2);
		
		System.out.println(c3);
		
		System.out.println((int)c4);
		
		/*System.out.println(c5);
		Demo.java:30: 错误: 找不到符号
                System.out.println(c5);
                                   ^
		符号:   变量 c5
		位置: 类 Demo
		1 个错误
		*/
		System.out.println(c6);
		
		System.out.print("Hello\n");
		
		System.out.print("world");
	}
}
整数类型
类型字节取值范围(二进制)取值范围(十进制)
byte1字节-27~27-1-128~127
short2字节-215~215-1-32768~32767
int4字节-231~231-1-2147483648~2147483647
long8字节-263~263-1-9223372036854775808~9223372036854775807
小数/浮点数
类型字节负数取值范围
float4字节-3.4E+38~1.4E-451.4E-45~3.4E+38
double8字节-1.7E+3.8~-4.9E-3244.9E-45~3.4E+38
9. CAS机制是什么,如何解决ABA问题。

ABA问题,简单描述就是存在一个变量值为A,第一个线程把变量值从A改成了B,第二个线程又把变量值从B改成了A,这样,后面的线程读取这个变量的时候就会以为变量值没有发生过任何变化。

  1. CAS概述

CAS:Compare and Swap,即比较再交换,它是一条CPU并发原语。
它的功能是判断内存某个位置的值是否为预期值,如果是,则更改为最新值,这个过程是原子的。

CAS并发原语体现在Java语言中的sun.misc.Unsafe类中的各个方法,调用Unsafe类中的CAS方法,JVM会帮我们实现CAS汇编指令,它是一种完全依赖于硬件的功能,通过它实现了原子操作,再次强调,由于CAS是一种系统原语,原语属于操作系统用语的范畴,是由若干条指令组成的,用于完成某个功能的一个过程,并且原语的执行是连续的,在执行过程中不允许被中断,也就是说CAS是一条CPU的原子指令,不会造成所谓的数据不一致问题。

jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronzied同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。

对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

10. http1.0和http1.1有什么区别

长连接: 长连接(HTTP persistent connection ,也有翻译为持久连接),指数据传输完成了保持TCP连接不断开(不发RST包、不四次握手),等待在同域名下继续用这个通道传输数据;相反的就是短连接。
Host域
带宽优化
消息传递
缓存

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值