JavaGuide面试突击版-学习-0507-Java基础
String ,StringBuffer ,StringBuilder的区别?
字符串拼接用+
还是StringBuilder
示例截图: 用的就是
+
拼接字符串示例
字符串对象通过+
的字符串拼接⽅式,实际上是通过StringBuilder
调⽤append()
⽅法实现的,拼接完成之后调⽤toString()
得到⼀个 String
对象 。
注意事项 :
在循环内使⽤+
进⾏字符串的拼接的话,存在比较明显的缺陷:编译器不会创建单个 StringBuilder
以复⽤,会导致创建过多的 StringBuilder
对象。
String#equals() 和 Object#equals() 有何区别
String : 比较的是值是否相等;
Object : 比较的是对象的内存地址是否相等;
字符串常量池的作⽤
字符串常量池 是 JVM
为了提升性能和减少内存消耗针对字符串(String 类)专⻔开辟的⼀块区域,主要⽬的是为了避免字符串的重复创建
创建了⼏个字符串对象? String s1 = new String("abc");
String
类型的变量和常量做+
运算时发生了什么?
+++ 点击展开/隐藏
字符串不加final
关键字拼接的情况
String str1 = "str"; //编译器确定常量字符串,jvm将其加入`字符串常量池` |
编译器的优化:
编译期
可以确定的值的字符串,也就是常量字符串
,jvm
会将其存入字符串常量池
.字符串常量
拼接可以得到的字符串常量
在编译阶段
就已经
被存放字符串常量池
.
编译器优化: 常量折叠
常量折叠会把常量表达式的值求出来作为常量嵌在最终⽣成的代码中,这是 Javac 编译器会对源代码做的极少量优化措施之⼀(代码优化⼏乎都在即时编译器中进⾏)。
例如: 对于 String str3 = “str” + “ing”; 编译器会给你优化成 String str3 = “string”;
常量折叠的条件:
final
修饰 / 无final
修饰的基本数据类型(byte,short,int,long,double,float,chat,boolean)及字符串常量- 运算关系
- 字符串通过
+
拼接得到的字符串 - 基本数据类型之间的算数运算(加减乘除),位运算(<<,>>,>>>)
- 字符串通过
引⽤的值在程序编译期是⽆法确定的,编译器⽆法对其进⾏优化
对象引⽤和“+”的字符串拼接⽅式,实际上是通过 StringBuilder 调⽤ append() ⽅法实现的,拼接完成之后调⽤ toString() 得到⼀个 String 对象
String str4 = new StringBuilder().append(str1).append(str2).toString(); |
声明final
关键字之后,可以让编译器当作常量处理
final String str1 = "str"; |
被 final 关键字修改之后的 String 会被编译器当做常量来处理,编译器在程序编译期就可以确定它的值,其效果就相当于访问常量。
截图参考
没有final
关键字修饰的字符串,字节码中通过StringBuilder
拼接(属于新的对象,==
用来比较引用类型
是比较的内存地址是否相等)
编译器在运⾏时才能知道其确切值的话,就⽆法对其优化
final String str1 = "str"; |
+++
Exception 和 Error 有什么区别?
try-catch-finally
的使⽤
注意事项:
不要在finally
语句块中使用return
!
当 try 语句和 finally 语句中都有 return 语句时,try 语句
块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在⼀个本地变量中,当执⾏到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。
代码示例:
public static void main(String[] args) { |
输出:
0 |
finally 中的代码是否⼀定会执⾏
==不⼀定的!==
不会执行finally
中的代码情况如下:
finally
之前虚拟机被终⽌运⾏的话- 程序所在线程死亡
- 关闭CPU
try-catch-finally关闭资源?
什么是SPI
SPI 即 Service Provider Interface ,字⾯意思就是: 服务提供者的接⼝
API 和 API 的区别
SPI : 由接口调用方确定规则,不同的接口实现方去根据这个接口进行实现,从而提供方服务.
SPI 的优缺点
- 需要遍历加载所有的实现类,不能做到按需加载,这样效率还是相对低的
- 当多个
ServiceLoader
同时load
时,会有并发问题
什么是序列化?什么是反序列化?
序列化: 将数据结构或对象转换成⼆进制字节流的过程
反序列化: 将在序列化过程中所⽣成的⼆进制字节流转换成数据结构或者对象的过程
序列化目的: 序列化的主要⽬的是通过⽹络传输对象或者说是将对象存储到⽂件系统、数据库、内存中
部分字段不想进⾏序列化处理
transient
关键字的作⽤是:阻⽌实例中那些⽤此关键字修饰的的变量序列化;当对象被反序列化时,被 transient
修饰的变量值不会被持久化和恢复。
注意事项:
- 修饰变量,不能修饰类和⽅法
- 在反序列化后变量值将会被置成类型的默认值。例如,如果是修饰 int类型,那么反序列后结果就是 0 。
static
变量因为不属于任何对象(Object)
,所以⽆论有没有transient
关键字修饰,均不会被序列化。
Java IO 流
- InputStream\OutputStream 字节输入流\字节输出流
- Reader\Writer 字符输入流\字符输出流