• Java多线程——不可变对象


    不可变对象条件

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

    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等。

  • 相关阅读:
    爬虫
    vue进级
    el-upload加header
    上传图片到服务器报错 {errMsg: "uploadFile:fail ssl hand shake error"}
    【Node.js】论一个低配版Web实时通信库是如何实现的1( WebSocket篇)
    【Node.js】 bodyparser实现原理解析
    【JavaScript】EventEmitter的前端实现
    【JavaScript】当我们尝试用JavaScipt测网速
    git命令
    【Java】利用注解和反射实现一个"低配版"的依赖注入
  • 原文地址:https://www.cnblogs.com/shamo89/p/10211413.html
Copyright © 2020-2023  润新知