使用所有对象通用的方法

本文是我们名为“ 高级Java ”的学院课程的一部分。

本课程旨在帮助您最有效地使用Java。 它讨论了高级主题,包括对象创建,并发,序列化,反射等。 它将指导您完成Java掌握的过程! 在这里查看 !

目录

1.简介 2.方法等于和hashCode 3.方法toString 4.方法克隆 5.方法等于和==运算符 6.有用的助手类 7.下载源代码 8.接下来

1.简介

从本教程的第1部分“ 如何创建和销毁对象”中 ,我们已经知道Java是一种面向对象的语言(但是,不是纯粹的面向对象的语言)。 在Java类层次结构的顶部是Object类,Java中的每个类都隐式地继承自它。 因此,所有类都继承Object类中声明的方法集,最重要的是以下方法:

方法 描述
protected Object clone() 创建并返回此对象的副本。
protected void finalize() 当垃圾回收确定不再有对该对象的引用时,由垃圾回收器在对象上调用。 我们在本教程的第1部分“ 如何创建和销毁对象”中讨论了终结器。
boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。
int hashCode() 返回对象的哈希码值。
String toString() 返回对象的字符串表示形式。
void notify() 唤醒正在此对象的监视器上等待的单个线程。 我们将在本教程的第9部分 并发最佳实践中讨论此方法。
void notifyAll() 唤醒正在此对象的监视器上等待的所有线程。 我们将在本教程的第9部分 并发最佳实践中讨论此方法。
void wait()

void wait(long timeout)

void wait(long timeout, int nanos)

使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。 我们将在本教程的第9部分 并发最佳实践中讨论这些方法。

表格1

在本教程的这一部分中,我们将研究equalshashCodetoStringclone方法,它们的用法以及需要牢记的重要约束。

2.方法等于和hashCode

默认情况下,Java中的任何两个对象引用(或类实例引用)仅在它们引用相同的内存位置(引用相等)时才相等。 但是Java允许类通过重写Object类的equals()方法来定义自己的相等性规则。 听起来像一个强大的概念,但是正确的equals()方法实现应符合一组规则并满足以下约束:

  • 反身的 。 对象x必须等于自身,并且equals(x)必须返回true
  • 对称的 。 如果equals(y)返回true,y.equals(x)也必须返回true
  • 传递的 。 如果equals(y)返回true,y.equals(z)返回true ,则x.equals(z)也必须返回true
  • 一致 。 除非修改用于相等比较的任何属性,否则多次调用equals()方法必须得到相同的值。
  • 等于Nullequals(null)的结果必须始终为false

不幸的是,Java编译器无法在编译过程中强制执行这些约束。 但是,不遵循这些规则可能会导致非常怪异且难以解决问题。 一般建议是这样的:如果您要编写自己的equals()方法实现,请在实际需要时三思而后行。 现在,有了所有这些规则,让我们为Person类编写一个equals()方法的简单实现。

package com.javacodegeeks.advanced.objects;public class Person {private final String firstName;private final String lastName;private final String email;public Person( final String firstName, final String lastName, final String email ) {this.firstName = firstName;this.lastName = lastName;this.email = email;}public String getEmail() {return email;}public String getFirstName() {return firstName;}public String getLastName() {return lastName;}// Step 0: Please add the @Override annotation, it will ensure that your// intention is to change the default implementation.@Overridepublic boolean equals( Object obj ) {// Step 1: Check if the 'obj' is nullif ( obj == null ) {return false;}// Step 2: Check if the 'obj' is pointing to the this instanceif ( this == obj ) {return true;}// Step 3: Check classes equality. Note of caution here: please do not use the // 'instanceof' operator unless class is declared as final. It may cause // an issues within class hierarchies.if ( getClass() != obj.getClass() ) {return false;}// Step 4: Check individual fields equalityfinal Person other = (Person) obj;if ( email == null ) {if ( other.email != null ) {return false;} } else if( !email.equals( other.email ) ) {return false;}if ( firstName == null ) {if ( other.firstName != null ) {return false;} } else if ( !firstName.equals( other.firstName ) ) {return false;}if ( lastName == null ) {if ( other.lastName != null ) {return false;}} else if ( !lastName.equals( other.lastName ) ) {return false;}return true;}        
}

并非偶然的是,本节的标题中还包含hashCode()方法。 最后要记住的规则是:每当您重写equals()方法时,也始终要重写hashCode()方法。 如果对于任何两个对象, equals()方法返回true ,则这两个对象中的每个对象的hashCode()方法必须返回相同的整数值(但是相反的语句不那么严格:如果对于任何两个对象, equals()方法返回false ,则这两个对象中的每个对象的hashCode()方法都可能会或可能不会返回相同的整数值)。 让我们看一下Person类的hashCode()方法。

