前言
在jdk源码中我们发现很多常用到的类里面都带有一个私有静态内部类,神秘的内部类一直都是让我头疼的东西,那这个“私有静态内部类”又是一个什么鬼呢?
解释前,我先给出一个熟识度高的使用案列—“IntegerCache”,这只是冰山一角,但他却是我们实际用的比较多的,但是被我们忽略的。jdk1.8中他是一个定义在Integer下的私有静态内部类:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
看起来跟正常类没区别呀,并且平常不是说—“静态内部类就是一个顶级类”吗?那这加了一个private又是怎么回事?
1.杜绝被别的外部类调度或实例化
class A{
static class C{
static final String high;
static {
high="这是C的high";
System.out.println(high);
}
}
private static class B {
static final String high;
static {
high="这是B的high";
System.out.println(high);
}
private B() {
System.out.println("这是B()方法");
}
}
public void c() {
System.out.println(C.high);
System.out.println(B.high);
}
}
class E{
public static void main(String[] args) {
A.B b1=new A.B(); //这里是会报错的。
A.C c1=new A.C();
System.out.println(A.C.high);
System.out.println(A.B.high); //这里是会报错的。
}
}
上面的代码会在注释处报错,因为静态内部类B被private修饰。
2.只为其依附的外部类服务
为其依附外部类,提供一个更小的,功能单一的小模块。并且这个模块是不需要实体化的,且不容许其他外部类访问。
给出一段代码:
class A{
private static class B {
static final String high; //提供一个静态常量high
static {
high="这是B的high"+Math.random();; //完成初始化功能,因为是static块,所以只会执行一次。
System.out.println("static块:"+high);
}
private B() {
System.out.println("这是B()方法");
}
}
public void c() {
System.out.println("c()方法:"+B.high);
}
}
class E{
public static void main(String[] args) {
A a_1=new A(); //这一步还不会执行私有静态内部类
a_1.c(); //调用c()方法。
a_1.c();
A a_2=new A();
a_2.c(); //调用c()方法。
}
}
输出:
static块:这是B的high0.30008771595404693
c()方法:这是B的high0.30008771595404693
c()方法:这是B的high0.30008771595404693
c()方法:这是B的high0.30008771595404693
上面就是一个体现,就是当我们用到A时,加载A类并实例化A时,这一步还不会执行私有静态内部类,当我们调用c()方法时,因为c()方法中显示的调用了B.high,所以会触发B类的加载初始化,B这个小模版的功能就是提供一个high常量,并完成初始化,而这个high只提供给A使用,因为是static块,所以只会在第一次加载执行一次。所以就算我们后面还去重新实例化A对象,high值都不会在变。
内部类的权限拦截对依附类是不生效的。
Integer中的Integercache也是同理。只为其依附的外部类服务。