一、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));
}
}
结果
二、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));
}
}
运行结果