如上例所述,变量a,b和它们的值10,20都是存在栈里面,声明的所以String类型的引用也都是存在栈里。而字符串abc是存在字符串常量池中,new出来的String对象则是存在堆里。

String str="abc";
System.out.print(str==str1);//true

上面这行代码被执行的时候,JVM先到字符串池中查找,看是否已经存在值为”abc”的对象,如果存在,则不再创建新的对象,直接返回已存在对象的引用;如果不存在,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。所以这句代码创建了一个对象

String str1="abc";
System.out.print(str==str2);//true

通过上面的解释这个就清楚了,在执行第二行代码时,”abc”字符串对象在常量池中已存在,所以直接返回池中已存在的那个字符串对象。

String str2="a"+"b"+"c";

由于常量字符串是在编译的时候就也被确定的,又因”a”,”b”和”c”都是常量,因此变量str2的值在编译时就可以确定。这行代码编译后的与String str=”abc”;是一样的,所以这句代码也是只创建了一个对象,但是这与我们平时好像不太一样啊?一般使用“+”连接两个字符串都会产生另一个新的字符对象。下面我们看一下下面这行代码就明白了:

String str3="c";
String str4="ab"+str3;
System.out.print(str==str4);//false
String str5="ab";
System.out.print(str==str6);//false

从上面例子我们就可以得出:使用“+”连接的两个字符串本身就是字面常量字符串时,如果池中存在这样连接后的字符串,则是不会重新创建对象,而是直接引用池中的字符串对象;如果“+”连接的两字符串中只要有一个不是字面常量串(即已经定义过的),会产生新的字符串对象(抛去特殊如final定义字符串不提)。
那我们来看一下有new创建字符串时会有什么不同:

String str7=new String("abc");  

首先、这行代码究竟创建了几个String对象呢?答案是2个。由于new String(“abc”)相当于”abc”,一个就是创建出来的放在堆的原实例对象,而另一个就是放在常量池中的 “aaa” 对象,当然这里的str7本身只是一个引用,放在栈里,用来指向堆中创建出来的对象。

String str7=new String("abc");
String str8=new String("abc");
System.out.print(str7.equals(str8));//true
System.out.print(str7==str8);//false
System.out.print(str==str7);//false

由于str7和str8是连个存在栈里的引用,他们分别创建了两个对象”abc”,虽然他们内容相同(str7.equals(str8)==true),但是实际存在物理地址不同,所以str7==str8值为false,同理,str指向常量池中的”abc”,所以str==str7也是false。

关于常量池,是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。
例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
(1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
(2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。

注意:常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic References),字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念。
所以当然常量池不只是表示字符串常量池,例如一些包装类都实现了常量池技术

基本类型和基本类型的包装类。基本类型有:byte、short、char、int、long、boolean。基本类型的包装类分别是:Byte、Short、Character、Integer、Long、Boolean(注意区分大小写)。
二者的区别是:基本类型体现在程序中是普通变量,基本类型的包装类是类,体现在程序中是引用变量。因此二者在内存中的存储位置不同:基本类型存储在栈中,而基本类型包装类存储在堆中
上边提到的这些包装类都实现了常量池技术,另外两种浮点数类型的包装类则没有实现
如下:

        Integer i1=10;
Integer i2=10;
Integer i3=new Integer(10);
Integer i4=new Integer(10);
System.out.print(i1==i2);//true
System.out.print(i2==i3);//false
System.out.print(i3==i4);//false
Double d1=1.0;
Double d2=1.0;
System.out.print(d1==d2);//false

案例分析:
1)i1和i2均是引用类型,在栈中存储指针,因为Integer是包装类。由于Integer包装类实现了常量池技术,因此i1和i2的10均是从常量池中获取的,均指向同一个地址,因此i1=12。
2)i3和i4均是引用类型,在栈中存储指针,因为Integer是包装类。但是由于他们各自都是new出来的,因此不再从常量池寻找数据,而是从堆中各自new一个对象,然后各自保存指向对象的指针,所以i3和i4不相等,因为他们所存指针不同,所指向对象不同。
3)d1和d2均是引用类型,在栈中存储指针,因为Double是包装类。但Double包装类没有实现常量池技术,因此Doubled1=1.0;相当于Double d1=new Double(1.0);,是从堆new一个对象,d2同理。因此d1和d2存放的指针不同,指向的对象不同,所以不相等。

