• Java入门系列之字符串创建方式、判断相等(一)


    前言

    陆续从0开始学习Java出于多掌握一门语言以后的路也会更宽,.NET和Java兼顾,虽然路还很艰难,但事在人为。由于Java和C#语法相似,所以关于一些很基础的内容不会再重头讲,Java系列中所有文章都会基于我个人所看文章和博客之后的思考,有些会和C#语法进行对比,有些是全新的概念,讲解完整个基础系列,然后进入数据结构和深入学习JVM,我都会详细记录,所有系列语法都是基于Java8,我们开始吧。

    字符串创建

    在Java中创建字符串四种方式,一是直接通过new运算符创建字符串,二是通过字符数组创建、三是通过提取字符数组创建、四是通过定义字符串变量创建,下面我们来一一过下

    (1)new运算符创建字符串

    String str = new String("Jeffcky");
    System.out.println(str);

    (2)字符数组创建String对象

    char a[] = {'j', 'e', 'f', 'f', 'c', 'k', 'y'};
    String str = new String(a);
    System.out.println(str);

    (3)提取字符数组创建String对象

    通过如上第一种方式直接通过new运算符获取字符数组,通过new运算符创建字符串对象还有重载,如下:

    char a[] = {'j', 'e', 'f', 'f', 'c', 'k', 'y'};
    String str = new String(a,0,4);
    System.out.println(str);

    该重载方式第一个参数则是操作的字符数据,第二个参数是偏移量offset,也就是说从字符数组哪里开始截取,第三个参数是count,也就是说我们要读取几个字符。

    (4)字符串常量引用赋值创建字符串

    这种方式也是我们最常用创建字符串变量的方式,如下:

    String str = "Jeffcky";
    System.out.println(str);

    字符串判断相等

    判断字符串是否相等在Java和C#中处理方式不一样,接下来我们将对比C#和Java中的处理方式。我们首先来整体看看C#和Java中判断方式的不同,如下为C#

    “==”和equals

            static void Main(string[] args)
            {
                string str1 = new string("Jeffcky");
                string str2 = new string("Jeffcky");
                Console.WriteLine(str1 == str2);
                Console.WriteLine(str1.Equals(str2));
                Console.ReadKey();
            }

    接下来我们再来看看Java中相同判断方式:

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

    通过如上C#和Java中打印结果,想必我们就知道了不同,在C#中==对于值类型直接判断其值是否相等,而对于引用类型尤其是字符串则重写了Equals方法而直接比较字符串值,所以上述都打印出true,在C#中若想要比较引用类型地址是否相等,则使用ReferenceEquals方法,所以上述在C#中的演示代码要想得到和Java中处理结果,则演示代码变成如下:

     static void Main(string[] args)
     {
         string str1 = new string("Jeffcky");
         string str2 = new string("Jeffcky");
         Console.WriteLine(ReferenceEquals(str1, str2));
         Console.WriteLine(str1.Equals(str2));
         Console.ReadKey();
    }

    我们反观Java中通过new操作符创建的字符串进行“==”比较是为false,这是由于通过new运算符创建了两个相同字符串对象的地址不一样,由此可见:在Java中的==并不是比较字符串的值,因为“==”仅仅只检查两个字符串的引用相等性,意味着它们是否引用相同的对象。如果将上述Java代码进行如下修改,此时两个字符串通过“==”比较则相等:

    public static void main(String[] args) {
            String str1 = "Jeffcky";
            String str2 = "Jeffcky";
            System.out.println(str1 == str2);
            System.out.println(str1.equals(str2));
     }

    我们经过如上修改后,通过“==”判断此时str1和str2指向堆上同一对象Jeffcky的地址,不好理解?那么接下来我们经过如下修改则一目了然

     public static void main(String[] args) {
            String str1, str2;
            str1 = "Jeffcky";
            str2 = "Jeffcky";
            System.out.println(str1 == str2);
            System.out.println(str1.equals(str2));
    }

    我们再来进行一行行解释,第一行字符串str1和str2引用为null,第二行在堆上创建名为Jeffcky的对象,此时将引用地址赋值给str1,第三行在堆上已有相同对象的字符串,直接将引用地址赋值给str2,所以此时str1和str2的引用对象相等打印出true。接下来我们再来看equals方法,最喜欢的则是在Java中可直接查看源码,我们看看equals方法实现,如下:

    public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            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类重写从Object继承的equals方法,此方法逐个字符地比较两个字符串,而忽略它们的引用地址,也就是说如果长度且字符顺序相等,则认为它们相等。

    Object equals

    上述我们讨论到字符串中的equals方法重写了Object类中的equals方法,那么Object类中的equals方法进行比较的逻辑又是怎样的呢?我们来看看如下代码:、

    import  java.util.Objects;
    
    public class Main {
    
        public static void main(String[] args) {
            String string1 = "using objects equals";
            String string2 = "using objects equals";
            String string3 = new String("using objects equals");
    
            System.out.println(Objects.equals(string1, string2));
    
            System.out.println(Objects.equals(string1, string3));
    
            System.out.println(Objects.equals(null, null));
            System.out.println(Objects.equals(null, string1));
        }
    }

    对于上述打印结果,我们结合Object类中的equals源码来分析,如下:

     public static boolean equals(Object a, Object b) {
            return (a == b) || (a != null && a.equals(b));
     }

    由此我们得出结论:Object类中equals为静态方法,首先使用它们的地址比较它们,即“==”判断,如果两个字符串相等,则该方法返回true。同时如果两个参数都为null,则返回true,如果只有一个参数为null,则返回false。否则,它只是调用传递的参数类型的类的equals方法,上述则是String的类equals方法。 此方法区分大小写,因为它在内部调用String类的equals方法。

    总结

    本文我们详细介绍了Java中关于字符串的比较,可能和我一样的初学者如果不是很了解内部实现的话会存在使用误区,对于字符串判断相等应该使用equals方法而不是“==”或者使用Object类的静态方法equals(因为其内置会调用对象的equals方法),因为“==”是比较引用是否相等(这里结论不太准确,更多详细信息请参考《https://www.cnblogs.com/CreateMyself/p/11437026.html》),当然对于值类型使用“==”毫无疑问没毛病。

  • 相关阅读:
    读书笔记之:数据结构,算法与应用(3)
    C++中的虚函数继承与虚继承
    读书笔记之:Effective STL
    C++虚函数及虚函数表解析
    类中的常量, const对象和成员函数
    读书笔记之:Boost程序库完全开发指南(Ch14)
    读书笔记之:C++探秘——68讲贯通C++
    读书笔记之:Boost程序库完全开发指南(ch516)
    配置java的环境变量
    查询并杀死死锁
  • 原文地址:https://www.cnblogs.com/CreateMyself/p/11437018.html
Copyright © 2020-2023  润新知