Java基础16-String类(Buffer和Builder)

一、String类的本质是什么?

 

 上边代码竟然输出的是一样的,我们进到String类的源码中

其实,字符串的本质就是字符数组, String 其实就是char数组的封装

二、字符串的分类

1.不可变得字符串String:当前对象创建完毕之后,该对象的内容是不能改变的,一旦内容改变就是一个新的类
2.可变的字符串:StringBuffer/StringBuilder,当前内容创建完毕之后,该对象的内容可以发生改变,内容改变时对象不变

 

我们输出上边两段代码,虽然引用名称相同,但是当我们重新赋值时,它的hashcode发生了变化,也就是说,str在内存中的地址发生了变化,str="索隆"虽然与str="路飞"名称相同,但实则是两个变量,也就是重新在内存中(常量池)开辟了一块空间

三、String对象的创建

1.直接赋一个字面量:
String str1="abcd";
2.通过构造器
String str2=new String("abcd");

 这两者有什么区别呢?别着急,请看下文

要说这个问题,那就必须要来了解一个内存中的区域,常量池

常量池:专门存储常量的地方,都指的方法区中
* 编译常量池:把字节码加载进jvm时,存储的是字节码的相关信息(不研究)
* 运行常量池:存储常量数据(研究)

通过这个问题我们就来揭晓 

String str4="abcd"和String str5=new String("abcd")的区别?

 

以上代码创建了几个String对象呢?

str4最多创建一个,最少不创建,如果常量池中已经存在abcd,直接引用不创建
str5最多创建两个String对象,至少创建一个,new关键字绝对会在堆空间创建内存区域,所以至少创建一个

我们再回头看第二种的hashcode不同的问题,实际上就是不同的值在常量池中开辟的空间其地址不同,当值变了。也就是这个引用指向的地址发生了变化

str和str10的hashcode竟然是一样的! 这下我们就明白了吧,只要是值相同,不管叫什么名字都指向的是同一个地址。

 

 

 

四、String对象的空值
1.表示引用为空(null):没有初始化,没有分配内存空间
String str3=null;
2.内容为空,已经初始化,分配了内存空间,不过没有内容
五、判断字符串非空
1.引用不能为空(null)
2.字符内容不能为空字符串
六、字符串的比较操作
1.使用==运算符,只能比较引用的内存地址是否相同
2.使用equals方法:在object类中和==相同,建议子类覆盖equals方法去比较内容
七、字符串的比较

1.单独使用""创建的字符串都是直接量,编译器已经确定存储到常量池中
2.使用new String("")创建的对象会存储到堆内存中,运行时期才创建
3.使用只包含直接量的字符串连接符如"aa"+"bb"创建的也是直接量,编译器就能确定,已经存储到常量池中
4.使用包含String直接量(无final修饰符)的字符串表达式(如"aa"+s1)创建的对象是运行期才创建的,存储在堆中

 

 

八、常用方法联系

 

    //一、String练习,获取hello开头的文件名的后缀名
    String filename="abc.java;hello.java";
    //1.一份好来分割字符串,获取每个的名称和拓展名
    String[] name=filename.split(";");
    for (String names : name) {
        System.out.println(names);
        //2.判断每个名称是否以hello开头
        if(names.startsWith("hello")) {
            //3.获取文件名的后缀名,最后一个点的后半截
            names.lastIndexOf(".");
            //截取字符串
            System.out.println(names.substring(names.lastIndexOf(".")));
        }
    }
    //二、单词首字母大写
    String str7="willabcad";
    //1.获取第一个字符,转换为大写
    String first=str.substring(0, 1).toUpperCase();
    //2.截取字符串从1到最后
    String last=str.substring(1);
    System.out.println(first+last);
    //trim方法消除前后空格
    System.out.println(" ab cd ".trim().length());
    System.out.println(" ab cd ".length());

九、StringBuilder和StringBuffer

先来看一个小例子

    //使用String/StringBuilder和StringBuffer拼接3万次
    long begin=System.currentTimeMillis();
    String str8="";
        for(int i=0;i<30000;i++) {
            str8+=i;
        }
        long end=System.currentTimeMillis();
        System.out.println(end-begin);
        //string做字符串拼接性能很低,原因是每次都要new新的对象
        StringBuffer sb=new StringBuffer("");
        long begin2=System.currentTimeMillis();
            for(int i=0;i<30000;i++) {
                sb.append(i);
            }
            long end2=System.currentTimeMillis();
        System.out.println(end2-begin2);
        StringBuilder sbr=new StringBuilder("");
        long begin3=System.currentTimeMillis();
        for(int i=0;i<30000;i++) {
            sbr.append(i);
        }
        long end3=System.currentTimeMillis();
    System.out.println(end3-begin3);
        }

经过测试,sbr耗时最短,sb次之,所以拼接字符串使用stringbuffer或者stringbuilder

StringBuilder和StringBuffer都表示可变的字符串,功能方法相同
唯一的区别;
stringbuffer:使用了synchronized修饰符,表示同步,再多钱程并发时保证线程安全
stringbuilder:没有synchronized,不安全
常用操作
链式编程
append,deleteCharAt

posted @ 2018-05-07 16:58  LuckyGJX  阅读(351)  评论(0编辑  收藏  举报