Java基础笔记(十一)—— 字符串与数组

字符串的声明与初始化主要两种:String s1=new String("abc");      或      String s2="abc";

String s1="abc";  //(1)在常量区里存放了一个"abc"字符串对象
String s2="abc";   //(2)s2引用常量区中的对象,不会创建新对象
String s3=new String("abc");   //(3)在堆中创建新对象
String s4=new String("abc");   //(4)在堆中又创建新对象

1.

JVM中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用。创建字符串常量 String s="abc";,会首先在字符串常量池中查找是否已经有相同的字符串被定义(由String类equals(Object obj)方法的返回值来判断)。若已经定义,则直接获取对其的引用,此时不需要创建新的对象;若没有定义,则首先创建这个字符串对象,然后把它加入到字符串池中,再将它的引用返回。

2.

new String("abc")会调用String类的构造函数public String(String original){},传入一个字符串常量,所以此语句相当于“abc”和new String()两个操作。若字符串常量池中不存在“abc”,则会创建一个字符串常量"abc",并将其添加到字符串池中;若存在,则不创建,然后new String()会在堆中创建一个新的对象(只要用到new总会生成新的对象),所以s3与s4指向的是堆中不同的String对象,地址也就不同。即两个内容相同的字符串对象"abc",它们在内存中的地址是不同的。

例:new String("abc")创建几个对象?

答:一个或两个。如果常量池中原来有"abc",那么只创建一个对象;如果常量池中没有字符串"abc",那么就会创建两个对象(一个常量区的"abc"字符串对象,一个在堆中new的String对象)。

3.

由于String是不可变类,一旦创建好了就不能被修改,因此String对象可以被共享而且不会导致程序的混乱。(不可变,就是其值不可变,如果想要拥有新值,只能再创建,开辟一块新的内存空间来存储。)

4.

String s;    

s=null; //s是一个字符串类型的引用,它不指向任何一个字符串。

s=" ";   //s是一个字符串类型的引用,它指向另外一个字符串,这个字符串的值为" ",即空字符串。

5.

"=="运算符用来比较两个变量对应的内存中存储的数值是否相同。

String s=new String();  变量s占用一块存储空间,而new String()则存储在另一块存储空间里,此时,变量s对应内存中存储的数值是对象占用的那块内存的首地址。如果比较两个变量是否指向同一个对象,可以用"=="比较(看存储的地址值是否相同),但如果要比较两个对象的内容是否相等,那么"=="无法实现。(比如上图中的s3和s4,如果比较它俩是否指向同一个对象,可以用"==",但是要比较它俩分别对应的堆中的两个对象的内容值是否相同,就要用equals方法。)

equals是Object类提供的方法之一,每一个Java类都继承自Object类,所以每一个对象都具有equals方法。String类的equals方法是用于比较两个独立对象的内容是否相同,即堆中的内容是否相同。

例:String s1=new String("Hello");

String s2=new String("Hello");

两条new语句创建了两个对象,然后用s1、s2两个变量分别指向一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,但两个对象中的内容是相同的。

所以,s1==s2会返回false,s1.equals(s2)会返回true。

如果s2=s1,s1==s2会返回true。

6.

Java中有5个类可以对字符或字符串进行操作:Character、String、StringBuffer、StringBuilder、StringTokenizer。

Character

用于单个字符操作。

String

用于字符串操作,属于不可变类,所以适合在需要被共享的场合中使用,如果用String保存一个经常被修改的字符串,会生成很多无用的对象,被垃圾回收器回收,影响程序性能,执行效率低。初始化方式:构造函数方式和赋值方式均可:String s=new String("world"); 或 String s="hello";

StringBuffer

字符串缓冲区,用于字符串操作,属于可变类,所以适合保存经常被修改的字符串,会比String少很多附加操作。初始化方式:只能使用构造函数方式:StringBuffer s=new StringBuffer("hello");

字符串修改的两种方式:

1.

String s="hello";

s+="world";

2.

StringBuffer s=new StringBuffer("hello");

String s1="world";

s.append(s1);

如果字符串修改次数多,StringBuffer要比String(第2种比第1种)运行效率高很多。

StringBuilder

字符串缓冲区,但不是线程安全的,如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会更高些。所以,在只有单线程访问时可以使用StringBuilder,当有多个线程访问时,最好使用线程安全的StringBuffer。因为StringBuffer必要时可以对这些方法进行同步,所以任意特定实例上的所有操作好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

在执行效率上,从高到低,依次是StringBuilder、StringBuffer、String。一般地,如果要操作的数据量比较小,优先使用String类;如果在单线程下操作大量数据,优先使用StringBuilder类;如果在多线程下操作大量数据,优先使用StringBuffer类。

StringTokenizer

分割字符串的工具类

import java.util.StringTokenizer;

public class Test {
    public static void main(String[] args){
        StringTokenizer s=new StringTokenizer("Hello my friends");
        while (s.hasMoreTokens()) {
            System.out.println(s.nextToken());
        }
    }
}

//运行结果:
Hello
my
friends
原文地址:https://www.cnblogs.com/tendo/p/10368977.html