不可变对象条件

对象需要满足一下三个条件才是不可变对象:

1、对象创建以后其状态就不能修改

2、对象所有域都是final类型

3、对象是正确创建的(对象在创建期间,this引用没有溢出)

简而言之就是将类声明为final,将所有的成员声明为私有的,对变量不提供set方法。将所有可变的成员声明为final。在get方法中不返回对象本身,而是克隆对象的拷贝。(可参考String类)。

final关键字

final关键字可修饰类、方法和变量。在修饰类时,这个类是不允许被继承。final类中的方法会被隐式的被指定为final方法。修饰方法是为了锁定方法不被继承类修改,即final方法不允许被修改,一个类的private方法会被隐式指定为final类型。final修饰变量可分为两种情况。一、修饰基本数据类型时,一旦被final修饰,这个变量的数值就不能被修改了。二、修饰引用类型变量时,则是让它在初始化之后就不能指向其他对象(可修改该引用变量的成员变量)。例如:

@Slf4j
public class ImmutableExample1 { private final static Integer a = 1;
private final static String b = "2";
private final static Map<Integer, Integer> map = new HashMap(); static {
map.put(1, 2);
map.put(3, 4);
map.put(5, 6);
} public static void main(String[] args) {
map.put(1, 3);
log.info("{}", map.get(1));
}
}

虽然map声明为final对象,但是依然可以往里放入键值对。

Java提供常见不可变对象

Collections.unmodifiableXXX:Collection、List、Set、Map等。

@Slf4j
public class ImmutableExample2 { private static Map<Integer, Integer> map = Maps.newHashMap(); static {
map.put(1, 2);
map.put(3, 4);
map.put(5, 6);
map = Collections.unmodifiableMap(map);
} public static void main(String[] args) {
map.put(1, 3);
log.info("{}", map.get(1));
} }

执行结果如下:

发现执行结果为抛出异常信息,不允许被修改。我们可以用这个方法来修饰不可变的集合对象。

查看源码的主要方法实现:

public class Collections {
// Suppresses default constructor, ensuring non-instantiability.
private Collections() {
} private final Map<? extends K, ? extends V> m; UnmodifiableMap(Map<? extends K, ? extends V> m) {
if (m==null)
throw new NullPointerException();
this.m = m;
} ... ... public V put(K key, V value) {
throw new UnsupportedOperationException();
}
public V remove(Object key) {
throw new UnsupportedOperationException();
}
public void putAll(Map<? extends K, ? extends V> m) {
throw new UnsupportedOperationException();
}
public void clear() {
throw new UnsupportedOperationException();
} ... ... }

其实就是将put方法等直接抛出异常,防止修改。

其他工具提供的不可变对象

Googel常用的工具包Guava同样也提供了很多不可变对象的方法如 ImmutableXXX:Collection、List、Set、Map等。

Java多线程——不可变对象的更多相关文章

  1. 从火箭发场景来学习Java多线程并发闭锁对象

    从火箭发场景来学习Java多线程并发闭锁对象 倒计时器场景 在我们开发过程中,有时候会使用到倒计时计数器.最简单的是:int size = 5; 执行后,size—这种方式来实现.但是在多线程并发的情 ...

  2. Java多线程操作同一个对象,线程不安全

    Java多线程操作同一个对象 发现问题:多个线程操作同一资源的情况下,线程不安全,数据紊乱 代码: package multithreading; // Java多线程操作同一个对象 // 买火车票的 ...

  3. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  4. java String不可变对象,但StringBuffer是可变对象

    什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不 ...

  5. java 多线程访问同一个对象数据保护的问题

    java 多线程同时访问统一个数据的时候,会引起一些错误,后面的线程会修改数据,而前面的线程还在使用修改前的内容, 使用 synchronized 关键字,保证代码块只能有一个线程来访问 public ...

  6. Java多线程对同一个对象进行操作

    示例: 三个窗口同时出售20张票. 程序分析: 1.票数要使用一个静态的值. 2.为保证不会出现卖出同一张票,要使用同步锁. 3.设计思路:创建一个站台类Station,继承THread,重写run方 ...

  7. java多线程系列(二)---对象变量并发访问

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  8. Java多线程编程核心技术---对象及变量的并发访问(一)

    synchronized同步方法 "非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是"脏读",也就是渠道的数据其实是被更改 ...

  9. Java多线程之释放对象的锁

          由于等待一个锁定线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不需要锁的时候及时释放锁是很重要的.在以下情况下,持有锁的线程会释放锁: 1. 执行完同步代码块. 2. 在执行 ...

随机推荐

  1. 12、Django实战第12天:课程机构列表页数据展示

    今天完成的是课程机构列表页.... 1.启动服务,进入xadmin后,添加5个城市信息用作测试数据 2.添加课程机构,其中有一项要上传封面图的地方要注意 封面图上传路径是我们在models中设置好的 ...

  2. RPD Volume 172 Issue 1-3 December 2016 评论04 end

    这一篇作为本期的结束是因为发现后面的一些基本上也是EPR有关的会议内容, Contribution of Harold M. Swartz to In VivoEPR and EPR Dosimetr ...

  3. [BZOJ 1912] patrol 巡逻

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1912 Algorithm: K=0:res=(n-1)*2   每条边恰好走2遍 K=1 ...

  4. iOS 文字渐变色

    // 创建UILabel UILabel *label = [[UILabel alloc] init]; label.text = @"我是渐变的label"; [label s ...

  5. hdu2829 四边形优化dp

    Lawrence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  6. 在WPF 4.5中跨线程更新集合

    WPF中一个非常强大的功能是数据绑定,我们可以把一个集合绑定到ListBox中,当集合的数据发生变更时,ListBox界面也会同步变更.本身这是一个非常美好的事情,但是美中不足的是:当把集合绑定到Li ...

  7. "__doPostBack”未定义的解决办法(转载)

    "__doPostBack”未定义,在IE下调试错误: 问题是服务器版的.Net40的补丁没有打上,ASP.NET 可能无法辨识出一些浏览器的最新版本,还会经常把它们看做是低级的浏览器,不支 ...

  8. SqlServer_删除重复行只保留一条记录

      前提:相同的数据重复往数据库写入,导致存在仅主键Id不同的重复数据,现在需要去除重复数据,仅保留重复数据中Id最大的一条   思路: 1.找出存在重复数据的记录,并取重复数据中最大的Id值 2.删 ...

  9. Intellij IDEA System.out.println输出中文乱码问题

    进行下列设置即可:

  10. IIS5/6/7 ASP.net 请求处理过程

    tks:http://www.cnblogs.com/TomXu/p/3756774.html 主要内容 本文讲解的是:服务器接受Http Request请求之后,是如何进入.Net CLR,从而进一 ...