package com.atguigu.test08;
import org.junit.Test;
/*
* java.lang.String:
* 1、特点
* (1)String类型不能被继承,因为String是由final修饰
* (2)String类型的对象是不可变
* 换句话说,只要修改字符串,就会产生新对象
* (3)String对象不可变的特性,使得我们可以把一些字符串存到常量池中,
* 字符串有常量池。常量池中的是可以共享的。
*
* 字符串常量池在哪里?Oracle官方虚拟机HotSpot
* (1)JDK1.6以及之前:方法区
* (2)JDK1.7:挪到堆中,即在堆中单独划分了一块来存字符串常量
* (3)JDK1.8:从堆中挪出,挪到一个“元空间meta space”,即类似于方法区
* (4)String对象底层的存储
* JDK1.9之前:底层是用char[]存储
* JDK1.9之后:底层选用byte[]存储
*
* (5)String对象怎么就不可变
* ①底层char[]数组有final修饰,意味着这个数组不能扩容等,来达到存更多的字符
* ②char[]数组是私有的,我们程序员无法直接操作这个char[]数组,而且String没有提供这样的方法,来修改char[]数组的元素的值。
* String提供的所有的方法,对字符串的修改都是给你返回一个新的字符串对象。
*/
public class TestString01 {
@Test
public void test02(){
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);//true,说明是同一个位置,==比较的是地址值、equals比较的是内容。。。
}
@Test
public void test01(){
/* String s1 = "hello";
s1 = "world";
s1 = s1 + "java";*/
String s = "";
change(s);
System.out.println(s);//输出空,说明字符串不能被修改
}
public void change(String str){
str = "hello";
}
}
package com.atguigu.test08;
import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
import org.junit.Test;
/*
* 2、字符串的比较
* (1)==:比较对象的地址
* 结论:只有两个字符串的常量对象(并且地址相同)比较时才会返回true,其他的都是false(比如常量和变量比较也是false)
* (2)equals:比较字符串的内容,严格区分大小写
* 因为String类型重写了Object的equals
* (3)equalsIgnoreCase(String anotherString) :比较字符串内容,不区分大小写
* (4)大小比较
* String类型实现了Comparable接口,(说明)重写了compareTo方法,严格区分大小写,s1.compateTo(s2) s1>s2,返回整数,<则返回负数;
* 依次比较对应位置的字符,以下是比较的顺序:
* ①比较最靠前的字母:hello和Hello,先[0]位置的h和H,h>H,就直接认定为hello>Hello
* ②比较第一个不一样的之母:hello和hella,先[0][1][2][3]比较,都一样,最后到[4]o>a,认定hello>hella
* ③比较长度: hello和helloworld,发现前面都一样,长的大
*
* (5)大小比较:不区分大小写
* String类型还提供了一个方法compareToIgnoreCase,可以忽略大小写比较大小
*
* (6)按照每个国家的语言校对顺序
* java.text.Collator:Collator 类执行区分语言环境的 String 比较。使用此类可为自然语言文本构建搜索和排序例程。
* Collator实现了Comparator接口 ,
* Collator是抽象类,不能直接创建对象,它有一个直接子类RuleBasedCollator
* Collator内部提供了一个静态方法,可以获取一个它的子类对象
*
* 自然排序:实现java.lang.Comparable接口,int compareTo(Object obj)
* 定制排序
*/
public class TestString02 {
@Test
public void test12(){
String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
//希望按照拼音顺序,字典顺序
Arrays.sort(arr, Collator.getInstance(Locale.CHINA));//Locale.CHINA指定语言环境
System.out.println(Arrays.toString(arr));
}
@Test
public void test11(){
String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
//希望按照拼音顺序,字典顺序
Arrays.sort(arr, Collator.getInstance());//默认语言环境,因为我现在的操作系统的平台是中文win
System.out.println(Arrays.toString(arr));
}
@Test
public void test10(){
String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
Arrays.sort(arr);//按照自然顺序,按照每一个字符的Unicode编码值排序的
System.out.println(Arrays.toString(arr));
}
@SuppressWarnings("all")
@Test
public void test09(){
String[] arr = {"hello","chai","Java","Alice","Hi"};
//排序
//按照字母的顺序排列,不区分大小写
Arrays.sort(arr,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
String s1 = (String) o1;
String s2 = (String) o2;
return s1.compareToIgnoreCase(s2);
}
});//按照元素的自然顺序排序
System.out.println(Arrays.toString(arr));
}
@Test
public void test08(){
String[] arr = {"hello","chai","Java","Alice","Hi"};
//排序
//按照字母的顺序排列
Arrays.sort(arr);//按照元素的自然顺序排序
System.out.println(Arrays.toString(arr));
}
@Test
public void test07(){
String s1 = new String("hello");
String s2 = new String("Hello");
if(s1.compareToIgnoreCase(s2) > 0){
System.out.println(s1 + ">" + s2);
}else if(s1.compareToIgnoreCase(s2) < 0){
System.out.println(s1 + "<" + s2);
}else{
System.out.println(s1 + "=" + s2);
}
}
@Test
public void test06(){
String s1 = new String("hello");
String s2 = new String("helloworld");
/* if(s1 > s2){//不能直接使用比较运算符
}*/
if(s1.compareTo(s2) > 0){
System.out.println(s1 + ">" + s2);
}else if(s1.compareTo(s2) < 0){
System.out.println(s1 + "<" + s2);
}else{
System.out.println(s1 + "=" + s2);
}
}
@Test
public void test05(){
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equalsIgnoreCase(s2));//true
String s3 = "hello";
System.out.println(s3.equalsIgnoreCase(s1));//true
String s4 = "Hello";
System.out.println(s3.equalsIgnoreCase(s4));//true
}
@Test
public void test04(){
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2));//true,变量与变量,内容严格一致。。。
String s3 = "hello";
System.out.println(s3.equals(s1));//true,常量与变量,内容严格一致。。。
String s4 = "Hello";
System.out.println(s3.equals(s4));//false,常量与变量,内容不严格一致。。。
}
@Test
public void test03(){
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2);//false,变量和变量比较,地址值不一致;
}
@Test
public void test02(){
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2);//false,变量和常量比较,地址不一致;
}
@Test
public void test01(){
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2);//true,常量和常量比较,并且地址相同;
}
}
package com.atguigu.test08;
import org.junit.Test;
/*
* 1、面试题
* (1)String str = new String("hello");几个对象(2个)
* (2)String str1 = new String("hello");
String str2 = new String("hello");几个对象(3个)
*
* 2、拼接的结果在堆还是在常量池?
* 因为只有常量池中才是共享,==比较才为true
*
* (1)常量 + 常量 在常量池
* (2)变量 + 常量 在堆
* (3)变量 + 变量 在堆
* (4)xx.intern():在常量池
* ![]()
* 3、空字符串
* (1)""
* (2)new String()
* (3)new String("")
*
* 四种方式:
* (1)if(str != null && str.length() == 0)
* (2)if(str != null && str.equals("")){
* (3)if("".equals(str)) 推荐
* (4)if(str!=null && str.isEmpty())
*/
public class TestString03 {
@Test
public void test08(){
String str = null;
System.out.println(test(str));
String str2 = "";
System.out.println(test(str2));
}
//判断str是否是空字符串,是就返回true,不是返回false
public boolean test(String str){//方法4
if(str!=null && str.isEmpty()){
return true;
}
return false;
}
/*public boolean test(String str){//方法3
if("".equals(str)){//推荐
return true;
}
return false;
}*/
/*public boolean test(String str){//方法2
if(str != null && str.equals("")){
return true;
}
return false;
}*/
/* public boolean test(String str){//方法1
if(str != null && str.length() == 0){
return true;
}
return false;
}*/
@Test
public void test07(){
String s1; //局部变量未初始化
String s2 = null;//初始化null
String s3 = "";//空字符串常量对象
String s4 = new String();//空字符串对象
String s5 = new String("");//两个对象,一个是常量池中的,一个是堆中
// System.out.println(s1);//无法使用
// System.out.println(s2.length());//空指针异常
System.out.println(s3.length());
System.out.println(s4.length());
System.out.println(s5.length());
}
@Test
public void test06(){
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = (s1 + "world").intern();//把拼接的结果放到常量池中
String s5 = (s1 + s2).intern();
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//true
}
@Test
public void test05(){
final String s1 = "hello";
final String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+ 常量 结果在常量池中
String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中
String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//true
System.out.println(s3 == s6);//true
}
@Test
public void test04(){
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中
String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中
String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//true
}
@Test
public void test03(){
String str1 = new String("hello");
String str2 = new String("hello");
//这两行代码,几个对象?3个
}
@Test
public void test02(){
String str = new String("hello");//两个字符串对象
//一个在常量池中:hello
//另一个在堆中,String的对象
//堆中的这个字符串对象char[]的value数组,指向常量池中"hello"的char[]的value
}
@Test
public void test01(){
String str = "hello";//一个字符串对象
}
}