关于String类的一些基本知识

    不论是对于C++还是Java,字符串总是很重要的一块内容。实际的开发中,字符串相关的内容自然也是要被经常用到的。

关于“==”以及equal 以及hashcode以及compareTo方法

    在这之前要补充一点关于Object类的相关知识:

    Java.lang包是系统自动导入进来的,Object类在lang包中。

    对于原生数据类型而言“==”自然就是比较两个数据类型所代表的数字是否相等。

    对于引用类型而言,“==”表示的是左边引用与右边的引用是否指向的是同一个对象,即使仅仅比较的是地址,而非所指向的内容,就是说仅仅比较的是左右两边的引用地址是否相同。

    直接打印一个引用类型,会默认自动调用toString方法,在Object类型本来的定义中,toString方法会打印出如下的内容:getClass().getName()+’@’+Integer.toHexString(hashcode())即是打印对象所属的类名加上这个对象的引用所指向的地址的16进制表示形式。在String类中,toString方法被进行了重写,直接打印出的是字符串所指的内容,HashCode方法也进行了重写,这个hashcode值不在是跟引用所指向的内存地址有关,而是跟String实例的实际内容有关,对于不同的String类型的引用,如果有相同的内容,则他们的hashcode也是相同的。

    想要比较两个字符串的内容,就要通过equal方法来比较了,注意Srring类中对equals方法进行了重写,在Object类中,equals方法相当简易与“==”是等价的,就是比较引用所指向的地址是否相同:

public boolean equals(Object obj) {

return (this == obj);}

    在String方法中重写的部分还是要特别留意一下源码,主要是借鉴这种模式,要有完整性和容错性,比如开始两步的判断。因为在许多情况下,都需要重写equals方法,这个笔试的时候也比较容易考察,String类的equals方法如下:

public boolean equals(Object anObject) {

//要是引用所指向的地址一样 直接返回true不再比较

if (this == anObject) {

return true;

}

//因为形参是Object类型的 判断如果是string类型的实例则依此比较字符 否则返回false

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;

}

//一般这种boolean类型的,也可以先默认设一个返回值,比如函数开始的时候让b=false在中间根据实际情况对b进行调整,在最后return b。

  

    如果面试的时候,让解释equals方法,一定要分开说,对于Object类是怎样的,对于其他类,重写的话是怎样的没重写的话是怎样的。这里还要注意一个方法compareTo方法,这个方法也可以用来比较两个字符串,但是这个方法的返回结果是int类型,如果str1.compareTo(str2)如果str1小于str2则返回一个负数,如果str1与str2内容一致,则返回0,如果str1>str2则返回一个正数,里面的基本实现就是相当于把两个字符串遍历一下,之后一个一个的char进行比较,要是第i个位置上不相等的话就返回chars1[i]-chars2[i],对于"abc".compareTo("abcd")这种情况,一个是另一个的子序列,返回的是str1.length-str2.length,也就是说对于"abc".compareTo("abcd")与"abc".compareTo("abce")这种与内容无关与长度有关,返回结果都是-1。

关于字符串池

    String的两种赋值方式:

    String s=”hello”这种方式叫做字面赋值方式

    String s=new String(“hello”)这个是通过new的方式来创建字符串对象。

    因为String类在实际开发中使用得非常频繁,有必要维护一个字符串池,字符串池是栈内存中的一段空间,主要有以下的功能:

    通过字面赋值的方式生成String对象,比如String s=”hello”:

    1、 从String Pool中检查,看是否有hello这个对象,

    2、 要是没有就在字符串池中创建一个hello对象,之后返回这个字符串池中的地址。

    3、 要是字符串池中存在hello对象就返回这个hello对象的地址。

    通过new的方式生成String对象,比如String s=new String(“hello”)

    1、 首先在字符串池中检查是否有hello对象

    2、 若是字符串池中存在hello对象,则直接在堆中创建一个hello对象,并返回堆中的地址。

    3、 若是字符串池中没有hello对象,则首先在字符串池中创建hello对象,再在堆中创建hello对象,之后将堆中的地址返回。

    对于上面的基本知识了解清楚,处理这个常见的String的比较问题就比较容易了:

   public class stringTest {

   public static void main(String[]args){

   String str1="hello";//str1指向的是字符串池中的地址

   String str2=new String("hello");//str2指向的是堆中的地址

   String str3=new String("hello");//str3指向的是堆中的地址

   Object str4=new String("welcome");

   System.out.println(str1==str2);

   //false str1是栈中的地址 str2是堆中的地址

   System.out.println(str2==str3);

   //false str2是堆中的地址 str3是堆中的另一个地址 指向不同的地址(不是同一个对象) 但所包含的内容相同

   System.out.println(str1=="he"+"llo");

   //true 全都是字符串池中的地址

   System.out.println(str1=="hel"+"lo");

   //true 同上

   System.out.println(str2=="hel"+"lo");

   //false str2是堆中的地址

  }

}

    关于intern方法,对于字符串的intern方法而言,会返回一个对应字符串的标准表示。比如调用”abc”.intern(),如果字符串池中有”abc”就返回其地址,如果没有,就先将”abc”存在字符串池中,在返回其所在字符串池中的地址。

关于 null以及””的区别

  通过下面的测试程序可以发现 String str=””以及String st=null是完全不一样的:

String str1="";
String str2=null;
System.out.println(str1==str2);//false
System.out.println(str1.equals(str2));//false

  第一个为false是显然的,因为一个是实例的对象一个是空的指针,第二个为false要特别注意了:””仍然表示一个字符串只不过这个字符串的值是空的,仍然占有空间,并且是一个已经被实例化的字符串对象,只不过内容是空的,这个实例还可以执行一些String类的相关函数,而null仅仅表示的是一个空的引用,str1已经指向了一个对象,而str2只是一个空指针,具体比较的时候不要把两种情况弄混淆!

关于StringBuffer

    String类型是常量,定义了之后就不可再改变了,每次用“+”的形式将两个字符串拼接起来,实际上是又生了一个新的字符串。Java中可以使用StringBuffer来对字符串进行修改,StringBuffer是一个变量,可以动态地往里面追加新的内容。利用toString方法可以将其转化成string的形式。StringBuffer buffer=new StringBuffer(“xxx”); buffer.append(xxx).apend(xxx)这里每次append之后返回的不是一个新的引用,仍然是原来的那个引用,虽然有多次append操作但是始终只有一个StringBuffer对象。注意这里的StringBuffer要通过new的方式来生成一个新的对象,并不能像String那样,直接通过常量的方式就能赋值,Java里面并没有对StringBuffer做特殊的优化处理,这里就和普通的类的使用方式是一样的。

原文地址:https://www.cnblogs.com/Goden/p/3990985.html