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》),当然对于值类型使用“==”毫无疑问没毛病。
Java入门系列之字符串创建方式、判断相等(一)的更多相关文章
- Java入门系列之字符串特性(二)
		
前言 上一节我们讲解到字符串本质上就是字符数组,同时详细讲解了字符串判断相等需要注意的地方,本节我们来深入探讨字符串特性,下面我们一起来看看. 不可变性 我们依然借助初始化字符串的方式来探讨字符串的不 ...
 - Java:多线程概述与创建方式
		
目录 Java:多线程概述与创建方式 进程和线程 并发与并行 多线程的优势 线程的创建和启动 继承Thread类 start()和run() 实现Runnable接口 实现Callable接口 创建方 ...
 - Java入门系列-26-JDBC
		
认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...
 - Java入门系列-19-泛型集合
		
集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...
 - Java入门教程四(字符串处理)
		
Java 语言的文本数据被保存为字符或字符串类型.字符及字符串的操作主要用到 String 类和 StringBuffer 类,如连接.修改.替换.比较和查找等. 定义字符串 直接定义字符串 直接定义 ...
 - Java中的多线程的创建方式
		
首先理清几个基本概念: 程序:为完成特定任务,用某种语言编写的一组指令的集合.即一段静态的代码(还没运行起来) 进程:是程序的一次执行过程,也就是说程序运行起来了,加载到了内存中,并占用了cpu的资源 ...
 - Java多线程学习(二)---线程创建方式
		
线程创建方式 摘要: 1. 通过继承Thread类来创建并启动多线程的方式 2. 通过实现Runnable接口来创建并启动线程的方式 3. 通过实现Callable接口来创建并启动线程的方式 4. 总 ...
 - Java多线程系列1 线程创建以及状态切换
		
我们知道线程线程有三种创建方式 1实现Runnable接口 2 继承Thread类 3使用Callable和Future接口创建线程.具体是创建Callable接口的实现类,并实现clall()方法. ...
 - Java入门系列(九)Java API
		
String,StringBuilder,StringBuffer三者的区别 1.首先说运行速度,或者说是执行速度 在这方面运行速度快慢为:StringBuilder > StringBuffe ...
 
随机推荐
- 关于Mysql修改帐号密码的多种方法
			
方法一: 登录Mysql进行修改(mysql的小黑框) 命令: set password for 用户名(一般为root) @localhost=password('新密码'); 方法二: 登录MyS ...
 - Failed to execute ‘createObjectURL’ on ‘URL’: No function was found that matched the signature provided.
			
这个报错是因为在浏览器上开启了手机模拟调试.Web SDK 不支持手机模拟调试的.
 - NFS文件系统及搭建NFS共享服务
			
一.什么是文件系统? 文件系统是对一个存储设备上的数据和元数据进行组织的一种机制.文件系统是在一个磁盘(包括光盘.软盘.闪盘及其它存储设备)或分区上组织文件方式方法,常见文件系统如ext2.ext3. ...
 - 动态SQL与变量绑定
			
有时候动态sql需要进行变量的赋值,这个时候就需要调用系统的存储过程sp_executesql了.使用中还是有些注意事项,代码如下: --字符型字段需声明为NVARCHAR类型 ),) --动态SQL ...
 - docker采用Dockerfile安装jdk1.8案例
			
1 获取一个简单的Docker系统镜像,并建立一个容器. 这里我选择下载CentOS镜像 docker pull centos 通过docker tag命令将下载的CentOS镜像名称换成centos ...
 - 关于kubernetes我们还有什么可做的?
			
kubernetes在容器编排大战中由于应用的可移植性以及支持混合云/多云部署方式上的灵活性.加上开放可扩展的理念,使得周边社区非常活跃.从既有调研结果看,kubernetes已成为容器编排领域的标准 ...
 - 松软科技web课堂:字符串方法和属性
			
字符串方法帮助您处理字符串. 字符串方法和属性 原始值,比如“Bill Gates”,无法拥有属性和方法(因为它们不是对象). 但是通过 JavaScript,方法和属性也可用于原始值,因为在执行方法 ...
 - NIO基础方法一
			
1.remaining();返回当前位置与limit之间得元素数. int[] intArray={1,2,3,4}; IntBuffer intBuffer=IntBuffer.wrap(intAr ...
 - ios中设置UIButton圆角,添加边框
			
//例如: UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(50, ...
 - IDEA org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
			
引用地址:https://guozh.net/idea-org-apache-ibatis-binding-bindingexception-invalid-bound-statement-not-f ...