// Please add the @Override annotation, it will ensure that your
// intention is to change the default implementation.
@Override
public int hashCode() {final int prime = 31;int result = 1;result = prime * result + ( ( email == null ) ? 0 : email.hashCode() );result = prime * result + ( ( firstName == null ) ? 0 : firstName.hashCode() );result = prime * result + ( ( lastName == null ) ? 0 : lastName.hashCode() );return result;
}

为了避免意外,请尽可能在实现equals()hashCode()同时尝试使用final字段。 这将确保这些方法的行为不会受到字段更改的影响(但是,在实际项目中,并非总是可能的)。

最后,始终确保在equals()hashCode()方法的实现中使用相同的字段。 如果有任何更改影响所讨论的字段,它将保证两种方法的行为一致。

3.方法toString

toString()可能是其他方法中最有趣的方法,并且被更频繁地覆盖。 它的目的是提供对象(类实例)的字符串表示形式。 正确编写的toString()方法可以大大简化实际系统中问题的调试和故障排除。

默认的toString()实现在大多数情况下不是很有用,只是返回完整的类名和对象哈希码,以@ ,fe分隔:

com.javacodegeeks.advanced.objects.Person@6104e2ee

让我们尝试改善实现,并为我们的Person类示例重写toString()方法。 这是使toString()更有用的一种方法。

// Please add the @Override annotation, it will ensure that your
// intention is to change the default implementation.
@Override
public String toString() {return String.format( "%s[email=%s, first name=%s, last name=%s]", getClass().getSimpleName(), email, firstName, lastName );
}

现在, toString()方法提供了Person类实例的字符串版本,包括其所有字段。 例如,在执行以下代码片段时:

final Person person = new Person( "John", "Smith", "john.smith@domain.com" );
System.out.println( person.toString() );

以下输出将在控制台中打印出来:

Person[email=john.smith@domain.com, first name=John, last name=Smith]

不幸的是,标准Java库对简化toString()方法实现的支持有限,尤其是,最有用的方法是Objects.toString()Arrays.toString() / Arrays.deepToString() 。 让我们看一下Office类及其可能的toString()实现。

package com.javacodegeeks.advanced.objects;import java.util.Arrays;public class Office {private Person[] persons;public Office( Person ... persons ) {this.persons = Arrays.copyOf( persons, persons.length );}@Overridepublic String toString() {return String.format( "%s{persons=%s}", getClass().getSimpleName(), Arrays.toString( persons ) );}public Person[] getPersons() {return persons;}
}

以下输出将在控制台中打印出来(如我们所见, Person类实例也已正确转换为字符串):

Office{persons=[Person[email=john.smith@domain.com, first name=John, last name=Smith]]}

Java社区已经开发了两个非常全面的库,这些库在很大程度上toString()实现的工作。 其中包括Google Guava's Objects.toStringHelper和Apache Commons Lang ToStringBuilder 。

4.方法克隆

如果Java中有一种声誉不佳的方法,则肯定是clone() 。 它的目的很明确–返回正在调用的类实例的确切副本,但是有很多原因使它不像听起来那么容易。

首先,如果您决定实现自己的clone()方法,则可以遵循Java文档中规定的许多约定。 其次,该方法在Object类中声明为protected ,因此为了使其可见,应使用重写类本身的返回类型将其重写为public 。 第三,重写的类应实现Cloneable接口(这只是一个没有定义方法的标记或mixin接口),否则将引发CloneNotSupportedException异常。 最后,实现应首先调用super.clone() ,然后在需要时执行其他操作。 让我们看看如何为我们的示例Person类实现它。

public class Person implements Cloneable {// Please add the @Override annotation, it will ensure that your// intention is to change the default implementation.@Overridepublic Person clone() throws CloneNotSupportedException {return ( Person )super.clone();}
}

该实现看起来非常简单明了,那么这里可能出什么毛病? 几件事情,实际上。 在执行类实例的克隆时,不会调用任何类构造函数。 这种行为的结果是可能会出现意外的数据共享。 让我们考虑上一节介绍的Office类的以下示例:

package com.javacodegeeks.advanced.objects;import java.util.Arrays;public class Office implements Cloneable {private Person[] persons;public Office( Person ... persons ) {this.persons = Arrays.copyOf( persons, persons.length );}@Overridepublic Office clone() throws CloneNotSupportedException {return ( Office )super.clone();}public Person[] getPersons() {return persons;}
}

在此实现中, Office类实例的所有克隆都将共享同一个人数组,这不太可能实现所需的行为。 为了使clone()实现能够做正确的事情,应该做一些工作。

@Override
public Office clone() throws CloneNotSupportedException {final Office clone = ( Office )super.clone();clone.persons = persons.clone();return clone;
}

