String引用类型的特性

目录

1.String类介绍

2.引用类型String

3.字符串的比较

4.字符串的查找

5.转化

6.字符串常量池

7.StringBuilder和StringBuffer

8.字符串的不可变性


1.String类介绍

1.C语言的时候学过字符和字符串,都是以字符数组和字符指针的方式储存的,例如

char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};

以'\0'作为字符串结束的标志

以上代码可以直接写成这样也是一样的结果:

不指定长度,直接初始化

char site[] = "RUNOOB";

Java的String类根据面向对象的思想来说是一个类,有自己的构造方法,成员变量,以及成员方法

储存时有以下方式:

String str = "huaweilin";//在常量池中寻找对象;把对象的地址值赋值给str

String str = new String("huaweilin");在堆上创建对象,str指向对象存储对象的地址值,value值为huaweilin;

 char[] array = {'h','u','a','w','e','i','l','i','n'}//利用字符数组作为构造方法的参数,跟第二种方法差不多,也是需要在堆上创建对象

2.引用类型String

上面学会初始化String类,下面了解一个很重要的概念,就是字符串是怎么判断相等或者比较的

public static void main(String[] args) {
int a = 10;
int b = 20;
int c = 10;
// 对于基本类型变量,==比较两个变量中存储的值是否相同
System.out.println(a == b); // false
System.out.println(a == c); // true
// 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = new String("world");
String s4 = s1;
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // false
System.out.println(s1 == s4); // true
}

s1和s2和s3都是在堆上创建对象

结果s1的值不等于s2

s4赋值给s1反而两个相等

是因为String类的对象s1和s2和s3不是存储内容而是存储对象的地址值

而s4把他的地址值赋给了s1,所以两者相等,这里注意==比较的是两个变量储存的值是否相同

所以如果是要比较两个字符内容是否相同应该调用String类的equals()和compareTo()方法:

3.字符串的比较

一.boolean equals()方法

String str = new String("huaweilin");
String s1 = "huaweilin";
System.out.println(str.equals(s1));//true

虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true

equals()都是逐个字符进行比较的,返回值为Boolean;源码如下:

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;
    }

二.int compareTo()方法:

String s1 = new String("abc");
String s2 = new String("ac");
System.out,println(s1.compareTo(s2));/*逐个字符进行比较,返回他们字符的差值,比如第二位b!=c,所以就是b的ASCII码值减去c的ASCII码值等于-1*/

String s3 = new String("abc");
System.out,println(s1.compareTo(s3));//相同返回值为0

String s4 = new String("abcdef");/*返回-3,这种情况是如果前几个字符都比较相同,然后再进行下一个比较时超出了两个字符串的最小长度,就会返回两个字符串的差值*/

以上结果出现的原因由于compareTo()方法的源码:(源码需要自己调用方法时按住ctrl键点一下就会出现了)

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

有一个方法与compareTo类似,叫compareToIgnoreCase(String str)方法,他可以比较时忽略大小写,大写和小写就被当做相同,大小写默认为相同的字符

public static void main(String[] args) {
String s1 = new String("abc");
String s2 = new String("ac");
String s3 = new String("ABc");
String s4 = new String("abcdef");
System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}

4.字符串的查找

一.获取字符串里的字符;char charAt(int index)

