String是一个不变的对象
简单的了解二进制
计算机的存储方式都是以二进制的形式完成的,用0、1来表示有电无电。
以8421原理可以进行简单的计算二进制。
字符集编码历史
最早的字符集编码ASCII,可以编码英文,和少数字符,用一个字节来表示。
ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符
GBK(可以编码中文了,占用两字节)
GBK即汉字内码扩展规范,K为扩展的汉语拼音中“扩”字的声母。英文全称Chinese Internal Code Specification。GBK编码标准兼容GB2312,共收录汉字21003个、符号883个,并提供1894个造字码位,简、繁体字融于一库。GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,1980年由国家标准总局发布。基本集共收入汉字6763个和非汉字图形字符682个,通行于中国大陆。新加坡等地也使用此编码。GBK是对GB2312-80的扩展,也就是CP936字码表 (Code Page 936)的扩展(之前CP936和GB 2312-80一模一样)。
Unicode编码(几乎覆盖了全球所有的语言)
如上ANSI编码条例中所述,世界上存在着多种编码
方式,在ANSi编码下,同一个编码值,在不同的编码体系里代表着不同的字。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码,可能最终显示的是中文,也可能显示的是日文。在ANSI编码体系下,要想打开一个文本文件,不但要知道它的编码方式,还要安装有对应编码表,否则就可能无法读取或出现乱码。为什么电子邮件和网页都经常会出现乱码,就是因为信息的提供者可能是日文的ANSI编码体系和信息的读取者可能是中文的编码体系,他们对同一个二进制编码值进行显示,采用了不同的编码,导致乱码。这个问题促使了unicode码的诞生。
UTF-8
为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。
注:GBK的中文编码占用字节,UTF-8的中文编码占用3字节 。
String 是一个字称为字符串
1、String是一个类;
2、String 可以申明变量;
3、String可以创建对象,其内部是一个字符数组;
字符串常量池
·为什么要用字符串常量池?
因为我们经常要使用字符串,所以我们要用的时候直接调用即可。
好处:内存开销小,可以重用。
缺点:不便于修改,要想修改的话将创建新的对象。
如果是动态变量的情况将不会进行复用,以下代码可以体现
package mystring;/*** @author: 天天快乐的小亮* @date: 2020/10/18 22:31* @description:*/public class StringDemo1 {public static void main(String[] args) {String s1 = "ABC";String s2 = "ABC";//创建了新的 对象String s3 = new String("ABC");//不会对动态变量的值进行复用String s4 = "ABCDE";String s5 = s1+"DE";System.out.println(s1 == s2);System.out.println(s2 == s3);System.out.println(s4 == s5);}}
经典面试题
String s3 = new String("ABC");
如上代码创建了几个字符对象?
如上代码创建了2个字符对象,1个字符串数组对象。
附加:
关于==和equals的区别和联系:
1、==比较基本数据类型比较的是值相等,比较的是引用数据类型比较的是地址值是否相等。
2、equals不能用于基本数据类型的比较,会报错。
1、equals()继承自object类
2、如果equals()没有重写,那么比较的还是地址,只有重写了才能
比较内容。
3、String、Date类多默认对equals()进行了重写。
/***String 类对equals()重写*/public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = value.length;if (n == anotherString.value.length) {char v1[] = value;char v2[] = anotherString.value;int i = 0;while (n-- != 0) {if (v1[i] != v2[i])return false;i++;}return true;}}return false;}
注意点:
只有采用字面量的形式对String类型的变量赋值时,才会重用常量池中的值,如果new了一个对象出来,那么这两个对象肯定不是统一个对象了。(所以通常我们比较字符串的时候要用equals()而不能用==)
String s1="123abc";String s4=new String("123abc");System.out.println(s1==s4);//false
附加:

