成都网站建设公司兴田德润在哪儿,云主机免费申请,微网站模板前后台,网站开发的基本功能本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题#xff0c;包括对象创建#xff0c;并发#xff0c;序列化#xff0c;反射等。 它将指导您完成Java掌握的过程#xff01; 在这里查看 #xff01; 目录 1.简… 本文是我们名为“ 高级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 在本教程的这一部分中我们将研究equals hashCode toString和clone方法它们的用法以及需要牢记的重要约束。 2.方法等于和hashCode 默认情况下Java中的任何两个对象引用或类实例引用仅在它们引用相同的内存位置引用相等时才相等。 但是Java允许类通过重写Object类的equals()方法来定义自己的相等性规则。 听起来像一个强大的概念但是正确的equals()方法实现应符合一组规则并满足以下约束 反身的 。 对象x必须等于自身并且equalsx必须返回true 。 对称的 。 如果equalsy返回true则y.equalsx也必须返回true 。 传递的 。 如果equalsy返回true而y.equalsz返回true 则x.equalsz也必须返回true 。 一致 。 除非修改用于相等比较的任何属性否则多次调用equals方法必须得到相同的值。 等于Null 。 equalsnull的结果必须始终为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.Person6104e2ee 让我们尝试改善实现并为我们的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.smithdomain.com );
System.out.println( person.toString() ); 以下输出将在控制台中打印出来 Person[emailjohn.smithdomain.com, first nameJohn, last nameSmith] 不幸的是标准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[emailjohn.smithdomain.com, first nameJohn, last nameSmith]]} Java社区已经开发了两个非常全面的库这些库在很大程度上toString()实现的工作。 其中包括Google Guavas 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