您当前的位置: 首页 >  Java

Charge8

暂无认证

  • 1浏览

    0关注

    447博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java String、StringBuffer和StringBuilder类

Charge8 发布时间:2019-07-26 16:32:04 ,浏览量:1

常量池:专门存储常量的地方,包括了类,方法,接口中的常量以及字符串常量。

     编译常量池:  把字节码加载斤JVM的时候,存储的是字节码的相关信息.(不研究)

     运行常量池:  存储常量数据(研究).

字符序列:把多个字符按照一定得顺序排列起来。

字符串:把多个字符串串联起来.

字符串的分类:

    1)不可变的字符串:

       String:当前对象创建完毕之后,该对象的内容(字符序列)是不能改变的,一旦内容改变就是一个新的对象.

     2)可变的字符串:

       StringBuilder/StringBuffer:当对象创建完毕之后,该对象的内容可以发生改变,当内容发生改变的时候,对象保持不变.

提示:String、StringBuffer和StringBuilder都实现了CharSequence接口,因此CharSequence可认为是一个字符串的协议接口。

一、java.lang.String

        String类:表示不可变的字符串,当前对象创建完毕之后,该对象的内容(字符序列)是不能改变的,一旦内容改变就是一个新的对象.

       字符串的本质(底层是什么其实就是char[]),char表示一个字符。比如:

         String  str = “ABCDEFG”;    //定义一个字符串对象,等价于

         char[] cs = new char[]{'A','B','C','D','E','F','G'};

       深入理解参考文章:深入理解Java中的String(大坑)

1、String对象的创建:

       1)直接赋一个字面量:       String   str1  =  “ABCD”;

       2)通过构造器创建:          String   str2  =  new String(“ABCD”);

面试题:两种方式有什么区别,分别在内存中如何分布?

        /**
         *  最多创建一个String对象,最少不创建String对象.
         *  如果常量池中,以及存在"ABCD",那么str1直接引用,此时不创建String对象;否则,先在常量池先创建"ABCD"内存空间,再引用.
         */
        String str1 = "ABCD";
        /**
         *  最多创建两个String对象,至少创建一个String对象.
         *  new关键字:绝对会在堆空间中创建内存区域.  所以至少创建一个String个对象.
         */
        String str2 = new String("ABCD");

2、String对象的空值 和 判断字符串对象非空或为空

public class StringUtils {
    /**
     * 判断字符串为空
     * @param str
     * @return true - 为空,false - 非空
     */
    public static boolean isBlank(String str) {
        return !isNonBlank(str);
    }

    /**
     * 判断字符串为非空
     * @param str
     * @return true - 非空,false - 为空
     */
    public static boolean isNonBlank(String str) {
        if (str != null && !"".equals(str.trim())) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
        /**
         *  String对象的空值:
         *      引用不能为空(null) 或者 字符内容不能为空字符串("")
         */
        // 没有初始化,没有分配内存空间
        String str1 = null;
        // 已经初始化,分配内存空间,不过没有内容
        String str2 = "";
        String str3 = " ";

        System.out.println(StringUtils.isNonBlank(str1)); // false
        System.out.println(StringUtils.isNonBlank(str2)); // false
        System.out.println(StringUtils.isNonBlank(str3)); // false
        System.out.println(StringUtils.isBlank(str3)); // true
    }
}

3、字符串的比较操作:

      1)使用 == 号:          只能比较引用的内存地址是否相同.

      2)使用equals方法:   在Object类中和”==”号相同,建议子类覆盖equals方法去比较自己的内容。String类覆盖了equals方法,所以比较的是字符内容.

面试题:String对象比较

    public static void main(String[] args) {
        String str1 = "ABCD";
        String str2 = "A" + "B" + "C" + "D";
        String str3 = "AB" + "CD";
        String str4 = new String("ABCD");
        String temp = "AB";
        String str5 = temp + "CD";
        String str6 = getAB() + "CD";
        /**
         * 面试题:String对象比较:
         *   1、单独使用 "" 引号创建的字符串都是直接量,编译期就已经确定存储到常量池中;
         *   2、使用 new String("") 创建的对象会存储到堆内存中,是运行期才创建;
         *   3、使用只包含直接量的字符串连接符如 "aa" + "bb" 创建的也是直接量,编译期就能确定,已经确定存储到常量池中(str2和str3);
         *   4、使用包含 String直接量(无final修饰符)的字符串表达式(如"aa" + s1)创建的对象是运行期才创建的,存储在堆中;
         *   5、通过变量/调用方法去连接字符串,都只能在运行时期才能确定变量的值和方法的返回值,不存在编译优化操作.
         */
        System.out.println(str1 == str2); // true
        System.out.println(str1.equals(str2)); // true
        System.out.println(str1 == str2); // true
        System.out.println(str1 == str3); // true
        System.out.println(str1 == str4); // false
        System.out.println(str1 == str5); // false
        System.out.println(str1 == str6); // false
    }

    private static String getAB() {
        return "AB";
    }

