精华内容
下载资源
问答
  • 这个obj到底调用的是Object类的toString方法还是Stirng类的toString方法? 这个obj通过Map,Object>得到 补上前面代码: Map , Object> map = new HashMap(); map.put("id", "32"); System.out....
  • 最近在看Zxing源码,使用IDEA打断点调试时,发现了一个问题, toString() 方法会自动执行,找不到调用它,就百思不得其解. 问题 类 BinaryBitmap 中 toString 方法里面有个赋值语句,给变量 matrix 赋值. 在调试...

    最近在看Zxing的源码,使用IDEA打断点调试时,发现了一个问题, toString() 方法会自动执行,找不到谁调用的它,就百思不得其解.

    问题

    • 类 BinaryBitmap 中的 toString 方法里面有个赋值语句,给变量 matrix 赋值.
    • 在调试过程中,我没有调用该 toString 方法,但断点结果却显示 matrix 有值,而且就是 toString 中的执行结果,
    • 就很纳闷,难道 toString 方法是什么特殊体质?
    • 于是自己仿造类 BinaryBitmap 写了个测试类,看到底是什么原因.

    测试代码

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class TestToString {
        private List<String> list = null;
        private Map<String, String> map = null;
    
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("xiaoming");
            list.add("xiaohua");
            TestToString testToString = new TestToString(list);
    
            // 直接运行结果为null, debugg时会显示 datou
            System.out.println(testToString.map);
        }
    
    
        public TestToString(List<String> list) {
            this.list = list;
        }
    
        @Override
        public String toString() {
            System.out.println("toString");
            if(map == null) {
                Map<String, String> hashMap = new HashMap<>();
                hashMap.put("name", "datou");
                map = hashMap;
            }
    
            return list.toString() + map.toString();
        }
    
    }
    

    运行结果

    • 在第17行打断点,debugger模式下会发现变量 map 是有值的,且执行了 toString 方法中的打印语句.
    • 如果直接运行程序,会发现变量 map 为 null, toString 中的打印语句也没有执行.
    • 所以猜测 toString 方法自动执行和 debugger 模式有关.
    • 在后面多次测试时,发现一个有趣的现象,在 debugger 模式下,鼠标移动到变量 testToString 上面,IDEA 会有一个弹窗,显示该变量的信息,然后控制台就会输出一条 toString 方法中的打印语句.

    总结

    • 最后发现 toString 方法其实是 IDEA 的调试工具调用的,因为它需要调用 toString 方法来在弹框中展示这个变量的信息,并且不会跳转到 toString 方法中的断点.
    • 所以 toString 方法只能由它所属对象来调用是对的,不会出现自动调用的情况,
    • 至于 IDEA 的 Debugger 工具是怎么调用 toString 的,就不清楚了,可能是通过反射吧.
    展开全文
  • 然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实可以被优化。 不过,首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象字符串表示,该结果...

    谁在关心toString的性能?没有人!除非当你有大量的数据在批量处理,使用toString产生了许多日志。然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实是可以被优化的。

    不过,首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象的字符串表示,该结果必须简明但表述详实易懂。建议所有子类重写该方法”。这里最有趣的就是“简明”和“详实”。我们所钟爱的IDE们常常为我们生成equals/hashcode/toString这些方法,且我们通常不再去管它们。此外,这些IDE们提供了许多方式来生成我们自己的toString:字符串连接(使用+号)、StringBuffer、StringBuilder、ToStringBuilder(Commons Lang 3)、 ReflectionToStringBuilder (Commons Lang 3)、Guava或者Objects.toString……该选哪一个?

    如果你想知道哪种toString的实现方式会更高效,不要去猜测,而是去测试!这时你需要用到JMH。我曾在博客上写过有关它的文章,所以这里不再细谈JMH如何工作的细节。

    在该基准测试中,我创建了一个复杂的对象图(使用继承、集合等等),而且我使用到了由IDE生成的所有不同toString的实现方式,来看看哪一种性能更好。就一条经验法则:简洁。无论你使用哪种技术(如下),为一些属性或者所有属性(包括继承、依赖或者集合)生成toSting,对性能会有巨大的影响。

    用 + 连接字符串

    让我们先从最高效的方法开始:用 + 连接字符串。曾经这种被认为是邪恶的使用方式(“不要用 + 连接字符串!!!”),已变得很酷且高效!如今JVM编译器(大部分时候)会把 + 编译成一个string builder。所以,不用犹豫,用它就是了。唯一的缺点是null值不会被处理,你需要自己来处理它。

    看看下面注解中使用JMH统计出来的平均性能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    publicString toString() {
        return"MyObject{" +
                "att1='"+ att1 + '''+
                ", att2='" + att2 + '''+
                ", att3='" + att3 + '''+
                "} " + super.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (140772,314, 142075,167, 143844,717)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (140772,314, 142075,167, 143844,717)

    用Objects.toString连接字符串

    Java SE 7带来了Objects类和它的一些静态方法。Objects.toString的优点是它可以处理null值,甚至可以给null设置默认值。其性能与上一个相比略低,但是null值可以被处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    publicString toString() {
        return"MyObject{" +
                "att1='"+ Objects.toString(att1) + '''+
                ", att2='" + Objects.toString(att2) + '''+
                ", att3='" + Objects.toString(att3) + '''+
                "} " + super.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (138790,233, 140791,365, 142031,847)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (138790,233, 140791,365, 142031,847)

    StringBuilder

    另一种技术是使用StringBuilder。很难讲清哪一种技术性能更好。如我前面所说,我已经使用了复杂的对象图(att1、 att2和att3变量的命名是为了可读性),JMH给出了或多或少相同的结果。后面这三种技术在性能方面非常接近。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    publicString toString() {
        finalStringBuilder sb = newStringBuilder("MyObject{");
        sb.append("att1='").append(att1).append(''');
        sb.append(", att2='").append(att2).append(''');
        sb.append(", att3='").append(att3).append(''');
        sb.append(super.toString());
        returnsb.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (96073,645, 141463,438, 146205,910)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (96073,645, 141463,438, 146205,910)

    Guava

    Guava有一些helper类:其中一个可以帮助你生成toString。这比纯JDK API性能要差一点,但是它可以提供给你一些额外的服务(我这里指的Guava):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    publicString toString() {
        returnObjects.toStringHelper(this)
        .add("att1", att1)
        .add("att2", att2)
        .add("att3", att3)
        .add("super",super.toString()).toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (97049,043, 110111,808, 114878,137)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (97049,043, 110111,808, 114878,137)

    Commons Lang3

    Commons Lang3有一些技术来生成toString:从builder到 introspector。如同你猜测到的,introspection更容易使用,代码量更少,但是性能比较糟糕:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    publicString toString() {
        returnnew ToStringBuilder(this)
        .append("att1", att1)
        .append("att2", att2)
        .append("att3", att3)
        .append("super",super.toString()).toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = ( 73510,509,  75165,552,  76406,370)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = ( 73510,509,  75165,552,  76406,370)
     
    publicString toString() {
        returnToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (31803,224, 34930,630, 35581,488)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) =(31803,224, 34930,630, 35581,488)
     
    publicString toString() {
        returnReflectionToStringBuilder.toString(this);
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (14172,485, 23204,479, 30754,901)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (14172,485, 23204,479, 30754,901)

    总结

    如今有了JVM优化,我们可以安全使用+来连接字符串(及使用Objects.toString来处理null)。有了内置到JDK的实用工具类,不需要外部框架来处理null值。因此,与本文中讲述的其它技术相比,开箱即用的JDK拥有更好的性能(如果你有其它的框架/技术,请留下评论我来试试看)。

    作为总结,下面是一个从JMH得到的平均性能数据表格(从最高效依次递减)

    使用技术 平均操作次数/秒
    用’+'连接字符串 142.075,167
    String builder 141.463,438
    Objects.toString 140.791,365
    Guava 110.111,808
    ToStringBuilder (append) 75.165,552
    ToStringBuilder (reflectionToString) 34.930,630
    ReflectionToStringBuilder 23.204,479

    再说一次,如果你经常调用toString方法,这是很重要的。否则,性能就真不是个事。

    原文链接: Antoniogoncalves.org 翻译: ImportNew.com 无名侠女谭

    译文链接: http://www.importnew.com/16382.html

    from: http://www.importnew.com/16382.html

    展开全文
  • toString的性能

    2019-10-08 04:07:09
    然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实可以被优化。 不过,首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象字符串表示,该结果...

    谁在关心toString的性能?没有人!除非当你有大量的数据在批量处理,使用toString产生了许多日志。然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实是可以被优化的。

    不过,首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象的字符串表示,该结果必须简明但表述详实易懂。建议所有子类重写该方法”。这里最有趣的就是“简明”和“详实”。我们所钟爱的IDE们常常为我们生成equals/hashcode/toString这些方法,且我们通常不再去管它们。此外,这些IDE们提供了许多方式来生成我们自己的toString:字符串连接(使用+号)、StringBuffer、StringBuilder、ToStringBuilder(Commons Lang 3)、 ReflectionToStringBuilder (Commons Lang 3)、Guava或者Objects.toString……该选哪一个?

    如果你想知道哪种toString的实现方式会更高效,不要去猜测,而是去测试!这时你需要用到JMH。我曾在博客上写过有关它的文章,所以这里不再细谈JMH如何工作的细节。

    在该基准测试中,我创建了一个复杂的对象图(使用继承、集合等等),而且我使用到了由IDE生成的所有不同toString的实现方式,来看看哪一种性能更好。就一条经验法则:简洁。无论你使用哪种技术(如下),为一些属性或者所有属性(包括继承、依赖或者集合)生成toSting,对性能会有巨大的影响。

    用 + 连接字符串

    让我们先从最高效的方法开始:用 + 连接字符串。曾经这种被认为是邪恶的使用方式(“不要用 + 连接字符串!!!”),已变得很酷且高效!如今JVM编译器(大部分时候)会把 + 编译成一个string builder。所以,不用犹豫,用它就是了。唯一的缺点是null值不会被处理,你需要自己来处理它。

    看看下面注解中使用JMH统计出来的平均性能。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public String toString() {
        return "MyObject{" +
                "att1='" + att1 + ''' +
                ", att2='" + att2 + ''' +
                ", att3='" + att3 + ''' +
                "} " + super.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (140772,314, 142075,167, 143844,717)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (140772,314, 142075,167, 143844,717)

    用Objects.toString连接字符串

    Java SE 7带来了Objects类和它的一些静态方法。Objects.toString的优点是它可以处理null值,甚至可以给null设置默认值。其性能与上一个相比略低,但是null值可以被处理:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public String toString() {
        return "MyObject{" +
                "att1='" + Objects.toString(att1) + ''' +
                ", att2='" + Objects.toString(att2) + ''' +
                ", att3='" + Objects.toString(att3) + ''' +
                "} " + super.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (138790,233, 140791,365, 142031,847)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (138790,233, 140791,365, 142031,847)

    StringBuilder

    另一种技术是使用StringBuilder。很难讲清哪一种技术性能更好。如我前面所说,我已经使用了复杂的对象图(att1、 att2和att3变量的命名是为了可读性),JMH给出了或多或少相同的结果。后面这三种技术在性能方面非常接近。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public String toString() {
        final StringBuilder sb = new StringBuilder("MyObject{");
        sb.append("att1='").append(att1).append(''');
        sb.append(", att2='").append(att2).append(''');
        sb.append(", att3='").append(att3).append(''');
        sb.append(super.toString());
        return sb.toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (96073,645, 141463,438, 146205,910)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (96073,645, 141463,438, 146205,910)

    Guava

    Guava有一些helper类:其中一个可以帮助你生成toString。这比纯JDK API性能要差一点,但是它可以提供给你一些额外的服务(我这里指的Guava):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public String toString() {
        return Objects.toStringHelper(this)
        .add("att1", att1)
        .add("att2", att2)
        .add("att3", att3)
        .add("super", super.toString()).toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (97049,043, 110111,808, 114878,137)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (97049,043, 110111,808, 114878,137)

    Commons Lang3

    Commons Lang3有一些技术来生成toString:从builder到 introspector。如同你猜测到的,introspection更容易使用,代码量更少,但是性能比较糟糕:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public String toString() {
        return new ToStringBuilder(this)
        .append("att1", att1)
        .append("att2", att2)
        .append("att3", att3)
        .append("super", super.toString()).toString();
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = ( 73510,509,  75165,552,  76406,370)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = ( 73510,509,  75165,552,  76406,370)
     
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (31803,224, 34930,630, 35581,488)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) =(31803,224, 34930,630, 35581,488)
     
    public String toString() {
        return ReflectionToStringBuilder.toString(this);
    }
     
    // Average performance with JMH (ops/s)
    // (min, avg, max) = (14172,485, 23204,479, 30754,901)
    // 使用JMH测出来的平均性能
    // (最小, 平均, 最大) = (14172,485, 23204,479, 30754,901)

    总结

    如今有了JVM优化,我们可以安全使用+来连接字符串(及使用Objects.toString来处理null)。有了内置到JDK的实用工具类,不需要外部框架来处理null值。因此,与本文中讲述的其它技术相比,开箱即用的JDK拥有更好的性能(如果你有其它的框架/技术,请留下评论我来试试看)。

    作为总结,下面是一个从JMH得到的平均性能数据表格(从最高效依次递减)

    使用技术平均操作次数/秒
    用’+'连接字符串 142.075,167
    String builder 141.463,438
    Objects.toString 140.791,365
    Guava 110.111,808
    ToStringBuilder (append) 75.165,552
    ToStringBuilder (reflectionToString) 34.930,630
    ReflectionToStringBuilder 23.204,479

    再说一次,如果你经常调用toString方法,这是很重要的。否则,性能就真不是个事。

    转载于:https://www.cnblogs.com/atwanli/articles/4899233.html

    展开全文
  • 一、Object类介绍 Object类在JAVA里面是一个比较特殊类,JAVA只支持单继承,子类只能从一个父类来继承,...所有类,不管是谁,都是从它继承下来。 二、toString方法介绍 一个字符串和另外一种类型连接

    一、Object类介绍

    Object类在JAVA里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能有一个,JAVA为了组织这个类组织得比较方便,它提供了一个最根上的类,相当于所有的类都是从这个类继承,这个类就叫Object。所以Object类是所有JAVA类的根基类,是所有JAVA类的老祖宗。所有的类,不管是谁,都是从它继承下来的。

    二、toString方法介绍

    一个字符串和另外一种类型连接的时候,另外一种类型会自动转换成String类型,然后再和字符串连接。基础的数据类型int,float,double转换成字符串比较简单,按照它们的数字转换过来就成了,可以引用类型呢,Person p = new Person();一个字符串加上这个p,你就不知道要怎么把这个p转换成字符串了,因为这个p是一个引用类型。

    public class TestToString {
    
        public static void main(String[] args) {
            Dog d = new Dog();
            /**
             * 如果没有重写toString方法,那么输出来的默认的字符串内容是“类名+哈希编码”,
             * 如:dog=cn.galc.test.Dog@150bd4d
             * 这里的d就是一个引用类型,打印的时候,这个引用类型d会自动调用toString()方法将自己转换成字符串然后再与字符串”d:=”相连,
             * 然后一起被打印出来。d为什么可以自动调用toString()方法呢,Dog类里面也没有声明这个toString()方法。
             * 这是因为toString()方法是Object类里面的方法,而所有的类都是从Object类继承下来的,
             * Dog类当然也不例外,所以Dog类继承了Object类里面的toString()方法,
             * 所以Dog类的对象当然可以直接调用toString()方法了。
             * 但是Dog类对继承下来的toString()方法很不满意,
             * 因为使用这个继续下来toString()方法将引用对象转换成字符串输出时输出的是一连串令人看不懂的哈希编码。
             * 为了使打印出来的信息使得正常人都能看得懂,因此要在Dog类里面把这个继承下来的toString()方法重写,
             * 使得调用这个toString()方法将引用对象转换成字符串时打印出来的是一些正常的,能看得懂的信息。
             * 在子类重写从父类继承下来的方法时,从父类把要重写的方法的声明直接copy到子类里面来,
             * 这样在子类里面重写的时候就不会出错了。
             */
            System.out.println("dog="+d);//打印结果:dog=I’m a cool Dog
        }
    }
    
    class Dog{
        /**
         * 在这里重写了Object类里面的toString()方法后,
         * 引用对象自动调用时调用的就是重写后的toString()方法了,
         * 此时打印出来的显示信息就是我们重写toString()方法时要返回的字符串信息了,
         * 不再是那些看不懂的哈希编码了。
         */
        public String toString() {
            return "I’m a cool Dog";
        }
    }

    任何一个类都是从Object类继承下来的,因此在任何一个类里面都可以重写这个toString()方法。toString()方法的作用是当一个引用对象和字符串作连接的时候,或者是直接打印这个引用对象的时侯,这个引用对象都会自动调用toString()方法,通过这个方法返回一个表示引用对象自己正常信息的字符串,而这个字符串的内容由我们自己去定义,默认的字符串内容是“类名+哈希编码”。因此我们可以通过在类里面重写toString()方法,把默认的字符串内容改成我们自己想要表达的正常信息的字符串内容。

    三、equals方法介绍

    通过下面的例子掌握equals的用法

    public class TestEquals {
        public static void main(String[] args) {
            /**
             * 这里使用构造方法Cat()在堆内存里面new出了两只猫,
             * 这两只猫的color,weight,height都是一样的,
             * 但c1和c2却永远不会相等,这是因为c1和c2分别为堆内存里面两只猫的引用对象,
             * 里面装着可以找到这两只猫的地址,但由于两只猫在堆内存里面存储在两个不同的空间里面,
             * 所以c1和c2分别装着不同的地址,因此c1和c2永远不会相等。
             */
            Cat c1 = new Cat(1, 1, 1);
            Cat c2 = new Cat(1, 1, 1);
            System.out.println("c1==c2的结果是:"+(c1==c2));//false
            System.out.println("c1.equals(c2)的结果是:"+c1.equals(c2));//false
        }
    }
    
    class Cat {
        int color, weight, height;
    
        public Cat(int color, int weight, int height) {
            this.color = color;
            this.weight = weight;
            this.height = height;
        }
    }

    画出内存分析图分析c1和c2比较的结果

    程序:

    Cat c1 = new Cat(1,1,1);

    Cat c2 = new Cat(1,1,1);

    执行完之后内存之中的布局如下图所示:

    c1指向一个对象,c2也指向一个对象,c1和c2里面装着的是这两只Cat对象在堆内存里面存储的地址,由于这两只Cat对象分别位于不同的存储空间,因此c1和c2里面装着的地址肯定不相等,因此c1和c2这两个引用对象也肯定不相等。因此执行:“System.out.println(c1==c2);”打印出来的结果肯定是false。因此你new出来了两个对象,你放心,这两个对象的引用永远不一样,一样的话就会把其中一个给覆盖掉了,这个可不成。c1是不是等于c2比较的是c1和c2这两个引用里面装着的内容,因为new出来的两个对象的它们的引用永远不一样,因此c1和c2这两个引用的内容也永远不一样,因此c1永远不可能等于c2。因此通过比较两个对象的引用是永远无法使得两个对象相等的,一模一样的。

    要想判断两个对象是否相等,不能通过比较两个对象的引用是否相等,这是永远都得不到相等的结果的,因为两个对象的引用永远不会相等,所以正确的比较方法是直接比较这两个对象,比较这两个对象的实质是不是一样的,即这两个对象里面的内容是不是相同的,通过比较这两个对象的属性值是否相同而决定这两个对象是否相等。

    Object类提供了一个equals()方法来比较两个对象的内容是否相同,因此我们可以采用这个方法去比较两个对象是否在逻辑上“相等”。如:c1.equals(c2);这里是调用从Object类继承下来的equals()方法,通过查阅API文档得到Object类里的equals方法的定义如下:

    public boolean equals(Object obj)

    在Object这个类里面提供的equals()方法默认的实现是比较当前对象的引用和你要比较的那个引用它们指向的是否是同一个对象,即和“c1==c2”这种写法是一样的,“c1.equals(c2)”与“c1==c2”是完全等价的。因此直接使用继承下来的equals()方法也是无法直接比较两个对象的内容是否相同的,为此,我们必须得重写equals()方法,改变这个方法默认的实现。

    下面在Cat类里面重写这个继承下来的equals()方法

    class Cat {
        int color, weight, height;
    
        public Cat(int color, int weight, int height) {
            this.color = color;
            this.weight = weight;
            this.height = height;
        }
    
        /**
         * 这里是重写相等从Object类继承下来的equals()方法,改变这个方法默认的实现,
         * 通过我们自己定义的实现来判断决定两个对象在逻辑上是否相等。
         * 这里我们定义如果两只猫的color,weight,height都相同,
         * 那么我们就认为这两只猫在逻辑上是一模一样的,即这两只猫是“相等”的。
         */
        public boolean equals(Object obj){
            if (obj==null){
                return false;
            }
            else{
                /**
                 * instanceof是对象运算符。
                 * 对象运算符用来测定一个对象是否属于某个指定类或指定的子类的实例。
                 * 对象运算符是一个组合单词instanceof。
                 * 该运算符是一个双目运算符,其左边的表达式是一个对象,右边的表达式是一个类,
                 * 如果左边的对象是右边的类创建的对象,则运算结果为true,否则为false。
                 */
                if (obj instanceof Cat){
                    Cat c = (Cat)obj;
                    if (c.color==this.color && c.weight==this.weight && c.height==this.height){
                        return true;
                    }
                }
            }
            return false;
        }
    }

    此时在main方法里面执行打印的命令:

    public static void main(String[] args) {
            /**
             * 这里使用构造方法Cat()在堆内存里面new出了两只猫,
             * 这两只猫的color,weight,height都是一样的,
             * 但c1和c2却永远不会相等,这是因为c1和c2分别为堆内存里面两只猫的引用对象,
             * 里面装着可以找到这两只猫的地址,但由于两只猫在堆内存里面存储在两个不同的空间里面,
             * 所以c1和c2分别装着不同的地址,因此c1和c2永远不会相等。
             */
            Cat c1 = new Cat(1, 1, 1);
            Cat c2 = new Cat(1, 1, 1);
            System.out.println("c1==c2的结果是:"+(c1==c2));//false
            System.out.println("c1.equals(c2)的结果是:"+c1.equals(c2));//true
    }

    这一次得到的结果就与上次没有重写equals()方法时得到的结果就不一样了:

    “System.out.println(c1 == c2);”打印出来的结果依然是false,因为这里是比较两个对象的引用里面的内容,这两个引用里面的内容当然不相等,而且永远不会相等,所以打印出来的结果肯定是false。

      “System.out.println(c1.equals(c2));”打印出来的结果为true,因为我们在Cat类里面重写了equals()方法,改变了这个方法默认的实现,我们把方法的实现改为只要这个两个对象是真的存在,并且都是猫,并且它们的颜色(color),身高(height)和体重(weight)都相同,那么这两只猫在逻辑上就是一模一样的,是完全相同的两只猫,即这两只猫是“相等”的。所以这里打印出来的结果是true。

    如何比较两个字符串对象是否相等?

    public class TestEquals {
    
        public static void main(String args[]){
            String s1 = new String("hello");
            String s2 = new String("hello");
            System.out.println("s1 == s2的结果是:"+(s1 == s2));//false
            System.out.println("s1.equals(s2)的结果是:"+s1.equals(s2));//true
        }
    }

    这一次是比较两个字符串对象是否相等:

    System.out.println(s1 == s2);

    打印出来的结果依然是fase,因为这里比较的是s1和s2两个字符串对象的引用,两个对象的引用永远不会相等,所以打印出来的结果为false。

    System.out.println(s1.equals(s2));

    打印出来的结果为true,因为在String类里面重写了从Object类继承(所有的类都是从Object类继承下来,String类当然也不例外,从父类继承下来就拥有了父类的一切属性与方法,所以Sting类里面也有equals()方法,并且还把这个继承下来的equals()方法重写了)下来的equals()方法,改变了这个方法默认的实现。

    在String类里面是这样重写equals()方法的实现的:用当前的这个字符串对象和指定的字符串对象比较,指定的字符串对象不能为空并且这个对象的字符序列和当前这个字符串对象的字符串序列一样,如果这些条件都满足,那么这两个字符串对象就是相等的。

    因此这里的s2已经满足了条件,所以打印出来的结果是true。

    以后在某一个类里面比较两个对象是否相等时,首先去API文档里面查找这个类是否重写了从Object类继承下来的equals()方法。如果重写了equals()方法,那么在比较两个对象是否相等时调用的就是重写以后的equals()方法,如果没有重写,那么调用时就是直接调用从Object类里面的继承下来的那个equals()方法,并且采用equals()方法默认的实现去比较两个对象是否相等。因此每一个类都可以根据需要对从Object类继承下来的equals()方法进行重写。

      对于在API文档里面找某个类,如果一个类不用引入包就可以直接使用,那么这个类肯定是在java.lang这个包里面,如这里的String类,直接就可以使用了,所以String类一定是在java.lang这个包里面。使用某个类时看这个类引入的是哪个包,然后就去这个包里面找这个类,不用引入包的类一定是位于java.lang里面,直接去java.lang里面找就可以了。

      总结:比较两个对象是否相等,我们采用equals()方法,判断两个对象是否相等的条件是由我们重写equals()方法的实现后定义的,这样就可以比较灵活地使用equals()方法在不同的类里面比较位于同一类下的两个对象是否相等了。

    展开全文
  • 然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实可以被优化。  不过,首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象字符串表示,该...
  • 看源码也没看明白,Throwable中的this是谁的对象啊,为啥转String之后就变成了“ExcpetionTest.CustomException: 自定义的异常toString”。 初始化的时候也没看见获取重写的那两个方法的相关代码,这俩重写的方法...
  • 然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实可以被优化。 不过,首先让我们一起看看Javadoc回忆下Object.toString应 当做什么:“返回该对象字符串表示,该...
  • start()和run()开始时候总是记不住那个线程启动方法,现在记得很真切了! 如果用run()启动线程就跟不用线程效果一样,因为run顺序执行。start()才线程启动方法。做了个测试类: 用一个for...
  • 这行代码可以正确执行你想要的方法,问题是,这个super是谁呢? 返回super.toString()竟然是Location。 不是应该继承自Object的吗?super为什么不是Object? 还有,这个clone方法到底是怎么...
  • 然后,你去调查为何如此之慢,才意识到大部分的toString方法使用的是introspection,它其实可以被优化。 不过,首先让我们一起看看Javadoc回忆下Object.toString应 当做什么:“返回该对象字符串表示,该结果...
  • 如题、。请问知道有啊。toString() 好像打印不出来这种基本数据类型与包装类
  • 背景介绍 一、 1、面向对象一些属性和方法?...constructor查看实例对象是谁构造出来 instanceof运算符查看实例对象和构造函数是否在一条原型链上 tostring是用来做类型判断 二、知识剖析 hasOwnPrope...
  • 这个是上次在博客园看到一篇文章,经测试,确实比jquery$(document).ready(function(){….})更快,并且在ie和火狐等主流浏览器上都没问题, 忘了原创是谁了,如果主人看到可以联系我, 我会立刻加上原文出处,...
  • 大神时间到了~下面这段代码每一个函数和里边的方法什么意思,用来干嘛的?能说得详细~绝对虚心求教 ``` package com.sysgrrj.module.QTCSSZ.action; import com.sysgrrj.core.action.BaseAction; import ...
  • c#检测有效串口的方法

    千次阅读 2013-07-18 12:45:33
    目前,我已知的方法有两种。 第一种是在网上百度到的,已经不知道原作者是谁了。  for (int i = 0; i  {  try  {  SerialPort sp = new SerialPort("COM" + (i + 1).ToString());
  • 简单类型(基本类型): number,string,boolean,null,undefined 复杂类型(引用类型):object typeof 只能判断基本...constructor:判断对象构造函数是谁 Object.prototype.toString.call(arr); Array.isArray(arr)—...
  • 我们知道JavaScript提供了typeof运算符,因此最容易想到的是用typeof来判断是否number类型。 代码如下: function isNumber(obj) {  return typeof obj === ‘number’ } 这个函数对于整数和浮点数都没有问题,...
  • 原作者也不知道是谁了,使用过程中发现了几个小问题,稍微改动了下,完善代码如下: function isObj(object) { return object && typeof(object) == 'object' && Object.prototype....
  • Spring之构造方法注入

    2018-03-08 11:22:00
    1.新建实体类Car,并创建两个构造器,其实toString方法是为了测试用,方便学习,在具体生产业务中没会闲没事建造一个toString方法 public class Car { private String brand; private String corp; ...
  • Java里面字符串拼接,估计使用的最多的,经常使用的就是几种方式,谁的效率高呢: 1,直接使用“+”来拼接字符串 2,使用字符串自带的contact()方法 3,使用StringBuffer的append()和toString()方法 4,使用...
  • 1:用怎样函数写?2:怎样把这个字符串本身传进去? 3:把得到结果连起来成整体? 1种 ... String.prototype.repeat=function(item){ var arr=[];...//这个this指的是谁tostring把它变成了什么?} r...
  • 重点在于判断 对象 小尤其比较类对象小”打印类对象 print(a) 必须在类里要重写 toString() 方法@Overridepublic String toString(){return this.food+"";//后面那个双引号为了把整个转成字符...
  • 尤其比较类对象小” 打印类对象 print(a) 必须在类里要重写 toString() 方法 @Override public String toString(){ return this.food+"";//后面那个双引号为了把整个转成字符串。不能直接...
  • 今天学的是Objectequals,它没有被重写。...先把刚才重写的toString方法注释掉。 、 出了p1和p2地址值,显然结果false。两个地址值不一样 把p2值赋值给p1 那么p1和p2地址值就是一样...

空空如也

空空如也

1 2 3 4 5
收藏数 84
精华内容 33
关键字:

tostring是谁的方法