java中 equals 方法详解 和 String 详解

第一个重要知识点
== 和equals 方法的区别,很重要的一点为,
== 永远比较的是地址,除了在原生数据类型时比较大小
而equals方法在 String类型 和 八种原生数据类型的包装类型如Integer等,的里面是比较的内容。而对于普通的对象,equals方法也比较的是 地址。

第二个重要知识点
new的原生数据类型,原生数据类型的包装型(但是有值一定的定义域,例如integer的域为-128—+127) 例如 Integer integer=100; 通过String a=”aaa” 定义的变量,是放在栈中的,
而 new出来的对象,和a=new String(“aaa”) 是存放在堆中的, 注意Integer integer=300,因为超出了字符串常量池维护的范围,所以它是通过new来创建的,也是放在堆中的

equals 方法是在java.lang.Object 下的,它本身的源码为:

    public boolean equals(Object obj) {
        return (this == obj);
    }

由此可见,如果equals方法没有被重写的话,它比较的应该是两个对象的地址。

注意(1):

如果: StringBuffer s1 = new StringBuffer(“a”);
StringBuffer s2 = new StringBuffer(“a”);

结果: s1.equals(s2) //是false

解释:StringBuffer:线程安全的可变字符序列,字符串长度可变StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,

      而Object类中的equals方法是用来比较“地址”的,所以等于false.

String 是一个比较特殊的类,因为比较常用,所以其的一些方法跟其他的类的方法有些不同,这是为了提高程序运行的效率,java专门重写了它的equals方法,下面是它的源码:

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        //判断anObject是不是String类型的
        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;
    }

由此可见,String类型的equals方法是比较两个字符串的内容的
对于String 类型,它的 == 符号比较的是两个对象的地址

对于八种原生数据类型 int,float,double,boolean,char,long,short,byte,他们的 == 比较的是两个对象的内容,他们并没有什么 equals 方法,
但是对于 八种基本类型的包装类型, Integer,Boolean、Character、Byte、Shot、Long、Float、Double是有着equals 方法,其中equals 方法比较的是它们自身的内容,而==比较的则是它们的地址

如何实现 原生数据类型和 其包装型的转化(以Integer为例子):

Integer integer=new Integer(i);

String 类型的详解:

public class StringTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

          // String  是常量, 一旦生成之后就不能被改变了 , + 代表拼接,生成了一个新的对象
          String strr1 = "Hello";
          String stre2 = " World";
          String strr3= strr1 + stre2;
          // 所有new出来的对象则都存放在  堆   中,而字符串池维护的则存放在栈中
          // new String() 时,首先在 String 池中检查是否有“aaa” 对象,如果有,则不再在池中创建新的对象,然后再在堆中创建
          //一个新的“aaa” 对象,将地址返回给 str1; 如果没有,则现在池中创建新的对象“aaa”, 然后再在堆中创建一个新的“aaa” 对象,将地址返回给 str1
          String str1 = new String("aaa");
          String str2 = new String("aaa");
          System.out.println( str1==str2); // False
          String str3 = "aaa";
          String str4 = "bbb";
          // 通过这种方法,String 会维护一个 String 池, 如果池里面已经有内容 为aaa 这个对象 ,则不会创建新的对象,
          //  直接把之前的对象的地址赋给str5
          //  java 中 String == 判断的是对象的地址是否相同, 如果要判断内容是否相同,请使用 equals() 方法
          String str5 = "aaa"; 
          System.out.println( str3==str4);  // False
          System.out.println( str3==str5);  // true
          System.out.println( str3==str1);  // false    
    }
}

String, StringBuffer/StringBuilder 的区别
第一: String(无法添加新的内容,只能通过+号拼接字符串,但其实是生成了一个新的对象) 和 StringBuffer/StringBuilder(它添加新的内容时使用append()方法,不再创建新的对象,在原来的字符串上的基础上相加)
第二: 三者速度的比较, String>StringBuilder>StringBuffer
第三:StringBuilder:可变字符串,线程非安全的, 一般单线程的时候使用,速度快
StringBuffer:可变字符串,线程安全的,除了线程安全方面的问题,其他方面的实现, StringBuffer和StringBuilder是一样的

          // String 只读字符串,意味着引用的字符串内容是不可以被修改的
          // StringBuilder:可变字符串,线程非安全的, 一般单线程的时候使用,速度快
         // StringBuffer:可变字符串,线程安全的,除了线程安全方面的问题,其他方面的实现StringBuffer和StringBuilder是一样的

          String s1="helloworld";
          String s2=new String ("helloworld");
          String s3="hello";
          String s4="world";
          String s5="hello"+"world";  // 这里你可能跟下面的一句搞混,这里其实就等价于 s5="helloworld";
          //  String 的intern()方法会比较看是否在常量池中有跟要创建的对象内容相同的,调用equals方法,
          //如果查找到相同的,就不再创建新的对象,会得到字符串对象在常量池中的引用将其返回,所以s5也指向了s1
          String s6=s3+s4;  // +号操作实际上是创建了StringBulider对象,进行append操作,
          //  然后将拼接后的StringBulider对象用toString方法处理成String, 所以这里是new了一个新的对象
          System.out.println(s1==s2);  // fasle
          System.out.println(s1==s5);  //true
          System.out.println(s1==s6);  // false
          System.out.println(s2==s5); // false
          System.out.println(s2==s6); // false

String 的intern() 机制
intern() 这个方法返回的是 返回字符串对象的规范化表示形式,当调用 intern 方法时,如果字符串常量池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。

          String a =  "b" ;   
          String b =  "b" ;   
          System.out.print( a == b);    // true
           // intern() 这个方法返回的是 返回字符串对象的规范化表示形式,当调用 intern 方法时,如果字符串常量池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。
          //否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。这时候c和d就是相同的
          String c = "d" ;  
          String d = new String( "d" ).intern() ;   
          System.out.println( c == d);    // true
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值