public static void main(String[] args){

String s = new String("11byte");
for(int i = 0,i < s.length(); i++){
char[] x = s.charAt(i);

}

二.根据下标找对应的字符或字符串,或者根据字符或者字符串找对应的下标

char charAt()方法                               indexOf()方法                    lastindexOf()方法 

public static void main(String[] args) {
String s = "aaabbbcccaaabbbccc";String底层是用数组来存储字符串的,所以下标需从0开始
System.out.println(s.charAt(3)); // 'b' 获取3下标的字符
System.out.println(s.indexOf('c')); // 6  获取第一次出现c的下标
System.out.println(s.indexOf('c', 10)); // 15  获取从10下标开始,第一次出现c的下标
System.out.println(s.indexOf("bbb")); // 3   获取第一次出现bbb字符串的下标
System.out.println(s.indexOf("bbb", 10)); // 12  获取从10下标开始,第一次出现bbb字符串的下标
System.out.println(s.lastIndexOf('c')); // 17    从后往前数,返回第一次出现c的下标
System.out.println(s.lastIndexOf('c', 10)); // 8   从下标10往前数,第一次出现c的下标
System.out.println(s.lastIndexOf("bbb")); // 12    后往前数,第一次出现字符串bbb的下标,
System.out.println(s.lastIndexOf("bbb", 10)); // 3  从下标10往前数,第一次出现bbb的下标

注意的是:

indexOf()和lastindexOf()对于获取字符串的位置都是以字符串的开头下标作为返回值,没有找到则返回-1

5.转化

1.数值和字符串转化

valueOf()方法,把数字转成字符串,String.valueOf(int i)源码如下:

String sw = String.valueOf(11);
 System.out.println(sw);

用parseInt()方法,像Integer,Double要用他们的包装类调用此方法

int a = Integer.parseInt("12");
        System.out.println(a);//12

double b = Double.parseDouble("11.77");
        System.out.println(b);//11.77

用valueOf()转字符串为数字也可以,下面看看Integer.valueOf(int i)的源码:

本质上还是用的parseInt方法把字符串转化为了数字,上面的radix是进制的意思

6.字符串常量池

只要是双引号引起来的元素,都要放在常量池,且只有一份

 当使用String s1 = "hello"的时候,现在常量池里找,找到了,就把该字符串的引用赋值给s1;

哈希桶存储了String对象的地址值,String对象里又存储着字符串的地址值,按照上面的图仔细感受下面代码的不同

public static void main(String[] args) {
String s1 = "hello";//1
String s2 = "hello";//2
String s3 = new String("hello);//3

当第1条语句执行时,会去找常量池中有没有"hello"这个字符串,如果有则把存储"hello"字符串哈希表里的地址赋给s1,没有则会把"hello"进入到常量池里;当第二条语句执行时,"hello"已经存在常量池里,则直接把引用赋值给s2,当第三条语句执行时,会创建一个新的对象,这时的引用跟前面的就不一样了,但他还是会去常量池寻找字符串,如果有则会把字符串的引用直接赋值给s3.

所以这里注意引用的不同:s1和s2都是直接在StringTable里找,找到了就把StringTable上的引用赋值给变量,没找到就把元素入常量池,在常量池构建一个哈希表

s3在new了对象之后在堆上开辟了一个新的空间,也是先去常量池找,如果找到相同的元素则把字符串的引用赋值给s3

7.StringBuilder和StringBuffer

StringBuilder和StringBuffer不是String,是单独出来的一个类,便于对字符串进行操作

方法如下:

StringBuff append(String
str)
在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、
double、float、int、long、Object、String、StringBuff的变量
char charAt(int index)获取index位置的字符
int length()获取字符串的长度
int capacity()获取底层保存字符串空间总的大小
void ensureCapacity(int
mininmumCapacity)
扩容
void setCharAt(int index,
char ch)
将index位置的字符设置为ch
int indexOf(String str)返回str第一次出现的位置
int indexOf(String str, int
fromIndex)
从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str)返回最后一次出现str的位置
int lastIndexOf(String str,
int fromIndex)
从fromIndex位置开始找str最后一次出现的位置
StringBuff insert(int
offset, String str)
在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer
deleteCharAt(int index)
删除index位置字符
StringBuffer delete(int
start, int end)
删除[start, end)区间内的字符
StringBuffer replace(int
start, int end, String str)
将[start, end)位置的字符替换为str
String substring(int start)从start开始一直到末尾的字符以String的方式返回
String substring(int
start,int end)
将[start, end)范围内的字符以String的方式返回
StringBuffer reverse()反转字符串
String toString()将所有字符按照String的方式返回

public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder("hello");
StringBuilder sb2 = sb1;
// 追加:即尾插-->字符、字符串、整形数字
sb1.append(' '); // hello
sb1.append("world"); // hello world
sb1.append(123); // hello world123
System.out.println(sb1); // hello world123
System.out.println(sb1 == sb2); // true
System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h
System.out.println(sb1.length()); // 获取字符串的有效长度14
System.out.println(sb1.capacity()); // 获取底层数组的总大小
sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123
sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123
System.out.println(sb1);
System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置
System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置
sb1.deleteCharAt(0); // 删除首字符
sb1.delete(0,5); // 删除[0, 5)范围内的字符
String str = sb1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
System.out.println(str);
sb1.reverse(); // 字符串逆转
str = sb1.toString(); // 将StringBuffer以String的方式返回
System.out.println(str);
}


从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可
以修改。频繁修改字符串的情况考虑使用StringBuilder。
注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:
String变为StringBuilder: 利用StringBuilder的构造方法或append()方法
StringBuilder变为String: 调用toString()方法
1. String、StringBuffer、StringBuilder的区别
String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
StringBuffer与StringBuilder大部分功能是相似的
StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
 

 以下面为例介绍

String str = new String("ab"); // 会创建多少个对象
String str = new String("a") + new String("b"); // 会创建多少个对象

第一个创建对象ab,创建了一个对象

第二个创建了对象a和对象b以及StringBuilder类对象ab,一共创建了3个对象

字符串在拼接时会创建一个StrimgBuilder类的对象,最后再通过toString()方法转变成字符串.

8.字符串的不可变性

String是一种不可变对象,字符串的内容不可改变

源码中对于String类的描述:

String类无论在声明时直接引用,还是new一个对象,里面的字符实际都保存在内部维护的value字符数组中:final表明value中引用该数组的地址值不能被修改且只有一份,并且由于private,外部类无法获取value的值,但引用的数组里面的值是可以通过数组下标的方式改变的,比如说:

public class Example{
    String str = new String("good");
    char[ ] ch = { 'a' , 'b' , 'c' };
    public static void main(String args[]){
        Example ex = new Example();//给类创建对象,包含了类里面的属性
        ex.change(ex.str,ex.ch);//给方法传参数
        System.out.print(ex.str + " and ");
        System.out.print(ex.ch);
    }
    public void change(String str,char ch[ ]){
        str = "test ok";//final修饰无法改变引用的值(无法改变value[]数组的地址值)
        ch[0] = 'g';//数组内部可利用数组下标进行修改
    }
}

输出结果为good and gbc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值