现在看起来更好,但是即使此实现也非常脆弱,因为将人员字段定为final将导致相同的数据共享问题(因为不能重新分配final )。

总的来说,如果您想精确复制类,最好避免使用clone() / Cloneable并使用更简单的替代方法(例如,复制构造函数,具有C ++背景的开发人员熟悉的概念或工厂)方法,这是我们在本教程的第1部分“ 如何创建和销毁对象”中讨论的一种有用的构造模式。

5.方法等于和==运算符

Java ==运算符和equals()方法之间存在有趣的关系,这会引起很多问题和混乱。 在大多数情况下(比较原始类型除外), ==运算符执行引用相等:如果两个引用都指向同一个对象,则返回true,否则返回false 。 让我们看一个说明差异的简单示例:

final String str1 = new String( "bbb" );
System.out.println( "Using == operator: " + ( str1 == "bbb" ) );
System.out.println( "Using equals() method: " + str1.equals( "bbb" ) );

从人类的角度来看,str1 ==“ bbb”和str1.equals(“ bbb”)之间没有区别:在两种情况下,结果都应该相同,因为str1只是对“ bbb”字符串的引用。 但是在Java中并非如此:

Using == operator: false
Using equals() method: true

即使两个字符串看起来完全相同,在此特定示例中,它们也作为两个不同的字符串实例存在。 根据经验,如果您处理对象引用,请始终使用equals()Objects.equals() (请参阅下一部分有用的帮助程序类以获取更多详细信息)进行相等性比较,除非您确实有比较的意图如果对象引用指向同一实例。

6.有用的助手类

自Java 7发行以来,标准Java库附带了几个非常有用的帮助程序类。 其中之一是Objects类。 特别是,以下三种方法可以大大简化您自己的equals()hashCode()方法的实现。

方法 描述
static boolean equals(Object a, Object b) 如果参数彼此相等,则返回true;否则返回false
static int hash(Object... values) 为一系列输入值生成哈希码。
static int hashCode(Object o) 返回非空参数的哈希码,对于空参数返回0。

表2

如果我们使用这些帮助器方法为Person的类示例重写equals()hashCode()方法,则代码量将大大减少,并且代码的可读性也将大大提高。

@Override
public boolean equals( Object obj ) {if ( obj == null ) {return false;}if ( this == obj ) {return true;}if ( getClass() != obj.getClass() ) {return false;}final PersonObjects other = (PersonObjects) obj;if( !Objects.equals( email, other.email ) ) {return false;} else if( !Objects.equals( firstName, other.firstName ) ) {return false;            } else if( !Objects.equals( lastName, other.lastName ) ) {return false;            }return true;
}@Override
public int hashCode() {return Objects.hash( email, firstName, lastName );
}

7.下载源代码

  • 您可以在此处下载源代码: advanced-java-part-2

8.接下来

在本节中,我们介绍了Object类,它是Java中面向对象编程的基础。 我们已经看到了每个类如何覆盖从Object类继承的方法并强加其自己的相等性规则。 在下一节中,我们将切换编码方式,并讨论如何正确设计类和接口。

翻译自: https://www.javacodegeeks.com/2015/09/using-methods-common-to-all-objects.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/358387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端工程师面经——概述及面试技巧加考点篇(一)

这段时间受到疫情的影响,本身做java开发的,面试了入职了一个外包公司的前端岗位,入职属于驻场开发的那种,前几周基本没啥事,一般经理会让你刷题,到了驻场那边需要机试过关才能在那边开发,这边在牛客网,LeetCode等平台找点前端的题做一做顺便记录,仅供参考,那边做的是…

Struts2漏洞和Struts Scan工具实战

一、Apache Struts 2漏洞背景 1.漏洞详情 2017年3月6日,Apache Struts 2被曝存在远程命令执行漏洞。在使用基于Jakarta插件的文件上传功能条件下,恶意用户可以通过修改HTTP请求头中的Content-Type值构造恶意代码,在服务器上执行系统命令&…

39 网络相关函数(七)——live555源码阅读(四)网络

39 网络相关函数(七)——live555源码阅读(四)网络 39 网络相关函数(七)——live555源码阅读(四)网络 简介14)readSocket从套接口读取数据recv/recvfrom 函数 函数原型:参数说明:返回说明:本文由乌合之众 lym瞎编,欢迎转载 blog.cn…

2020年前端招聘技术概览

学习当下前端技术最好的方法就是从求职网站上找出前端的招聘要求,因为前端技术每年变化都很快,每个阶段都会不一样,这里简单从网站招聘要求罗列,仅供参考。更有针对性的是针对每个公司的招聘要求写简历,学习相关技术&a…

