网站开发毕业设计论文,衡阳城乡建设部网站首页,网站搭建php源码,活动策划代运营的公司String
1#xff1a;字符串的不可变性 什么是不可变对象#xff1f;不可变对象是指创建后无法变更的对象 String为什么是不可变的#xff1f;String类为final#xff0c;并且内部字符数组也为final。所以String对象是不可变对象。 String类为什么要设计为不可变#xff1…String
1字符串的不可变性 什么是不可变对象不可变对象是指创建后无法变更的对象 String为什么是不可变的String类为final并且内部字符数组也为final。所以String对象是不可变对象。 String类为什么要设计为不可变 主要出于对效率和安全的考量。 当你复制一个对象的时候如果你知道它是不可变的那么你只需要复制此对象的引用即可一般引用会比对象小很多所以能提高效率String是不可变的所以字符串常量池才可以存在减少很多heap内存的占用因为String的不可变性所以在创建的时候hashcode就可以缓存很适合作为map的key值 安全方面不可变对象是线程安全的。在多线程情况下可变对象的内部状态可能会被其他线程改变导致不可预期的结果。比如数据库连接socket连接的IP PORT类加载器等都是通过String传参的如果String是可变的那会引起很大的安全问题。
2JDK 6和JDK 7中substring的原理及区别 subString(int beginIndex, int endIndex)方法用来截取字符串
String x qwertt;x x.substring(1,2);System.out.println(x);结果输出
wJDK6中的subString String类有三个属性 char[] value字符数组 int offset起始位置 int count字符串长度 对于subString方法生成的String对象value相同只是改变了offset和count。这样会导致一个严重的问题本来只需要很短的字符串但是因为指向了一个很长的字符串导致这个长字符串无法回收存在内存泄漏的风险。
//JDK 6
String(int offset, int count, char value[]) {this.value value;this.offset offset;this.count count;
}public String substring(int beginIndex, int endIndex) {//check boundaryreturn new String(offset beginIndex, endIndex - beginIndex, value);
}jdk6中为解决上述问题一般生成一个新的字符串并引用它
x x.substring(x, y)
JDK7中的subString 在jdk7中对上述问题进行了优化。每次执行subString的时候都会去生成一个新的char[] 从而避免了上述问题 jdk7源码如下
//JDK 7
public String(char value[], int offset, int count) {//check boundarythis.value Arrays.copyOfRange(value, offset, offset count);
}public String substring(int beginIndex, int endIndex) {//check boundaryint subLen endIndex - beginIndex;return new String(value, beginIndex, subLen);
}3replaceFirst、replaceAll、replace区别
先看一个示例String s my.test.txt;
System.out.println(s.replace(., #));
System.out.println(s.replaceAll(., #));
System.out.println(s.replaceFirst(., #));
System.out.println(s.replaceFirst(\\., #));执行结果
my#test#txt
###########
#y.test.txt
my#test.txt原因 replace方法有两个实现一个是传入字符循环匹配一个是传入字符串使用Pattern的逐个按字符进行匹配 replaceFirst和replaceAll是使用Pattern进行正则表达式的匹配。因为“.”在正则表达式中表示任一字符所以出现了“###########”的结果。
附源代码实现jdk1.8版
replace()
public String replace(char oldChar, char newChar) {if (oldChar ! newChar) {int len value.length;int i -1;char[] val value; /* avoid getfield opcode */while (i len) {if (val[i] oldChar) {break;}}if (i len) {char buf[] new char[len];for (int j 0; j i; j) {buf[j] val[j];}while (i len) {char c val[i];buf[i] (c oldChar) ? newChar : c;i;}return new String(buf, true);}}return this;}replace()
public String replace(CharSequence target, CharSequence replacement) {return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));}replaceAll()
public String replaceAll(String regex, String replacement) {return Pattern.compile(regex).matcher(this).replaceAll(replacement);}replaceFirst()
public String replaceFirst(String regex, String replacement) {return Pattern.compile(regex).matcher(this).replaceFirst(replacement);}4String对“”的重载、字符串拼接的几种方式和区别 字符串的拼接方式“”、StringBuffer、new String().concat、StringBuilder “”底层是使用StringBuilder实现。如
String s1 11;
String s2 22;
String s s1s2;
System.out.println(s);其实此段代码基本等价于
String s1 11;
String s2 22;
StringBuilder sb new StringBuilder();
sb.append(s1);
sb.append(s2);
String str sb.toString();
System.out.println(str);在大量使用“”进行字符串拼接的时候会产生大量的StringBuilder和String对象会严重影响效率
concat concat其实是申请一个新的数组进行数组的拷贝然后用来创建新的String对象。底层是调用System.arraycopy()
public String concat(String str) {int otherLen str.length();if (otherLen 0) {return this;}int len value.length;char buf[] Arrays.copyOf(value, len otherLen);str.getChars(buf, len);return new String(buf, true);}StringBuffer StringBuilder 两者调用的父类方法如下区别在于StringBuffer 方法用了synchronized是线程安全的 与concat的区别在于 扩容逻辑不同concat为需要多少扩多少StringBuilder等是指数级扩容 concat每次会生成新的String对象而StringBuilder不会
public AbstractStringBuilder append(String str) {if (str null)return appendNull();int len str.length();ensureCapacityInternal(count len);str.getChars(0, len, value, count);count len;return this;}5String.valueOf和Integer.toString的区别
直接看源代码就好
public static String valueOf(int i) {return Integer.toString(i);
}//对null进行了处理
public static String valueOf(Object obj) {return (obj null) ? null : obj.toString();} public static String toString(int i) {if (i Integer.MIN_VALUE)return -2147483648;int size (i 0) ? stringSize(-i) 1 : stringSize(i);char[] buf new char[size];getChars(i, size, buf);return new String(buf, true);}6switch对String的支持 Java JDK7中switch添加了对String的支持之前仅支持short、int、byte、char并且底层最终都会转为int类型。那么对于String是如何支持的呢 请看以下代码
public static void test(String status) {switch (status) {case INIT:System.out.println(INIT); break;case PAY_ING:System.out.println(PAY_ING); break;case PAY_SUCCESS:System.out.println(PAY_SUCCESS); break;case PAY_FAIL:System.out.println(PAY_FAIL); break;default:System.out.println(default); break;}}反编译class文件得到
public void test(String status){String str;switch ((str status).hashCode()){case -2113017739:if (str.equals(PAY_FAIL)) break label129; break;case -68158581:if (str.equals(PAY_ING)) break label107; break;case 2252048:if (str.equals(INIT)) break label96; break;case 1643683628:if (!(str.equals(PAY_SUCCESS))) { break label140:System.out.println(INIT);return;System.out.println(PAY_ING);return;}System.out.println(PAY_SUCCESS);return;label129: System.out.println(PAY_FAIL);label140: break;default:label96: label107: System.out.println(default);}}虽然看不懂有些带标签的break语句break label;但是很明显可以看出来支持String的方式 将String转为了int类型的hashCode因为hashCode可能会冲突又加入了equals判断。
7字符串池、常量池运行时常量池、Class常量池、intern 偷个懒先放个链接后续再慢慢完善 https://www.cnblogs.com/tiancai/p/9321338.html