• CLR via C#(04)- 本是同根生


    一、等值性——Equals()方法

    有时候我们需要比较两个对象是否相等,比如在一个ArrayList中进行排序查找等操作时。

    System.Object提供了Equals()虚方法:

    class Object

    {

    public virtual Boolean Equals(object o)

    {

    if (this == o) return true;

    else return false;

    }

    }

    这种判断方式非常简单:直接比较是两个引用是否指向的是同一对象。但这样比较是不确切的。所以我们需要重写该方法,提供更合适的实现方式。

    重写时Equals()四大原则?我们在离散数学中好像学过这个呀:

    • 自反。即x.Equals(x)必须为true。
    • 对称。即x.Equals(y)和y.Equals(x)必须返回同样的值。
    • 可传递。即如果x.Equals(y)和y.Equals(z)都返回true,则x.Equals(z)也返回true。
    • 前后一致。如果两个对象的值没变,那么多次比较的值都应该是相同的。

    重写思路

    • 1. 如果参数obj为null,返回false。      因为在非静态方法中,使用this表示的当前对象肯定不是Null。
    • 2. 如果this和obj参数指向同一实例对象,返回true。    这样省略字段比对过程,提高性能。
    • 3. 如果this 和obj参数指向的对象类型不同,则返回false。
    • 4. 比较this和obj中每个实例字段,如果字段不相等则返回false。
    • 5. 调用基类的Equals方法,如果调用结果为false,则返回false;
    • 6. 至此,才能返回true。
    二、惟一性——ReferenceEquals() 方法

    惟一性指两个引用指向同一对象。一旦我们的类重写了Ojbect的Equals方法,我们就不能用它来检测唯一性了。Object提供了另一个静态方法ReferenceEquals()

    public class Object {

    public static Boolean ReferenceEquals(Object objA, Object objB) {

    return (objA == objB);

    }

    }

    但是我们尽量不要在C#中用==操作符来判断唯一性,除非两参数都为Object类型。因为有可能其中一个参数类型会重写==操作符,使他产生了其他语义。

    实例体验?

    class Animal { };

    static void Main(string[] args)
            {
                Animal a1 = new Animal();
                Animal a2 = a1;
                Console.WriteLine(Object.ReferenceEquals(a1, a2));                //true,指向同一对象
                a2 = new Animal();
                Console.WriteLine(Object.ReferenceEquals(a1, a2));                //false,a2重新指向新对象
                int number = 100;
                Console.WriteLine(Object.ReferenceEquals(number, number));//false,值类型Number两次装箱到不同的对象中
                Console.Read();
            }

    三、散列码——GetHashCode() 方法

    System.Object提供了虚方法GetHashCode()从一个对象上得到Int32的散列码。该方法返回的是在整个应用程序域中保证惟一的值,该值在对象整个生存周期内都不会改变。

    如果我们重写了类的Equals()方法,那么我们最好也重写GetHashCode()方法,否则编译器可能会产生警告信息。因为System.Collections.Hashtable类要求两个相等的对象具有相同的散列值。

    四、克隆——ICloneable接口

    如果一个类允许实例被拷贝,则继承ICloneable接口。

    Public interface ICloneable{ object Clone();}

    浅拷贝?

    当对象的字段值被拷贝时,字段引用的对象不会被拷贝。实现时可以调用Object的MemberwiseClone方法即可。

    深拷贝?

    对象实例中字段引用的对象也进行拷贝。深拷贝后,新创建的对象和原对象没有任何公用的东西,改变一个对象时也不会影响另外一个。

  • 相关阅读:
    Nginx 相关介绍(Nginx是什么?能干嘛?)
    springMVC源码学习之:springMVC响应请求的几种方法
    springMvc源码学习之:spirngMvc获取请求参数的方法
    java编程之:org.apache.commons.lang3.text.StrTokenizer
    java的nio之:java的nio的服务器实现模型
    java定时框架:表达式设置
    java的nio之:浅析I/O模型
    java的nio之:unix内核的五种I/O通信模型
    java的nio之:java的bio流下实现的socket服务器同步阻塞模型和socket的伪异步的socket服务器的通信模型
    java.lang.OutOfMemoryError: unable to create new native thread如何解决
  • 原文地址:https://www.cnblogs.com/changrulin/p/4778370.html
Copyright © 2020-2023  润新知