【十七】Java多线程之不可变 变量、集合(final、Collections.unmodifiableXXX、ImmutableXXX、浅拷贝)

版权声明:转载注明出处 https://blog.csdn.net/jy02268879/article/details/86149080

一、final关键字

可以用来修饰类、方法、变量

1.final类

不能被继承

final类中的所有成员方法都会被隐式的指定为final方法。

2.final方法

子类不能覆盖该方法,一个类的priavte方法会隐式的被指定为final方法

3.final变量

final修饰的基本数据类型的变量,它的值在初始化后就不能修改。

final修饰的引用类型的变量,它在初始化之后不能再指向另外一个对象,并不是不能修改值

代码示例map

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

public class FinalTest {

    private final static Integer a = 1;
    private final static String b = "2";
    private final static Map<Integer, Integer> map = Maps.newHashMap();

    static {
        map.put(1, 2);
        map.put(2, 4);
    }

    public static void main(String[] args) {
//        a = 5;    报错
//        b = "5";  报错
//        map = Maps.newHashMap();  报错
        map.put(1, 3);   //修改成功
         System.out.println(map.get(1));
    }
}

结果

扫描二维码关注公众号,回复: 5117419 查看本文章

二、Collections.unmodifiableXXX (其实是不安全的,可被修改的

Collections是java.util里面的,它提供了不修改的集合,如map,set,list。

支持Null值

以map为例:

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.Map;

public class CollectionsUnmodifiableTest {

    private static Map<Integer, Integer> map = Maps.newHashMap();

    static {
        map.put(1, 2);
        map = Collections.unmodifiableMap(map);
    }

    public static void main(String[] args) {
//        map.put(2, 3);  //同样报错
//        map.put(1, 3);  //同样报错
        map.remove(1);    //同样报错
        System.out.println(map.get(1));
    }

}

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.Collections$UnmodifiableMap.remove(Collections.java:1460)
    at com.mmall.concurrency.example.immutable.ImmutableExample2.main(ImmutableExample2.java:24) 

 Collections.unmodifiableMap方法源码:

    /**
     * Returns an unmodifiable view of the specified map.  This method
     * allows modules to provide users with "read-only" access to internal
     * maps.  Query operations on the returned map "read through"
     * to the specified map, and attempts to modify the returned
     * map, whether direct or via its collection views, result in an
     * <tt>UnsupportedOperationException</tt>.<p>
     *
     * The returned map will be serializable if the specified map
     * is serializable.
     *
     * @param <K> the class of the map keys
     * @param <V> the class of the map values
     * @param  m the map for which an unmodifiable view is to be returned.
     * @return an unmodifiable view of the specified map.
     */
    public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {
        return new UnmodifiableMap<>(m);
    }

实际上在调用unmodifiableMap方法的时候是返回了一个新的UnmodifiableMap对象,UnmodifiableMap中的map是原来的入参map的一个浅拷贝

用“=”号给非基本类型赋值,均是浅拷贝

        private final Map<? extends K, ? extends V> m;

        UnmodifiableMap(Map<? extends K, ? extends V> m) {
            if (m==null)
                throw new NullPointerException();
            this.m = m;
        }

而UnmodifiableMap类的源码把所有修改方法换成了抛出异常

        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();
        }

 其实Collections.unmodifiableXXX集合是可变的

由于是浅拷贝

如果还有除了Collections.unmodifiableXXX返回的,其他引用指向这个对象,

那么那个非Collections.unmodifiableXXX返回的引用是可以改变对象的值的。

例如把上面示例代码改成:


import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.Map;

public class CollectionsUnmodifiableTest {

    private static Map<Integer, Integer> map = Maps.newHashMap();
    private static Map<Integer, Integer> mapUnmodifiable = null;
    static {
        map.put(1, 2);
        mapUnmodifiable = Collections.unmodifiableMap(map);
    }

    public static void main(String[] args) {
//        mapUnmodifiable.put(2, 3);    //报错java.lang.UnsupportedOperationException
//        mapUnmodifiable.put(1, 3);    //报错java.lang.UnsupportedOperationException
//        mapUnmodifiable.remove(1);//报错java.lang.UnsupportedOperationException
        map.put(2, 3);
        System.out.println(mapUnmodifiable.size());
        System.out.println(mapUnmodifiable.get(2));
    }

}

运行结果

三、ImmutableXXX 真正的不可变

ImmutableXXX是google guava里面的,提供不可变集合

每个Guava immutable集合类的实现都不支持null值

需要引入依赖

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

 创建示例

    //用of()初始化数据
    private final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);

    //用copyOf()初始化
    private final static ImmutableSet set = ImmutableSet.copyOf(list);

    private final static ImmutableMap<Integer, Integer> map = ImmutableMap.of(1, 2, 3, 4);

    //用builder()形式初始化
    private final static ImmutableMap<Integer, Integer> map2 = ImmutableMap.<Integer, Integer>builder().put(1, 2).put(3, 4).put(5, 6).build();

代码示例

import com.google.common.collect.ImmutableList;

import java.util.ArrayList;
import java.util.List;

public class ImmutableTest {
    public static void main(String[] args) {
        Map<Integer, Integer> map = Maps.newHashMap();
        map.put(1, 2);
        ImmutableMap<Integer, Integer> mapImmutable = ImmutableMap.copyOf(map);
        map.put(2,4);
        map.put(1,1);

        System.out.println(mapImmutable.size());
        System.out.println(mapImmutable.get(1));
    }
}

运行结果

猜你喜欢

转载自blog.csdn.net/jy02268879/article/details/86149080
今日推荐