给出上面程序的输出?
解答:
上面的输出分别是
true
false
原因:s1的这种表达式因为在编译的时候就可以确定结果,所以不需要编译器出编译,所以可以将它当成字面量处理,而s3则是拼接了新的对象,对对象不一样,比较的结果肯定是不一样的。
这题考查的是编译器的一个特性,而并非字符串的知识点。
字符串的方法
length()获取字符串长度
package string;/**返回字符串的长度* @author 天天快乐的小亮* @date 2019/10/20-16:44*/public class StringLengthDemo {public static void main(String[] args) {String str="学习java think in";System.out.println(str.length());}}
IndexOf()
查找字符串的位置,位置到则返回-1
还有几个重载的方法
package string;/*** @author 天天快乐的小亮* @date 2019/10/20-16:48*/public class StringIndexOfDemo {public static void main(String[] args) {String str="学习java think in";System.out.println(str.indexOf("java"));//返回其位置为2System.out.println(str.indexOf("javas"));//未找到则返回-1}}
subSting()(包头不包尾)
结合indexOf查找指定域名的名称。
package string;/*** 截取字符串 包头不包尾** @author 天天快乐的小亮* @date 2019/10/20-17:01*/public class StringSubString {public static void main(String[] args) {String str = "www.baidu.com";System.out.println(str.substring(4, 9));//baidu//还有个重载的方法 切一刀到末尾System.out.println(str.substring(4));//根据subString()截取域名String url1="www.souhu.com";String url2="https://.meituan.com";String url3="www.hopu.com.cn";//String hostName = getHostName(url1);String hostName = getHostName(url2);String hostName3 = getHostName(url3);System.out.println(hostName3);System.out.println(hostName);}/*** 根据URL截取域名** @param url* @return 域名*/public static String getHostName(String url) {//查第一个点出现的位置int first = url.indexOf(".")+1;//查第二个点出现的位置int end=url.indexOf(".",first);return url.substring(first,end);}}
trim()去字符左右两边空格
package string;/**去字符左右两边空格* @author 天天快乐的小亮* @date 2019/10/20-19:38*/public class StringTrim {public static void main(String[] args) {String str=" helllo ";//去除左右两边空格System.out.println(str.trim());}}
charAt()根据索引查找指定字符串
package string;/***charAt()根据索引查找指定字符串* @author 天天快乐的小亮* @date 2019/10/20-19:42*/public class ChaAtDemo {public static void main(String[] args) {String str="I love think in java!";//根据索引查找指定字符串System.out.println(str.charAt(5));//查找每个字符for (int i = 0; i <str.length() ; i++) {System.out.println(str.charAt(i));}}}
startsWith()和endsWith()
匹配是不是以某个字符开始或结束
package string;/*** 匹配是不是以某个字符开始或结束** @author 天天快乐的小亮* @date 2019/10/20-19:50*/public class StringStartsWith {public static void main(String[] args) {String str = "I love think in java!";System.out.println(str.startsWith("java"));}}
valueOf()静态方法
package string;/*** 将类型转换成字符串类型* @author 天天快乐的小亮* @date 2019/10/20-19:54*/public class StringValueOf {public static void main(String[] args) {int i=10;String s = String.valueOf(i);System.out.println(s);double j=20;System.out.println(String.valueOf(j));//或者直接加""float c=30.0f;String c1=c+"";System.out.println(c1);}}
字符串频繁拼接带来的性能问题

下面的代码会频繁的创建对象,性能非常低(方式一)
package string;/*** 字符串频繁修改带来的性能问题* @author 天天快乐的小亮* @date 2019/10/20-20:39*/public class StringDemo2 {public static void main(String[] args) {String str="a";for (int i = 0; i < 1000000; i++) {str+="a";System.out.println(str);}}}
StringBuilder修改字符串操作
package string;/*** @author 天天快乐的小亮* @date 2019/10/21-10:34*/public class StringBuilderDemo {public static void main(String[] args) {String str="I love java!";StringBuilder stringBuilder=new StringBuilder(str);/*** append()拼接字符串**/StringBuilder str1 = stringBuilder.append(",为了迎娶白富美!");System.out.println(str1);/*** insert() 插入字符串*/StringBuilder str2 = stringBuilder.insert(str.indexOf("!"), "、C#");System.out.println(str2);/*** replace()替换*/StringBuilder str3 = stringBuilder.replace(7, 11, "JavaScript");System.out.println(str3);}}
方式二
package string;/*** StringBuilder 的性能问题* @author 天天快乐的小亮* @date 2019/10/21-11:06*/public class StringBuilderDemo2 {public static void main(String[] args) {String str="a";StringBuilder sb=new StringBuilder(str);for (int i = 0; i < 1000000; i++) {/*采用stringBuilder执行字符串的修改操作效率是可观的*/sb.append("a");}System.out.println("执行完毕");}}
频繁修改字字符串的总结
因为方式二不会频繁的去创建stringBuilder对象,只是在后面进行拼接,所以相对方式一的效率会高很多。
