java中的静态内部类与非静态内部类的联系
区别
1. 从使用上说:静态内部类中才能有静态属性和静态方法,非静态内部类中不能有静态属性和静态方法。
2. 从生命周期上说:静态内部随着外部类的加载而加载,不是伴随着外部类的对象产生而产生的。外部类的实例与静态内部类的实例没有任何关系的。而非静态内部类的实例是需要依赖外部类实例才能创建的。换句话说非静态内部类是附属在外部类实例基础之上的,需要先创建一个外部类的实例,通过外部类的实例才能实例化非静态内部类,而静态内部类是依附在外部类的。
这里需要注意的是:无论是静态内部类还是非静态内部类它们的加载时间是只有用到了内部类才会初始化加载,而不是外部类加载的时候。
验证静态内部类加载的时间与顺序
public class TestExecuteOrder {
public static int num=
5;
static {
Log.e(
"ssssss",
"outter class num:" + num);
num=
10;
}
public TestExecuteOrder() {
Log.e(
"sssssss",
"outter class contsructor num:" +num);
}
public static class StaticInnerClass {
public static long timeStamp=System.currentTimeMillis();
}
public class NormalInnerClass{
public int b=
0;
}
public void getStaticInnerClassTime() {
Log.e(
"ssssss",
"getStaticInnerClassTimeStamp:" +StaticInnerClass.timeStamp);
}
public void test(){
TestExecuteOrder.StaticInnerClass staticInnerClass=
new TestExecuteOrder.StaticInnerClass();
TestExecuteOrder.NormalInnerClass normalInnerClass=
new TestExecuteOrder().
new NormalInnerClass();
}
1.上面代码示例中的test()方法演示了静态内部类与非静态内部类实例的创建方式
2.Log日志的输出结果依次为outter class num:5,outter class contsructor num:10,getStaticInnerClassNum2:1488956673146,outter class contsructor num:10,getStaticInnerClassNum2:1488956673146。
3.因此得出加载顺序为:静态属性—>静态代码块—->构造函数。其中静态属性与静态代码块在类加载的时候开始调用并且只会执行一次,而静态内部类只在调用getStaticInnerClassTime()方法的时候才进行加载并且只会加载一次。我们可以根据这个原理实现多线程安全的单例模式。
静态内部类实现线程安全的单例模式
public class Singleton {
private Singleton(){};
public static Singleton
getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
private static Singleton instance=
new Singleton();
}
}
懒汉式(避免资源浪费)、线程安全、代码简单。因为java机制规定,内部类SingletonHolder只有在getInstance()方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的(实现线程安全)。内部类加载的时候实例化一次instance。更多细节说明可以阅读:双重检查锁定与延迟初始化。
转载请注明原文地址: https://ju.6miu.com/read-3433.html