JAVA String类型和原型模式的更多相关文章

  1. 【java设计模式】-06原型模式

    原型模式简述 定义: 使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象 ,也就是通过复制现有对象实例产生新的对象,也就是所谓的"克隆" 实现方式: 1.实现Cl ...

  2. 《JAVA设计模式》之原型模式(Prototype)

    在阎宏博士的<JAVA与模式>一书中开头是这样描述原型(Prototype)模式的: 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办 ...

  3. java string类型的初始化

    以下基本上是java string类型最常用的三种方法 new string()就不介绍了  基本等同于第三种 String a;  申明一个string类型的 a,即没有在申请内存地址,更没有在内存 ...

  4. Java——string类型与date类型之间的转化

    String类型转化为Date类型 方法一 Date date=new Date("2019-01-25"); 方法二 String =(new SimpleDateFormat( ...

  5. Java设计模式5:原型模式

    原型模式 原型模式属于对象的创建模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意. 原型模式结构 原型模式要求对象实现一个 ...

  6. java设计模式-----5、原型模式

    原型(Prototype)模式是一种对象创建型模式,他采取复制原型对象的方法来创建对象的实例.使用原型模式创建的实例,具有与原型一样的数据. 原型模式的特点: 1.由原型对象自身创建目标对象.也就是说 ...

  7. 重学 Java 设计模式:实战原型模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 老板你加钱我的代码能飞 程序员这份工作里有两种人:一类是热爱喜欢的.一类是仅当成工作 ...

  8. 深度分析:java设计模式中的原型模式,看完就没有说不懂的

    前言 原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象 原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的 ...

  9. java学习笔记之原型模式及深浅拷贝

    一.原型模式的基本介绍 在聊原型模式之前,我们来思考一个小问题,传统的方式我们是如何克隆对象呢? 那我们以多利羊(Sheep)为例,来说明上述这个问题,具体代码见下面: 多利羊(Sheep) publ ...

随机推荐

  1. ListView刷新某一项Item

    ListView现在已经很少被使用,但还是在这里列出来说一下,有时候我们仅仅需要改变listView的某个Item,如果调用adapter的notifyDataSetChanged()方法效率不高,并 ...

  2. 原生Js交互之DSBridge

    文章链接:https://mp.weixin.qq.com/s/Iqd0dKM-ZW4UwkIgSTnvYg 在上一篇文章「android 记一次富文本加载之路」中 介绍了关于android加载富文本 ...

  3. SpringMVC从认识到细化了解

    目录 SpringMVC的介绍 介绍: 执行流程 与strut2的对比 基本运行环境搭建 基础示例 控制器的编写 控制器创建方式: 请求映射问题: 获取请求提交的参数 通过域对象(request,re ...

  4. 微信小程序下拉刷新和上拉加载的实现

    一: 下拉刷新 下拉刷新两个步骤就能实现. 1.在要实现下拉刷新的页面的json配置文件里面加上 "enablePullDownRefresh": true, //开启下拉刷新 & ...

  5. SQLServer之存储过程简介

    存储过程定义 存储的过程 (存储过程(数据库引擎)) 是存储在数据库中的可执行对象. 存储过程分类 系统存储过程   系统存储过程是 SQL Server系统自身提供的存储过程,可以作为命令执行各种操 ...

  6. Python文件操作之把臂入林

    文件操作1.打开文件open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=Tru ...

  7. win10 系统 wifi自动断开连接 wifi热点不稳定

    我的系统的电脑是win10系统,笔记本 下载了一个wifi共享大师,但是wifi总是自动断,于是就找了找问题所在 在网上看了许多方案,大多数都是    在   电源管理  把[允许计算机关闭此设备以节 ...

  8. 把exe注册为windows服务

    1.需要工具 Instsrv.exe(可以给系统安装和删除服务) Srvany.exe(可以让程序以服务的方式运行) 2.运行cmd,输入注册服务命令 "instsrv.exe完整路径&qu ...

  9. python3 shell 中添加清屏

    在windows中: 安装目录 \Lib(  D:\Python37\Lib) 中添加 ClearWindow.py 文件,文件内容: """ Clear Window ...

  10. LeetCode算法题-Array Partition I(Java实现)

    这是悦乐书的第262次更新,第275篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第129题(顺位题号是561).给定一个2n个整数的数组,你的任务是将这些整数分组为n对 ...