- 字符型常量和字符串常量的区别
- 形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
- 含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字
符串在内存中存放位置) - 占内存大小 字符常量只占一个字节 字符串常量占若干个字节(至少一个字符结束标志)
字符串在jdk8之前底层使用的是一个char的数组
在jdk8之后使用的是一个byte的数组
- 什么是字符串常量池?
字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存 储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回 它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。
- String有哪些特性
- 不可变性 : String字符串是一个只读字符串 对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并 频繁访问时,可以保证数据的一致性。
- String为什么是不可变的?
简单来说就是String类利用了final修饰的char类型数组存储字符
/** The value is used for character storage. */
private final char value[];
原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。
反射也可以破坏它的不可变性
- String s = new String(“xyz”);创建了几个字符串对象
两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。
- String 类的常用方法都有那些?
- charAt(i) 返回第 I - 1个下标的元素
- subString(a,b) 从第a个位置返回b个元素
- indexOf(); 返回制定索引的字符
- replace() 字符串替换
- trim()。去掉字符串两边的空白部分
- split() 把一个字符串按照某个符号分成一个数组
- getBytes() 返回字符串的byte数组
- toLowerCase()。小写
- toUpperCase() 大写
- length() 获取长度
- 在使用 HashMap 的时候,用 String 做 key 有什么好处?
HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。
- String和StringBuffer、StringBuilder的区别是什么?String为什么是不可 变的
- 可变性: String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。 StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字 符数组保存字符串,char[] value,这两种对象都是可变的。
- 线程安全性: String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder 与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、 indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全 的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
- 性能:每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。 StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情 况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不 安全的风险。
- 小总结:
如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
- Integer a= 127 与 Integer b = 127相等吗
public static void main(String[] args) { Integer a = new Integer(3);
Integer b = 3; // 将3自动装箱成Integer类型 int c = 3;
System.out.println(a == b); // false 两个引用没有引用同一对象 System.out.println(a == c); // true a自动拆箱成int类型再和c比较 System.out.println(b == c); // true
Integer a1 = 128;
Integer b1 = 128; System.out.println(a1 == b1); // false
Integer a2 = 127;
Integer b2 = 127; System.out.println(a2 == b2); // true
}
如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量
池中的Integer对象,超过范围 a1==b1的结果是false;
- jdk165以后对StringBuffer和锁进行的一些优化
- 锁粗化 lock eliminate
- 锁消除
在插入数据的一个循环中一直插入数据 那么StringBuffer就有一个锁消除的机制 避免重复加入的时候影响效率