java的不可变类

1、Integer

public static void main(String[]args) {
       Integer i=new Integer(1);
       System.out.println(i.intValue());
       i=2;
       System.out.println(i.intValue());
}

我们知道Integer的属性value的类型为:final int value;

而方法intValue就是返回value。

很显然,上面两次打印结果是不同的,而都是同一个引用变量i。然道我们对置为1的Integer实例做了修改,将其value值变成了2?

很显然,这种结论是不正确的,因为它违反了final修饰变量的特性。

1 public class Test {
2     public static void main(String[]args) {
3         Integer i=new Integer(1);
4         System.out.println(System.identityHashCode(i));
5         i=2;
6         System.out.println(System.identityHashCode(i));
7     }
8 }

通过这段代码,可知,value值为1的实例和value值为2的实例是两个不同的实例。正如上说,因为value属性是由final修饰的,因此这个类是不可变的。

内存空间释义图如下:

由释义图可知,改变了value值,其实就是新生成了一个空间,改变引用变量的指示方向;而原先那个value值为1的实例就变成了游离的实例,成为java虚拟机回收的对象目标。正因为,要想改变value就得重启一个空间,这是比较消耗性能的,因此Integer会对[-128,127]范围类的值的实例缓存下来。

2、String

其属性类型为final char value[];

因此String类也是不可变的。

和Integer一样,改变value值就得新开辟一个空间,这也是性能上的一种消耗,因此,Java给String的字面量也提供了缓存,如果某个字符串的字面量能够

在缓存池当中找到那么就会复用(编译阶段完成的)。

 1     public static void main(String[]args) {
 2         String str1="feijishuo";
 3         String str2="feijishuo";
 4         System.out.println(str1==str2); //true
 5
 6         String str3="feiji";
 7         String str4="fei";
 8         String str5="ji";
 9         String str6="fei"+"ji";
10         String str7=str4+str5;
11         System.out.println(str3==str6); //true
12         System.out.println(str3==str7); //false13         14         final String Str8="fei";15         String str9=str8+"ji";16         System.out.println(str3==str9); //true17    }

代码分析:str1和str2指向同一个实例,那是因为字面相同,它们会存在于缓存池(编译时常量池)当中。

str3和str6指向同一个实例,因为字面量“fei”和“ji”在编译时就确定下来了,那么str6在编译时候也能确定下来,然后这个字面量已经在

缓存池(编译时常量池)当中存在了,因此就不用生成新的实例了,只要将引用变量指向存在的实例即可。

str3和str7不是同一个实例,因为变量只有在运行期间才能知道其所指示的值。

str3和str9是同一个实例,因为变量str8定义为final类型的,因此其在编译期间就能确定下来。其实例已经存在常量池(编译时常量池)当中

存在,因此不会生成新的实例。于是,构成str9的式子都能在编译期间在常量池中找到,因此str9在编译期间也就确定了下来,其实例在常量池中已经存       在。

时间: 2025-01-18 01:11:12

java的不可变类的相关文章

Java 的不可变类 (IMMUTABLE CLASS) 和 可变类 (MUTABLE CLASS)

一.简单定义不可变对象(Immutable Objects)即对象一旦被创建,它的状态(对象的数据,也即对象属性值)就不能改变,反之即为可变对象(Mutable Objects).当满足以下条件时,对象才是不可变的:1. 对象创建以后其状态就不能修改.2. 对象的所有域都是final类型.3. 对象是正确创建的(在对象的创建期间,this引用没有逸出).不可变对象的类即为不可变类(Immutable Class).Java平台类库中包含许多不可变类,如String.基本类型的包装类.BigInt

java 构造不可变类集的使用方法

首先用到的就是Collections.unmodifiablexxx()这个函数 剩下的见下面的代码. 据说这个函数有bug,于是乎出了guava 1 import java.util.Collection; 2 import java.util.Collections; 3 import java.util.HashSet; 4 import java.util.Set; 5  6  7 public class Guava { 8     public static void main(St

Java中的不可变类

本文与个人博客 zhiheng.me 同步发布,标题: Java中的不可变类. 不可变类(Immutable Objects):当类的实例一经创建,其内容便不可改变,即无法修改其成员变量. 可变类(Mutable Objects):类的实例创建后,可以修改其内容. Java 中八个基本类型的包装类和 String 类都属于不可变类,而其他的大多数类都属于可变类. 与引用不可变的区别 需要特别注意的是,不可变类的不可变是指该类的实例不可变而非指向该实例的引用的不可变. String s = "ab

深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/details/26744661),看代码和提问.讨论都更方便. Java中final的作用主要表如今三方面:修饰变量.修饰方法和修饰类.以下就从这两个方面来解说final的作用.在文末从final及类的设计安全性出发,论述了Java中String为何要被设计成不可变类. 1.final修饰变量 fina

《Java中的不可变类》

1 //不可变类举例: 2 /* 3 下面程序试图定义一个不可变类Person类,但=因为Person类包含一个引用类型的成员变量, 4 且这个引用类是可变类,所以导致Person类也变成了可变类. 5 */ 6 class Name1 7 { 8 private String firstName; 9 private String lastName; 10 public Name1(){} 11 public Name1(String firstName,String lastName) 12

【Java基础】JAVA不可变类(immutable)机制与String的不可变性

一.不可变类简介 不可变类:所谓的不可变类是指这个类的实例一旦创建完成后,就不能改变其成员变量值.如JDK内部自带的很多不可变类:Interger.Long和String等. 可变类:相对于不可变类,可变类创建实例后可以改变其成员变量值,开发中创建的大部分类都属于可变类. 下面的理解可能会易懂一些: {概念:不可变类的意思是创建该类的实例后,该实例的属性是不可改变的.Java中的8个包装类和String类都是不可变类.所以不可变类并不是指该类是被final修饰的,而是指该类的属性是被final修

JAVA不可变类(immutable)机制与String的不可变性

不可变类:是指这个类实例一旦创建,就不能不该其成员变量的值 优点: 1.线程安全 对象的值无法改变,降低并发错误的可能性 2.效率高 当一个对象需要复制时,就只需要复制对象地址,不用复制本生 不变性,保证了hashcode的唯一性,每次缓存时不必重新计算hashcode,所以常用string作为key 3.便于测试 而且如果程序里的变量都是immutable 的话 side effect就比较小 程序只要写好测一遍基本没有什么bug 缺点: 每一次改变都需要产生新的对象,容易产生很多垃圾 设计方

Java面向对象进阶篇(包装类,不可变类)

一. Java 8的包装类 Java中的8种基本数据类型不支持面向对象的变成机制,也不具备对象的特性:没有成员变量,方法可以调用.为此,Java为这8 种基本数据类型分别提供了对应的 包装类(Byte,Short,Integer,Long,Double,Float,Charater,Boolean). 从jdk 1.5开始,Java提供了自动装箱和自动拆箱的功能.自动装箱就是可以把一个基本类型变量赋给对应的包装类变量.自动拆箱与之相反. 包装类提供了基本类型变量和字符串之间的转换的方法.有两种方

JAVA不可变类与可变类、值传递与引用传递深入理解

一个由try...catch...finally引出的思考,在前面已经初步了解过不可变与可变.值传递与引用传递,在这里再次深入理解. 1.先看下面一个try..catch..finally的例子: Person.java package cn.qlq.test; public class Person { private int age; private String name; public int getAge() { return age; } public void setAge(int