String类

1.常见字符串的三种方法

public class TestDemo {
    public static void main(String[] args) {
        String name="tjg";
        System.out.println(name);
        String name1=new String("tjg1");
        System.out.println(name1);
        char[] array={'a','b','c'};
        String name3=new String(array);
        System.out.println(name3);
    }
}

在java中,不像C语言,不是通过/0来判断字符串结束,而是通过长度来判断字符串的结束。

1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

先写代码:

String s1=new String("hello");
String s2=new String("world");
String s3=s1;

具体的情况就二如同上图一般。但是虽然s1和s3指向同一个地址,之后都是指向的hello,但是在Java当中的字符串市字符串常量值,是不可以进行修改的。

2. 在Java中“”引起来的也是String类型对象

// 打印"hello"字符串(String对象)的长度

System.out.println("hello".length()); 

2.String对象的比较

字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4种方式:

 ==比较是否引用同一个对象

public static void main(String[] args) {
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
        String s3=new String("hello");
        String s4=new String("hello");
        System.out.println(s3==s4);
    }

前面的结果是true,但是后面的结果是flase,为什么呢?在str1和2里面的内容是一样的,所以结果是true,但是在s3和s4之中,只要是new了,就会开辟一个新的空间,s3和s4是存的不同对象的地址,所以结果是flase。那怎么比较两个里面的内容呢?代码如下:

System.out.println(s3.equals(s4));

这个的结果是用来比较里面的内容是否相同,但是如果是object类的话是不一样的,因为object用equal进行比较的时候,也是比较的地址,除非你重写比较方法。

你可以使用的比较方法:

System.out.println(s3.equals(s4));
System.out.println(s3.compareTo(s4));

但似乎用一个特殊的比较方法:我下面先来展示一下代码:

System.out.println(str1==str2);
        String s3=new String("hello");
        String s4=new String("Hello");
        System.out.println(s3.equalsIgnoreCase(s4));

这个equalsIgnoreCase是忽视大小写,结果也是true。

3.字符串查找

此时的参数 需要是一个合法下标

public static void main(String[] args) {
        String str="hello";
        char ch=str.charAt(1);
        System.out.println(ch);
    }

这个是用来显示某个下标的位置是啥。

下面还有一个办法来找某个字符或者字符串所在的位置,代码如下:

    public static void main(String[] args) {
        String str="hello";
        //char ch=str.charAt(1);
        int ch=str.indexOf("l");
        System.out.println(ch);
    }

如果找不到的话会返回-1;下面我用一个图来展示一下这些重载的方法:

4.转化

1.数值和字符串的相互转换

public static void main(String[] args) {
        double a=10.99;
        String str=String.valueOf(a);
        System.out.println(str);

        String str1="1223";
        int i=Integer.valueOf(str1);
        i+=1;
        System.out.println(i);
        int ret2=Integer.parseInt(str1);
        i+=1;
        System.out.println(i);
    }

2.大小写转换

public class TestDemo {
    public static void main(String[] args) {
        String s1="hello";
        String s2="Hello";
        System.out.println(s1.toUpperCase());
        System.out.println(s2.toLowerCase());
        System.out.println(s1);
    }
}

这是代码,但是当你输出你会发现,你不是把s1的小写改成大写了吗,但是为什么输出的s1还是小写,其实这个代码更改可以说是新创了一个空间来存放更改之后的结果,而不是直接更改s1.这个只是把大写字面或者小写字母进行了更改,如果里面放入了其他的不会进行变化。

3.字符串和数组之间的转换

public class TestDemo {
    public static void main(String[] args) {
        String s1="hello";
        char[] chars=s1.toCharArray();
        System.out.println(Arrays.toString(chars));

        String s2=new String(chars);
        System.out.println(s2);
    }

4.格式化

String s = String.format("%d-%d-%d", 2019, 9,14);
System.out.println(s);

5.字符串的替换

public static void main(String[] args) {
        String str1="ababcabcd";
        String s2=str1.replace("a","e");
        System.out.println(s2);
    }

在Java中所有的对字符喜欢的操作都不会对原来的字符串进行操作,因为字符串是不可变的。

6.字符串的拆分

先简单的演示一下,一个字符用“ ”来拆分的代码:

String str1="ni hao ya";
        String[] s1=str1.split(" ");
        System.out.println(Arrays.toString(s1));
        for (String s:s1) {
            System.out.println(s);
        }

如果又有=又有空格那怎么办呢?代码如下:

        String str2="ni=shi zhen=sha";
        String[] s2=str2.split(" ");
        for (String s:s2) {
            String[] s3=s.split("=");
            for (String s4:s3) {
                System.out.println(s4);
            }
        }

或者这样:

        String[] s5=str2.split(" |=");
        for (String s:s5) {
            System.out.println(s);
        }

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义.

代码示例: 拆分IP地址

        String s6="192.116.1.1";
        String[] s7=s6.split("\\.");
        for (String s:s7) {
            System.out.println(s);
        }

注意事项:

1. 字符"|","*","+"都得加上转义字符,前面加上"\\".

2. 而如果是"\",那么就得写成"\\\\".

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

7.字符串的截取

public class TestDemo {
    public static void main(String[] args) {
        String str="ababcabcd";
        String s1=str.substring(2);
        String s2=str.substring(2,5);
        System.out.println(s1);
        System.out.println(s2);
    }
}

在substring里面如果只有一个数字,代表是从该数字下标开始截取,如果是有两个数字代表是从前面一个数字开始,后面一个数字结束,左闭右开。范围必须合法

注意事项:

1. 索引从0开始

2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

8.其他操作方法

    public static void main(String[] args) {
        String s1="   ab abc   ";
        String s2=s1.trim();
        System.out.println(s2);
    }

trim去除字符串左右两边的空格,但是中间的空格不会去除。

    public static void main(String[] args) {
        String s1="abcDe";
        String s2=s1.toLowerCase();
        String s3=s1.toUpperCase();
        System.out.println(s2);
        System.out.println(s3);
    }

toLowerCase:大写全部转换成小写,

toUpperCase:小写全部转换成大写。

9.常量池

public class TestDemo {
    public static void main(String[] args) {
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
        String str3=new String("hello");
        System.out.println(str1==str3);
    }
}

当这个代码走完你会产生疑问,为什么str1=str2,但是后面就不相等呢?
当你看完下面你就会知道具体的原因是什么。

首先要先引入一个概念叫做常量池,StringTable【常量池】,StringTable是哈希表。

为什么会有常量池这个概念产生呢?主要的目的就是为了使程序的运行速度更快、更节省内存,下面先简单的了解认识一下三个池:
1. Class文件常量池:每个.Java源文件编译后生成.Class文件中会保存当前类中的字面常量以及符号信息

2. 运行时常量池:在.Class文件被加载时,.Class文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都有一份

3. 字符串常量池

字符串常量池(StringTable)

字符串常量池在JVM中是StringTable类,实际是一个固定大小的HashTable

注意:

1. 在JVM中字符串常量池只有一份,是全局共享的

2. 刚开始字符串常量池是空的,随着程序不断运行,字符串常量池中元素会越来越多

3. 当类加载时,字节码文件中的常量池也被加载到JVM中,称为运行时常量池,同时会将其中的字符串常量保存在字符串常量池中

4. 字符创常量池中的内容:一部分来自运行时常量池,一部分来自程序动态添加

注意一下我上面加粗部分的内容,一开始常量池也是空的,是随着程序的不断运行,使得字符串常量池里面的元素越来越多。

 

 下面展示一下用new来创建对象时候的过程。

 那怎么才能让我一开始的那个str1=str3呢?

下面我们讲到的intern方法就可以解决这个问题,通过这个方法,可以使得把new的对象也放入到常量池中(前提是目前常量池中没有这个)。

public class TestDemo {
    public static void main(String[] args) {
        char[] ch={'h','e','l','l','o'};
        String str3=new String(ch);
        str3.intern();
        String str1="hello";
        String str2="hello";
        System.out.println(str1==str2);
        System.out.println(str1==str3);
    }
}

10.字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

1. String类在设计时就是不可改变的,String类实现描述中已经说明了

 String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:

1. String类被final修饰,表明该类不能被继承

2. value被修饰被final修饰,表明value自身的值不能改变,即不能引用其它字符数组,但是其引用空间中的内容可以修改。

2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象

【纠正】网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。

这种说法是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。

final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容是可以修改的。

11 字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。

public static void main(String[] args) {
        String str="hello";
        str+="world";
        System.out.println(str);
    }

 借助StringBuilder和StringBuffer

12.StringBuilder和StringBuffer

    public static void main(String[] args) {
        StringBuffer str1=new StringBuffer("hello");
        StringBuffer str2=str1;
        str1.append(" ");
        str1.append("world");
        System.out.println(str1);
        System.out.println(str2);
    }

使用StringBuilder和StringBuffer不会进行新的创建,会直接在原有的上面进行删改。

从上述例子可以看出:String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

String变为StringBuilder: 利用StringBuilder的构造方法或append()方法

StringBuilder变为String: 调用toString()方法。

String、StringBuffer、StringBuilder的区别

String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

StringBuffer与StringBuilder大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值