外贸网站模板免费,网站设计开发网站,了解什么是网络营销,怎样注册网站账号申请String在java中我们是用来操作字符串的#xff0c;但它的底层结构确是一个char[]数组#xff0c;通过数组的方式将每个字符进行保存。 使用时#xff1a;String strABCD#xff0c;内部存value确是#xff1a;value[A,B,C,D]; 如下图#xff1a; 参考String源…String在java中我们是用来操作字符串的但它的底层结构确是一个char[]数组通过数组的方式将每个字符进行保存。 使用时String strABCD内部存value确是value[A,B,C,D]; 如下图 参考String源码如下 public final class Stringimplements java.io.Serializable, ComparableString, CharSequence {private final char value[];private int hash; // Default to 0private static final long serialVersionUID -6849794470754667710L;......此处省略N多代码public String(String original) {this.value original.value;this.hash original.hash;}
}通过源码中的构造方法可以看到我们传递的参数值 是直接赋值给了value。如果声明一个String a”ABCD”那a对象的value实际就是一个数组[A,B,C,D] String赋值有两种一种是“”直接赋值另一种是new String(xxx)赋值这两种是有区别的。 “”赋值不会在堆上创建新的对象而是在常量池中搜索如果常量池中有这个字符串则直接引用这个字符串的地址。如果没有这个字符则会在常量池中创建该字符串并引用地址字符常量池中不存在两个相同的字符串也就是说
String str1 abc;
String str2 abc;
System.out.println(str1str2);//true
//二者引用的地址是相同的都指向一个字符串
new String()意味着创建了一个新的对象会在堆上分配一块内存但并不是说这个字符就存储在了堆上而是存储了一个地址这个地址仍然指向字符常量池。
String str1 abc;
String str2 new String(abc);
System.out.println(str1str2);//false继续看下列问题 声明四个String对象如下思考下它们之间用 比较的结果 String a “abc”;
String b “abc”;
String c new String(“abc”);
String d “ab” “c”; 其中a,b,d所有他们的引用是一样的所以String 没有被新创建对象。所以他们三个用 对比是true。 而c 则是new(“abc”) 新建了一个String 对象值虽然一样但是与 a,b,d 引用不一样所以a,b,d 与 c 对比则是 false。 String aabc在内存中创建几个对象 这个问题涉及到了字符串常量池和字符串拼接String aabc 通过编译器优化后得到的效果是 String aabc。此时如果字符串常量池中存在abc则该语句并不会创建对象只是将字符串常量池中的引用返回而已。如果字符串常量池中不存在abc则会创建并放入字符串常量池并返回引用此时会有一个对象进行创建。 JDK9为何要将String底层由char[]改成了byte[] 对于JDK9后的版本String底层由char[]改成了byte。那么将char[]改成了byte有和意义呢
1节省内存char占用两个字节byte只需要一个字节。
那么问题来了如果存储英文或数字可以使用byte那存储的中文或特殊字符呢
源码内有一个private final byte coder;用于兼容两个字节的字符
private final byte coder;static final byte LATIN1 0 ;// LATIN1用单个字节来表示字符
static final byte UTF16 1; // UTF16 是用双字节来表示字符 所以就可以根据存储内容的不同去判断应该使用那种编码如中文时使用UTF16英文就可以是LATIN1
2减少GC的次数减少了内存使用之后必然垃圾回收次数也会相对应减少