Java数据类型:String

内容:创建String 的方式,String比较方式,String类,实例对象的小区别,一些工具包

首先,查看String源码:有几个比较重要的点

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    }

class被final修饰,这意味着String不能被继承,也不能使用Object instanceof String得到bool;

    private final char value[];

value对应的是String实例出来的具体的值对应的char[],被final修饰,意味着该值不能被修改(但是可以重新给实例对象指向新的地址)

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重写equlas()equals是在不为空的情况下比较char的长度,长度相同 再一一比较char

    public String substring(int beginIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }

String 类下的方法substring 我们可以看到返回的值 是new String的,所以使用substring的时候并不会影响原对象本身。其他的方法也是如此。

在Java中有字符串常量池举个栗子
下面是对字符串“hello”的几种声明方式,发现value都是一样的。但是用"=="来进行比较的时候,前面三个是true.
最后一个与前面任何一个在栈内地址都不相同。
在这里插入图片描述

  • 字符串常量池是为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串常量池,该池是Java堆内存中一个特殊的存储区域。
String str2 = "hell"+"o";
String str3 = "hello";

上面这两种在JVM字符串常量池中为什么不是创建了三个"hell",“o”,"hello"呢,因为JVM对字符串这个特殊的数据进行了特殊的处理。上面两种声明在字符串常量池中申请的是同一个。

  • new String(“hello”);在字符串常量池中与上面几种申请的其实是同一处地址,但是为什么与前面几种方式的任意一种使用==的时候返回false。虽然在常量池中是同一个值,但是对应对象的"栈"却是不同的,new关键字创建的对象是开辟内存新的地址。
    StringBuffer
    是我们常用的字符串处理的一个类。
 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{}

该类也是被final修饰的,意味着不能被继承。

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

在他的append字符串拼接值的方法是被synchronized 意味着该类在多线程中是线程安全的。

StringBuilder

public final class StringBuilder
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{}

StringBuilder同样被final修饰,该类也是不能被继承的最终。

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

没有被锁锁着,所以多线程下“写”不安全。
String对象被传值

    private static void changesValue(String str){
        str = "hello zhangsan";
    }
    public static void main(String[] args) {
        String lisi = "lisi";
        changesValue(lisi);
        System.out.println(lisi);
        lisi = "hello wangwu";
        System.out.println(lisi);
    }

结果:

lisi
hello wangwu

观察上面的结果可以发现,String为不可变类型,在方法内对String修改的时候,相当于传入的是String的副本,并不是对象本身,所以修改之后也只是修改备份,并不会修改对象本身的值。
但是使用StringBuffer或者StringBuilder的时候是可以进行修改的,因为StringBuffer下对应的具体的值并没有被final修饰,在本文的开头就看到String类下的value是被fianl修饰的。

private transient char[] toStringCache;//StringBuffer
private final char value[];//String

Utils
我常使用的String工具类:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>

里面有判空,去空格等处理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章