Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学Java系列,这个系列记录了我的Java基础知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/jVH6W,话不多说我们马上开始!
1.字节和字符的区别?
字节:存储容量的基本单位,1字节 = 8个二进制位
字符:数字、字母、汉字以及其它语言的各种符号,一个字符由一个字节或多个字节的二进制单位组成,Java中,字符型数据(char)的大小为2个字节,16位,简单来记就是一个char = 一个汉字
2.String类的特性?
public final class String implements java.io.Serializable,
Comparable<String>, CharSequence {
private final char value[]; // JDK9之后为byte[]
private int hash;
......
}
(1)final类,不能被继承
(2)实现了Serializable和Comparable接口,支持序列化和比较
(3)底层通过char[]实现(JDK9之后为byte[]),被final修饰,因此String对象创建后不可被修改,具有不可变性
3.String为什么要设计为不可变类?
这个问题可以考虑从两个大的方面回答:性能优化和安全性
4.String的不可变性?
通过字面量方式为字符串赋值时,此时的字符串存储在方法区的字符串常量池中,并且在字符串常量池中不会存储相同内容的字符串。
String s1 = "hi";
String s2 = "hi";
s1 = "hello";
刚开始字符串s1和s2内容相等,都指向字符串常量池中的同一个地址,如下图所示:
当s1值的改变之后,此时s2的值不变还是指向原来的内存地址,但是s1会重新分配内存地址进行赋值,如下图所示:
总结1:String字符串具有不可变性,当字符串重新赋值时,不会在原来的内存地址进行修改,而是重新分配新的内存地址进行赋值。
String s3 = "abc";
String s4 = s3 + "def";
System.out.println(s3); //abc
总结2:当字符串进行拼接时,也不会在原来的内存地址进行修改,而是重新分配新的内存地址进行赋值。
String s5 = "abcd";
String s6 = s5.replace("d", "g");
System.out.println(s5);
此时的内存结构如下图所示:
总结3:当调用String的replace方法修改指定的字符或字符串时,也不会在原来的内存地址进行修改,也是重新分配新的内存地址进行赋值。
5.String str = “i” 与 String str = new String(“i”)一样吗?
不一样
通过字面量方式为字符串赋值时,此时的字符串存储在方法区的字符串常量池中;
通过new+构造器方式实例化字符串时,字符串对象存储在堆中,但是字符串的值仍然存储在方法区的常量池中。如下图所示:
// 通过字面量方式为字符串赋值时,此时字符串存储在方法区的字符串常量池中
String s1 = "hello";
String s2 = "hello";
// 通过new+构造器方式实例化字符串时,字符串对象存储在堆中
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // false
System.out.println(s3 == s4); // false
public class Person {
public String name;
public int age;
Person() {}
Person(String name,int age) {
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
Person p1 = new Person("Tom", 18);
Person p2 = new Person("Tom", 18);
System.out.println(p1.name == p2.name); // true
}
此时的内存结构如下图所示:
如果p2中name值进行了修改,那么就会在字符串常量池中新生成一个修改后的值,然后改变堆中name指向的地址值,内存结构就会变成如下图所示:
6.String str = new String(“i”)一共创建了几个对象?
一共会创建两个对象,一个是使用new创建的对象,存储在堆中;另一个是常量对象"i",存储在字符串常量池中