String常见题目及API分析

1.new 和直接创建的区别

      	String aa = "aa";
        String bb = "aa";
        //true
        System.out.println(aa == bb);
		//true
        System.out.println(aa.equals(bb));

        String ab = new String("ab");
        String bc = new String("ab");
        //false
        System.out.println(ab == bc);
		//true
        System.out.println(ab.equals(bc));

直接创建就是在常量池中创建一个"aa" 然后 aa 对象和 bb这两个对象分别去引用常量池里的这个"aa" 所以它们相等。

用new 创建就是在堆内存里创建一个新的对象,两个对象指向不同的引用,所以它们不相等。

再看equals方法,在String源码中重写了equals方法

public boolean equals(Object anObject) {
		//首先判断这两个对象是否是同一个对象,== 即比较地址
        if (this == anObject) {
            return true;
        }
        //接着比较类型,传进来的anObject是否是String类型的
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            //n代表当前String对象的char[]长度
            int n = value.length;
            //比较两个对象的长度
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                //比较char[]里每个位置的值是否相等
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

因为上面两个equals方法比较的都是字符串是否相等,所以返回的都是true

2. final不可变

在String源码中,用来存储字符的char[] 被final修饰,所以String对象是不可变的,并且class也被final修饰,说明String是不可继承的

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

这样做的好处是什么?

  1. 保证String对象的安全,防止被恶意修改
  2. 保证hash值不会被频繁修改,确保唯一性
  3. 可以实现字符串常量池,这种方法可以减少同一个值的字符串的创建,减少内存的使用

3.indexOf()方法

方法

  • public int indexOf(int ch): 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

  • public int indexOf(int ch, int fromIndex): 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

  • int indexOf(String str): 返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

  • int indexOf(String str, int fromIndex): 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

参数

  • ch – 字符,Unicode 编码。

  • fromIndex – 开始搜索的索引位置,第一个字符是 0 ,第二个是 1 ,以此类推。

  • str – 要搜索的子字符串

		String s = "aaa456ac";
        //7
        System.out.println(s.indexOf("c"));
        //3
        System.out.println(s.indexOf('4'));
        //6
        System.out.println(s.indexOf("a",4));
        //7  因为unicode编码99代表的就是c
        System.out.println(s.indexOf(99));

4.intern()方法

首先看一下常量池的概念:
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。 常量池的实现是类似与一个HashTable的实现方式。

intern方法就是Java在常量池中寻找是否有这个字符串,如果有,则返回它的引用,如果没有则在常量池中创建,并返回它的引用。

		public native String intern();
		String a = new String("abc").intern();
        String b = new String("abc").intern();
        if (a == b) {
            //a==b
            System.out.print("a==b");
        }

返回结果是a==b,说明他们是同一个引用。
String a = new String(“abc”).intern(),会先去堆中创建一个对象,然后在常量池中寻找是否有这个字符串,因为没有,所以创建一个,再返回,a指向的就是常量池那个字符串的引用,那么之前创建的那个对象就会被GC回收。
b创建的时候也是一样的,因为之前a已经在常量池中创建过了,所以直接返回引用,a和b 指向的就是同一个引用,所以他们是相等的。

5. spilt()方法

split() 方法根据匹配给定的正则表达式来拆分字符串。

public String[] split(String regex, int limit) 

参数

  • regex – 正则表达式分隔符。

  • limit – 分割的份数。

		String a = "a-a-b";
        String [] b= a.split("-");
		/**
		*a
		*a
		*b
		**/
        for (String s : b) {
            System.out.println(s);
        }
        String c = "a-a-c";
        String [] d= c.split("-",2);
        /**
        *a
        *a-c
        **.
        for (String s : d) {
            System.out.println(s);
        }

6.replaceAll()方法

replaceAll() 方法使用给定的参数 replacement 替换字符串所有匹配给定的正则表达式的子字符串。

		public String replaceAll(String regex, String replacement)

参数

  • regex – 匹配此字符串的正则表达式。

  • replacement-- 用来替换每个匹配项的字符串。

        String id = UUID.randomUUID().toString();
        System.out.println(id);
        System.out.println(id.replaceAll("-",""));

Java中常见的生成随机字符串的方法UUID,因为经常需要去除中间的"-"这个字符,所以会使用到replaceAll()这个方法。

上面的方法返回值如下

		8a9d366b-57b0-4ee2-bebb-39a74a58483a
		8a9d366b57b04ee2bebb39a74a58483a

使用空串,替换了"-"。

7.subString()

substring() 方法返回字符串的子字符串。

  • public String substring(int beginIndex)

  • public String substring(int beginIndex, int endIndex)

参数

  • beginIndex – 起始索引, 索引从 0 开始。

  • endIndex – 结束索引。

		String s = "aabbcc";
		//bbcc
        System.out.println(s.substring(2));
        //bbc
        System.out.println(s.substring(2,5));

8.String和StringBuilder,StringBuffer的区别

从几个方面来区分,可变性,线程安全性,对象引用

  1. 可变性
    String的char[]数组是final修饰的,所以是不可变的。但是StringBuilder和StringBuffer并没有被final修饰,所以是可变的

  2. 线程安全性
    String的char[]数组是final修饰的,所以也就可以理解为一个常量,所以是线程安全的。而StringBuilder并没有做同步,是线程不安全的。StringBuffer做了同步,是线程安全的。

  3. 对象引用
    String进行改变的时候,都会生成一个新的字符串,并将指针指向它。而StringBuilder和StringBuffer都是在本身的字符串上修改。

参考资料:
菜鸟教程
JavaGuide
极客时间—Java性能调优实战

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值