Java面试题

本文介绍了Java中String、StringBuilder和StringBuffer的区别,重点在于它们的可变性和线程安全性。String是不可变的,适合常量使用;StringBuilder在单线程环境下提供更高的效率;StringBuffer是线程安全的选择。此外,讨论了自定义异常在实际项目中的应用,以及如何解决并发编程中的ABA问题,提出了版本号或时间戳的解决方案。
摘要由CSDN通过智能技术生成

String、StringBuffer、StringBuilder区别及使用场景

Java平台提供了两钟类型的字符串:String和StringBuffer/StringBuider,它们都可以储存和操作字符串,区别如下:
(1)String是只读字符串,也就意味String引用的字符串内容是不能被改变的。初学者可能误解:

String str = "abc";
str = "bcd";

如上,字符串str明明是可以改变的啊?其实不然,str仅仅是一个引用对象,它指向一个字符串对象“abc”。第二行代码的含义是让str重新指向了一个新的字符串“bcd”对象,而“abc”对象并没有任何改变,只不过该对象已经成为一个不可以及对象而已。
(2)StringBuffer/StringBuilder表示的字符串对象可以直接进行修改。
(3)StringBuilder是Java5中引入的,他和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方法都没有被synchronized修饰,因此它的效率理论上也比StringBuffer高。

怎么声明一个类不会被继承,什么情况下使用?

如果一个类被final修饰,那么此类不可以有子类,不能被其它类继承。
如果一个类中所有方法都没有重写的需要,当前类没有子类也罢,就可以使用final修饰类。
比如java中的Math类,算数运算类。

自定义异常在生产中如何应用?

Java虽然提供了丰富的异常处理类,但是在项目中还是会常常使用自定义异常,其主要原因是Java提供的异常类在某些情况下还是不能满足实际需求。例如以下情况:
1、在系统中有些错误是符合Java语法的,但不符和业务逻辑。
2、在分层的软件结构中,通常是在表现层统一对系统其他层次的异常进行捕获处理。

ABA问题

1、有两个线程同时去修改一个变量的值,比如线程1、线程2,都更新变量的值,将变量值从A变为B。
2、首先线程1获取CPU的时间片,线程2由于某些原因发生阻塞进行等待,这时线程1进行比较更新,成功将变量的值从A更新成为B。
3、更新完毕后,恰好有线程3进来想要把变量的值从B更新为A,线程3进行比较更新,成功将变量的值从B更新成A
4.线程2获取到CPU的时间片,然后进行比较更新,发现值是预期的A,然后又更新成了B。但是线程1不知道,该值已经有了A-》B-》A这个过程,也就是我们常说的ABA问题

举个例子:
小明在提款机,提取了50元,因此提款机问题,
有两个线程,同时把余款从100变为50
线程1(提款机):获取当前值100,期望更新为50,
线程2(提款机):获取当前值100,期望更新为50,
线程1成功执行,线程2某种原因block了,这时某人给小明汇款50
线程3(默认):获取当前值50,期望更新为100,
这时候线程3执行成功,余款变为100,
线程2从block中恢复,获取到的也是100,compare之后,继续更新余款为50!!!
此时可以看到,实际余款应该为100(100-50+50),但实际上为50(100-50+50-50)

如何避免ABA问题

可以通过加版本号或者时间戳解决,或者保证单向递增或者递减就不会出现此类问题。

atomic包下的AtomicStampedReference类:其compareAndSet方法首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用的标志的值设置为给定的更新值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏天的狗子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值