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 ...
随机推荐
- 第一个月.day1
1. 编辑器下载 推荐的是hbulider 开发环境 2. 浏览器 推荐chrome 谷歌浏览器学习 3. 建立技术笔记 推荐博客园 Web 本月任务 搭建静态网页. 静态页面:不需要网络请求 ...
- github仓库迁移到gitlab以及gitlab仓库迁移到另一个gitlab服务器
一. github仓库迁移到gitlab 先进入 new project: 选择 Import project, 选择下面的github: 进入后,这里需要github的 personal acces ...
- mybatis无效比较:invalid comparison:java.util.data and java.lang.string
原因: 时间与空字符串比较是无效的,如果拿传入的时间类型参数与空字符串''进行对比则会引发invalid comparison:java.util.data and java.lang.string异 ...
- PAT 1005 Spell It Right 字符串处理
Given a non-negative integer N, your task is to compute the sum of all the digits of N, and output e ...
- Java入门系列之StringBuilder、StringBuffer(三)
前言 上一节我们讲解了字符串的特性,除了字符串类外,还有两个我们也会经常用到的类,那就是StringBuffer和StringBuilder.因为字符串不可变,所以我们每次对字符串的修改比如通过连接c ...
- Nginx配置Tomcat8反向代理出现 java.lang.IllegalArgumentException: The character [_] is never valid in a domain name.
在配置Nginx的反向代理,访问反向代理的路径而出现了异常 java.lang.IllegalArgumentException: The character [_] is never valid i ...
- idea搜索不到任何插件
今天在idea安装插件的时候,突然发现,什么都搜索不到了?? 解决方案: 完活.
- django中使用pandas Django-pandas
在django中使用pandas操作django的ORM查询出来的QuerySet对象,可以使用插件django-pandas. 截止教程书写时间,django-pandas已发布到0.6.1. 依赖 ...
- JMeter资源监控插件PerfMon的使用
1.插件下载 首先下载jmeter的插件管理工具,下载地址:jmeter-plugins.org 如英文说明,把下载后的jar包放到jmeter的安装目录lib/ext文件夹下,重启jmeter,就会 ...
- Cobalt Strike系列教程第四章:文件/进程管理与键盘记录
Cobalt Strike系列教程分享如约而至,新关注的小伙伴可以先回顾一下前面的内容: Cobalt Strike系列教程第一章:简介与安装 Cobalt Strike系列教程第二章:Beacon详 ...