首页 > 技术文章 > java的对象及引用

ls-shiyi 2019-06-30 15:39 原文

前言

        java虽说是“一切皆对象”,但是也会引出一系列的关于对象创建的问题。如 String str1 = new String(“aaabb”); 和 String str2 = “aaabb”; 的区别,抑或是上述两个语句创建了多少个对象,(str1==str2) ? 这些说法其实我在之前也是不太确定,仅有一些模糊的认识,接下来就一起学习一下。

正文

关于对象引用

        首先避开string不谈,string这个比较特殊,我们先引入一个普通的对象,如User;

User user1;
user1 = new User("张三");

User user2 = new User("李四");

        上面两个对象的创建有什么区别吗?肯定是有的,其中对于user1来说,第一步只是先创建了一个user1类型的引用,而第二步,才是在jvm的堆中实例化了一个User对象,完成了整个对象的创建。

        而如果user1类型的对象引用在第一步时指向哪里呢,应该是指向了null,null作为java的一种特殊类型,我觉得既不能叫一种变量,也不能叫做一个对象,因为实在是太特殊了,两种类型的特性都和它不吻合。因此得出结论,User user1 = new User(“张三”); 这个语句创建了两个对象,一个是User类型的引用对象,在jvm的栈中,实例化的对象则在jvm的堆中。

String的对象及引用

        String相较于普通对象有些特殊,那我们依旧把String拉出来,创建对象和引用,如下:

String str1;
str1 = new String("123");

String str2 = new String("123");

String str3 = "123";

        我们依旧是和上面的操作方式一样,创建了str1和str2,因此二者的区别还是是单独创建对象引用和对象实例化。但String有另外的创建方式,就是str3,str3的创建方式是这样的:先去jvm字符串常量池中寻找有没有 "123"的字符串常亮,如果有的话,则直接进行引用的赋值;如果没有,则在常量池中创建"123"字符串,再进行引用赋值。因此又引出了对于String对象的==和.equals的的对比使用。如下:

        String str1 = "123";
        String str2 = "123";
        String str3 = new String("123");
        String str4 = new String("123");
        System.out.println("str1==str2:"+(str1==str2));
        System.out.println("str3==str4:"+(str3==str4));
        System.out.println("str1==str3:"+(str1==str3));
        System.out.println("str1.euqals(str3):"+(str1.equals(str3)));
————————————————————————————————————————————————————————————————————
str1==str2:true
str3==str4:false
str1==str3:false
str1.euqals(str3):true

        结果如上,也就是说,直接创建的相同内容的string,是在常量池中,因此引用对象指向的地址为同一个;而使用new String进行实例化的String类型,每次都是在栈中新建一个对象。

常量池

        关于常量池,又是另外一个知识了,在java中,很多包装类型都有自己的常量池,甚至有已经初始化的常量。包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。

        因此在使用Integer类型时,即使使用了==这个操作符来比较大小,在-128-127之间都还是有效的,但如果不在这个范围内使用,便会出问题,因此对于对象的比较来说,还是需要用专有的比较大小的方法,否则就是一个bug。

结语

        这篇文章探索了java中的对象与引用及部分常量池的使用及误区,对于String类型来说,还可以选择将这个String对象强行加入至常量池中,具体可见intern方法 https://www.cnblogs.com/guozhenqiang/p/5633269.html

推荐阅读