4、String类中的常用方法

1)获取字符串信息

    • charcharAt(int index)

      返回 char指定索引处的值。

      intindexOf(String str)

      返回指定子字符串第一次出现的字符串内的索引。

      intindexOf(String str, int fromIndex)

      返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。

       

      booleanisEmpty()

      返回 true如果,且仅当 length()0

      intlastIndexOf(String str)

      返回指定子字符串最后一次出现的字符串中的索引。

      intlastIndexOf(String str, int fromIndex)

      返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。

      intlength()

      返回此字符串的长度。

       

      booleanstartsWith(String prefix)

      测试此字符串是否以指定的前缀开头。

      booleanstartsWith(String prefix, int toffset)

      测试在指定索引处开始的此字符串的子字符串是否以指定的前缀开头。

      booleanendsWith(String suffix)

      测试此字符串是否以指定的后缀结尾。

      Stringtrim()

      返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。

    public static void main(String[] args) {
        String str1 = "ABCD";
        System.out.println(str1.charAt(1)); // B
        System.out.println(str1.indexOf("B")); // 1
        System.out.println(str1.isEmpty()); // false. 注意 str1 != null
        System.out.println(str1.lastIndexOf("D")); // 3
        System.out.println(str1.length()); // 4
        System.out.println(str1.startsWith("A")); // true
        System.out.println(str1.endsWith("D")); // true
    }

2)字符串比较判断

    • booleanequals(Object anObject)

      将此字符串与指定对象进行比较。

      booleanequalsIgnoreCase(String anotherString)

      将此 String与其他 String比较,忽略大小写。

        String str1 = "ABCD";
        String str2 = "abcd";
        System.out.println(str1.equals(str2)); // false
        System.out.println(str1.equalsIgnoreCase(str2)); // true

3)字符串大小写转换

    • StringtoLowerCase()

      将所有在此字符 String使用默认语言环境的规则,以小写。

      StringtoUpperCase()

      将所有在此字符 String使用默认语言环境的规则大写。

        String str1 = "AbcD";
        System.out.println(str1.toUpperCase()); // ABCD
        System.out.println(str1.toLowerCase()); // abcd
二、StringBuffer 与 StringBuilder

          StringBuffer JDK1.0版本提供的类,线程安全,做线程同步检查, 效率较低。

          StringBuilder JDK1.5版本提供的类,线程不安全,不做线程同步检查,因此效率较高,官方推荐使用

  在使用上,二者的方法大部分都是一样的,使用下 StringBuilder类,覆盖了toString()方法

    • StringBuilderappend(String str)

      将指定的字符串附加到此字符序列。

      intcapacity()

      返回当前容量。

      StringBuilderdelete(int start, int end)

      删除此序列的子字符串中的字符。

      StringBuilderdeleteCharAt(int index)

      删除 char在这个序列中的指定位置。

      intindexOf(String str)

      返回指定子字符串第一次出现的字符串内的索引。

      StringBuilderinsert(int offset, String str)

      将字符串插入到此字符序列中。

      intlastIndexOf(String str)

      返回指定子字符串最右边出现的字符串内的索引。

      intlength()

      返回长度(字符数)。

      StringBuilderreplace(int start, int end, String str)

      用指定的String中的字符替换此序列的子字符串中的 String

      StringBuilderreverse()

      导致该字符序列被序列的相反代替。

      Stringsubstring(int start)

      返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。

      Stringsubstring(int start, int end)

      返回一个新的 String ,其中包含此序列中当前包含的字符的子序列。

      StringtoString()

      返回表示此顺序中的数据的字符串。

        StringBuilder sb = new StringBuilder();
        sb.append("aAAbBB").append("CccdDD");

        System.out.println(sb); // aAAbBBCccdDD
        System.out.println(sb.capacity()); // 16
        System.out.println(sb.deleteCharAt(2)); // aAbBBCccdDD
        System.out.println(sb.indexOf("a")); // 0
        System.out.println(sb.length()); // 11
        System.out.println(sb.toString()); // aAbBBCccdDD
        System.out.println(sb.replace(0, 2, "==")); // ==bBBCccdDD
        System.out.println(sb.substring(2, sb.length())); // bBBCccdDD
        System.out.println(sb.reverse()); // DDdccCBBb==
StringBuIlder 类的扩容机制:默认长度均为 16

        

JDK 1.8中,查看 AbstractStringBuilder 父类源码

  

可以看出,扩容的大小是新字符串的长度的2倍,然后再加上2。

为什么要再加上2呢?

    来自网上一个合理的回答:在使用StringBuilder的时候,append()之后,我们一般会在后面在加上一个分隔符,例如逗号,也就是再加上一个char,而char在java中占2个字节,避免了因为添加分隔符而再次引起扩容。不得不佩服JDK开发者的高瞻远瞩!

 

ends ~

关注
打赏
1664721914
查看更多评论
立即登录/注册

微信扫码登录

0.0387s