Java基础之字符串

Catálogo
  1. 1. 类结构
  2. 2. 类概述
    1. 2.1. 小结
  3. 3. 方法
  4. 4. 思考
    1. 4.1. null和空字符串的区别s

类结构

public final class String
extends Object
implements Serializable, Comparable, CharSequence

类概述

Java把内存划分为两种:一种是栈内存,一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。

堆内存用来存放由new创建的对象和数组,在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量(以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量相当于是为数组或者对象起的一个名称)。

PS:引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new产生的数组或者对象所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能再被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放)。- >这也是Java比较占内存的原因。

String类是一个很特殊的类,它本身是final的,它是不可变的,String类是的本质是字符数组char[], 并且其值不可改变,但StringBuilder也是final,为什么StringBuilder是可变的呢? 究其原因,String类的内部是char[]数组构成,而String的加号(+)运算符的底层是由StringBuilder实现的,一个String每次“+“上一个String,都会创建一个新的StringBuilder,然后调用它的append()方法,该方法返回一个新形成的String。所以字符串的一些合并操作可以使用StringBuilder来提高效率。

用new String()创建的字符串不是常量,不能在编译期就确定,而因为String是类,所以new String()创建的字符串不放入常量池中,它们有自己的地址空间。即Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。而直接初始化则会形成字符串常量,分配到运行时常量池中,这会在编译时确定。

小结

  • Java程序中的所有字面值(string literals),即双引号括起来的字符串,如“bia”,都是作为String类的实例实现的。
  • String类是一个很特殊的类,它本身是final的,它是不可变的,String类的本质是字符数组char[ ], 并且其值不可改变。String是常量,其对象一旦构造就不能被改变。In other words,String对象是不可变的,每一个看起来会修改String值的方法,实际上都是创造了一个全新的String对象(构建一个新的StringBuilder,然后调用它的append()方法,该方法方法返回一个新创建的String对象),以包含修改后的字符串内容。
  • String对象具有只读特性,指向它的任何引用都不可能改变它的值,因此,也不会对其他的引用有什么影响。

方法

1.创建字符串

1
2
3
4
5
String str = "Hello World";
String str1 = new String("Hello World");
String str2 = new String();
str2 = "Hello World"
System.out.println("str:" + str + "str1:" + str1 + "str2:" + str2);
  • String类有11种构造方法,这些方法提供不同的参数来初始化字符串
  • String类是不可改变的,所以一旦创建了String对象,其值就无法改变了

2.字符串长度

1
2
3
String str = "Hello World";
int i = str.length();
System.out.println(i);

String类的一个访问器方法是length( )方法,它返回字符串对象包含的字符数。

3.连接字符串

  • 字符串常量使用concat( )方法连接
  • 使用’+’操作符来连接字符串
1
2
3
4
String str = "Hello World";
String str1 = "Good Friends";
str2 = str.concat(str1);
str3 = str + str1;

4.创建格式化字符串

1
2
3
4
5
6
7
String str;
int i = 100;
double d = 10.243;
float f = 124124;
str = String.format("NO1 : %d" + "NO2 : %f" + "NO3 : %f",i,f,d); //使用 .format() 方法格式化字符串
System.out.printf("NO1 : %d" + "NO2 : %f" + "NO3 : %f",i,f,d); //使用 printf()方法 格式化字符串
System.out.println(str);

我们知道输出格式化数字可以使用printf( )和format( )方法。String类使用静态方法format( )返回一个String对象而不是PrintStream对象。
String类的静态方法format( )能用来创建可复用的格式化字符串,而不仅仅是用于一次打印输出。

5.char charAt(int index)
返回指定索引处的char值

1
2
3
4
5
String str = "hello world";
char c = str.charAt(2);
System.out.println(c);
//output: l

6.int compareTo(Object o)
把这个字符串和另一个对象比较

1
2
3
4
5
6
String str = "Hello world";
String str1 = "Good Friends";
int i = str.compareTo(str1);
System.out.println(i);
//output: 1

比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。返回整数,1,-1,0;返回1表示大于,返回-1表示小于,返回0表示相等。

7.boolean endsWith(String str)
测试此字符串是否以指定的后缀结束。

1
2
3
4
5
6
String str = "Hello World";
boolean b = str.endsWith("d");
System.out.println(b);
//output:true

8.boolean equals(Object object)
将此字符串与指定的对象比较

1
2
3
4
String str = "Hello World !";
String str1 = "Good Friends";
boolean b = str.equals(str1);
System.out.println(b);

9.int indexOf(int char)
返回指定字符在此字符串中第一次出现处的索引

1
2
3
4
5
6
String str = "Hello World !";
int i = str.indexOf('e');
System.out.println(i);
//output: 1
//若无此字符串,则返回-1

更多String方法,点击查看

思考

null和空字符串的区别s

String s=null;
string.trim()就会抛出为空的exception
String s=””;
string.trim()就不会抛,为什么?

答:
1)null代表声明了一个空对象,根本就不是一个字符串,对空对象做任何操作都不行,除了 = 和 == ;
“”代表声明了一个对象实例,这个对象实例的值是一个长度为0的空字符串,其仍代表一个字符串,只是字符串里面没有内容。
2)String s = null;只是定义了一个句柄,也就是说你有了个引用,但是这个引用未指向任何内存空间;
String s = “”;这个引用指向了一块是空字符串的内存空间,可对其进行满足字符串操作的任何操作。

所以,题目中为何一个会抛异常,一个不会抛异常就得以解答。

String s;和String s=null;和String s=”a”;有什么区别?
针对这三种情况,使用out.println(s);的时候,第一个会出现异常,第二个会输出null.第三个则会输出a.
这是为什么呢?这三句声明语句,各自作了什么呢?

答:
第一个只是定义了一个String类型变量s,并没有给它赋值(若是类的成员变量,才默认赋值),在Java中,默认在使用一个对象的时候必须赋予它初值(降低风险)。
第二个和第三个都定义了String类型变量s,并赋予它初值,只不过第二个赋予的值为null;
Attention:s为一个引用,它不是对象。第一个是没有初始化的引用,第二个为空引用,第三个是在字符串池里写入一个字符’a’,然后s指向它。
Ps:String s = ‘a’ ;和 String s = new String(“a”);是有本质上的区别的。前者是在字符串池里写入一个字符’a’,然后s指向它,后者是在堆上创建一个内容为’a’的字符串对象。

声明了一个string a;变量
在以后的判断中,a==””和a==null有何不同?

答:
如果没有给a赋过值,a == “” 会导致异常。
在实际处理中,往往认为””和null代表相同的含义,即代表无值。
此时,建议用如下语法:

1
2
3
if (a == null || a == ""){
//处理语句
}

如果a为null,则不会执行后面的判断,直接返回true。
null是用来判断引用类型是否分配了存储空间,””是针对字符串的。所以如果没有给a赋过值,a == “”会导致异常。

String abc=null;String abc=””;String abc;三种写法有什么区别?

答:
1:创建一个空字符串对象,
2:创建一个字符串为空的字符串对象。
3:声明一个字符串对象,但并没有分配内存,而1,2已经分配了内存

tips:
在成员变量的定义中,String s;等同于String s=null;
而在本地变量(方法变量)的定义中,String s;不等同于String s=null;,这时要使用s必须显式地赋值。

还有一点要说明的是:
只要是在方法在中定义变量都要显示赋初值,main()方法也不例外,而在方法之外编译器回自动赋初值。

Compartir Comentarios