jexboss工具 -- JBOSS未授权访问漏洞利用

其实所有的节日,都不是为了礼物和红包而生,而是提醒我们不要忘记爱与被爱,生活需要仪式感,而你需要的是在乎和关爱。。。 ---- 网易云热评 小受:Ubuntu20 小攻:Kali2020 一、搭建该漏洞环境 查看上一篇文章…

sublime text 3 前端开发常用插件

sublime text 3 前端开发常用插件https://packagecontrol.io/browse 代码对齐:Alignmenthtml代码补全: EmmetCoffeeScript语法: Better CoffeeScriptcss格式化: CSS Formatless语法: LESSjs代码格式化:JsFormat代码注释文档: DocBlockr代码美化: HTML-CSS-JS Prettify 去除行尾…

前端工程师有哪些面试技巧值得掌握?

这段时间受到疫情的影响,本身做java开发的,面试了入职了一个外包公司的前端岗位,入职属于驻场开发的那种,前几周基本没啥事,一般经理会让你刷题,到了驻场那边需要机试过关才能在那边开发,这边在…

java 模块化_Java模块化方法–模块,模块,模块

java 模块化我想每个人都会同意,编写模块化应用程序和模块化通常是一件好事。 但是,从Java和Scala语言以及各种Java / Scala框架来看,对模块化的支持看起来如何? 有很多不同的方法! 让我们看看其中的一些。 “保护”以…

Fastjson批量检查及一键利用工具

0x01 序章 上次讲解过手动利用fastjson,但讲的过于太简单了。根据大家的反应,收集如下几个问题。 1、如何盲打fastjson 2、判断fastjson的指纹 3、各版本payload以及使用ldap模式监听。 下面我就一一解答,我只是把我在网上查到的资料消化 后分…

动态规划--重拾我的“背包”

前言: 背包问题所涉及的是经典的动态规划算法。因为长时间不AC了,渐渐感觉思维也都麻了!本文将基础的背包问题做个小结,方便以后翻阅。感兴趣的朋友也可以阅读一下~------------------------(1)如何从n个重…

CSS3学习笔记总结,你值得拥有(呕心沥血之作,涵盖CSS3所有知识点)

目录 简介 边框 圆角 背景 渐变 文本效果 字体 2D转换 3D转换

Java 8 SE可选,严格的方法

大约两周前,Stephen Colebourne提出了使用Optional的实用方法 。 如果您阅读了它,您可能会从我以前的建议中猜到我不同意。 总览 我必须以免责声明开头,但随后我将直接解释为什么我认为他的方法不够理想。 所有不归因于他人的报价均摘自Ste…

routersploit简单实例

https://github.com/reverse-shell/routersploit RouterSploit。它包含了27个品牌的上百种漏洞利用模块,涉及的路由器、摄像头等设备有几百种。渗透的时候,用户首先根据目标设备的品牌选择对应的扫描模块,用以发现漏洞。一旦漏洞识别&#x…

《Spring3.0就这么简单》

第一章 认识Spring 1、Spring提供的IOC容器,是Spring大杀器之一。容器将对象之间的依赖关系交给Spring进行控制,采用配制的方式对依赖关系进行描述,由Ioc容器负责依赖类之间的创建、拼接、管理、获取工作 2、Spring提供的第二大杀器&#xff…

前端面试题之http/HTML/浏览器(一)

1.cookie sessionStorage localStorage区别?答:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递cookie数据还有路径(path)的概念,可以限制。cookie只属于某个路径下…

[Vulhub](WooYun-2016-199433)phpmyadmin反序列化漏洞

0x00 预备知识 什么是序列化 序列化 (serialize)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。【将状…

用户指南接口

在AppDelegate在代码 视图控制器里的 版权声明:本文博客原创文章。博客,未经同意,不得转载。 转载于:https://www.cnblogs.com/bhlsheji/p/4747547.html

前端面试题之http/HTML/浏览器(二)

csrf和xss的网络攻击及防范?答:CSRF:跨站请求伪造,可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶意请求,比如用户登录了一个网站后,立刻在另一个ta&#xff42…

使用Spring Cloud休息客户电话

使用Spring-Cloud项目进行REST客户端调用有几种有趣的方法。 Spring-Cloud REST支持建立在核心Netflix OSS库的基础上,但将它们抽象化并在此过程中简化了库的使用。 RestTemplate 首先,让我们考虑使用RestTemplate通过基于Spring的应用程序进行Rest调用…

查看目标主机安装的杀毒软件

命令: wmic /namespace:\\root\securitycenter2 path antivirusproduct GET displayName,productState, pathToSignedProductExe 参考链接:https://stackoverflow.com/questions/42472336/is-there-a-command-to-check-if-there-was-any-antivirus-insta…