Java面试题:基础

最近在准备面试题,准备找个好工作,以我准备好就发的形式,一般一次三道,答案内容是我自行查阅相关资料获得.

1、StringBuffer、StringBuilder

StringBuffer 代码片段:

private transient char[] toStringCache;
@Override
public synchronized String toString() {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}

StringBuilder 代码片段:

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}
--StringBuffer、StringBuilder的区别 

区别1:线程安全
StringBuffer:线程安全,StringBuilder:线程不安全.因为StringBuffer的所有公开方法都是synchronized修饰的,而StringBuilder并没有synchronizedr修饰
区别2:缓冲区
可以看出,StringBuffer每次获取toString都会直接使用缓冲区的toStringCache值来构造一个字符串
而StringBuilder则每次都需要复制一次字符串,再构造一个字符串
所以,缓冲区这也是对StringBuffer的一个优化吧,不过StringBuffer的这个toString 方法仍然是同步的
区别3:性能
既然StringBuffer是线程安全的,它的所有公开方法都是同步的,StringBuilder是没有对方法加锁同步的,所以StringBuilder的性能要远大于StringBuffer.

总结:所以StringBuffer适用于用在多线程操作同一个StringBuffer的场景,如果是单线程场合StringBuilder更适合

2、#{}和${}的区别

1.编译过程
    1.#{}是占位符:动态解析->预编译->执行
    2.${}是拼接符:动态解析->编译->执行
预编译可以类比java类的编译,java类被编译成class文件,载入虚拟机,sql预编译后会在参数位置用占位符表示.
预编译:数据库驱动在发送sql和参数到DBMS之前,先对sql语句进行编译处理,之后DBMS则可以直接对sql进行处理,不需要再次编译,提供了性能.这一点mybatis默认情况下,将对所有的sql进行预编译处理
    预编译可以将多个操作步骤合并成一个步骤,一般而言,越复杂的sql,编译程度也会复杂,难度大,耗时,费性能,而预编译可以合并这些操作,预编译之后DBMS可以省去编译直接运行sql.
    预编译语句可以重复利用.
    把一个sql预编译后产生的PreparedStatement对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的PreparedState对象
2.是否自动加单引号
    1.#{}对应的变量会自动加上单引号
    2.${}对应的变量不会加上单引号
3.安全性
    1.#{}能防止sql注入
    2.${}不能防止sql注入
4.Mybatis默认值不同
    1.#{}默认值arg0、arg1、arg2 或01
    2.${}默认值param1、param2、param3
三.如何选择#{}和${}
	1.能用#{}的地方就用#{},尽量少用${}
	2.表示作参数,或者order by 排序时用${}
	3.传参时参数使用@Param("")注解,@Param注解的作用是给参数命名,参数命名后就能根据名字得到参数值(相当于又加了一层密),正确的将参数传入sql语句中(一般用过#{}会有sql注入的问题)如下:
	Role selectById(@Param("id") String id);
	List<Role>selectByNameAndOrgId(@Param("name")String name,@Param("orgId")String orgId);

3、hashtable与currenthashmap

hashtable与currenthashmap的区别
HashTable
1.底层数组+链表实现,key还是value都不能为null
2.线程安全,在修改数据时锁住整个HashTable,效率低,使用synchronize修饰
3.初始size为11,扩容:newsize = oldsize * 2 +1
4.多线程访问时,只要有一个线程访问或操作该对象,其他线程只能阻塞,并发形成非常差.

CurrentHashMap
1.jdk1,7采用数组+segment+分段锁来实现
分段锁技术:将数据分成一段一段的存储,然后把每一段数据配一把锁,当一个线程占用锁访问其中一段数据时,其他段数据也能被其他线程访问,能实现真正并发访问.
缺点:hash的过程比普通hashmap要长
2.jdk1.8采用数据+链表+红黑树,内部大量使用CAS操作,CAS是一种乐观锁
	悲观锁:将资源锁住,等一个之前获得锁的线程释放锁之后,下个线程才可以访问.
	乐观锁:通过方式不加锁处理资源,性能优于悲观锁.
3.jdk1.8彻底放弃segment而采用node,不再使用分段锁
4.线程安全
	jdk1.7采用segment分段锁机制,segment继承自ReetrantLock
	jdk1.8采用CAS + synchronized,是对hashtable进行优化,将锁细粒化到每个table的每个元素,来提升并发性能.
5.链表节点数量大于8时,链表转换为红黑树
6.时间复杂度:从遍历链表O(n),变成遍历红黑树O(logN)


以上观点,纯属个人理解,若有不正之处,烦请指出


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值