单例模式之类的加载
来源:互联网 发布:mac safari 编辑:程序博客网 时间:2024/06/04 17:50
单例模式中经常提到懒汉式和饿汉式,最大的区别就是在创建对象的时间不一样,饿汉是在类加载的时候就创建了对象,懒汉是在使用时候才创建对象
同时单例模式保证只有一个对象,那么请问类的加载的时机是什么?类加载都做了什么?
对象在内存中都做什么?以下是我的理解
首先明确类的加载模式
类什么时候加载
类的加载是通过类加载器(Classloader)完成的,它既可以是饿汉式[eagerly load](只要有其它类引用了它就加载)加载类,也可以是懒加载[lazy load](等到类初始化发生的时候才加载)。不过我相信这跟不同的JVM实现有关,然而他又是受JLS保证的(当有静态初始化需求的时候才被加载)。
类什么时候初始化
加载完类后,类的初始化就会发生,意味着它会初始化所有类静态成员,以下情况一个类被初始化:
- 实例通过使用new()关键字创建或者使用class.forName()反射,但它有可能导致ClassNotFoundException。
- 类的静态方法被调用
- 类的静态域被赋值
- 静态域被访问,而且它不是常量
- 在顶层类中执行assert语句
反射同样可以使类初始化,比如java.lang.reflect包下面的某些方法,JLS严格的说明:一个类不会被任何除以上之外的原因初始化。
类是如何被初始化的
现在我们知道什么时候触发类的初始化了,他精确地写在Java语言规范中。但了解清楚 域(fields,静态的还是非静态的)、块(block静态的还是非静态的)、不同类(子类和超类)和不同的接口(子接口,实现类和超接口)的初始化顺序也很重要类。事实上很多核心Java面试题和SCJP问题都是基于这些概念,下面是类初始化的一些规则:
- 类从顶至底的顺序初始化,所以声明在顶部的字段的早于底部的字段初始化
- 超类早于子类和衍生类的初始化
- 如果类的初始化是由于访问静态域而触发,那么只有声明静态域的类才被初始化,而不会触发超类的初始化或者子类的初始化即使静态域被子类或子接口或者它的实现类所引用。
- 接口初始化不会导致父接口的初始化。
- 静态域的初始化是在类的静态初始化期间,非静态域的初始化时在类的实例创建期间。这意味这静态域初始化在非静态域之前。
- 非静态域通过构造器初始化,子类在做任何初始化之前构造器会隐含地调用父类的构造器,他保证了非静态或实例变量(父类)初始化早于子类
初始化例子
这是一个有关类被初始化的例子,你可以看到哪个类被初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* Java program to demonstrate class loading and initialization in Java.
*/
public
class
ClassInitializationTest {
public
static
void
main(String args[])
throws
InterruptedException {
NotUsed o =
null
;
//this class is not used, should not be initialized
Child t =
new
Child();
//initializing sub class, should trigger super class initialization
System.out.println((Object)o == (Object)t);
}
}
/**
* Super class to demonstrate that Super class is loaded and initialized before Subclass.
*/
class
Parent {
static
{ System.out.println(
"static block of Super class is initialized"
); }
{System.out.println(
"non static blocks in super class is initialized"
);}
}
/**
* Java class which is not used in this program, consequently not loaded by JVM
*/
class
NotUsed {
static
{ System.out.println(
"NotUsed Class is initialized "
); }
}
/**
* Sub class of Parent, demonstrate when exactly sub class loading and initialization occurs.
*/
class
Child
extends
Parent {
static
{ System.out.println(
"static block of Sub class is initialized in Java "
); }
{System.out.println(
"non static blocks in sub class is initialized"
);}
}
Output:
static
block of Super
class
is initialized
static
block of Sub
class
is initialized in Java
non
static
blocks in
super
class
is initialized
non
static
blocks in sub
class
is initialized
false
从上面结果可以看出:
- 超类初始化早于子类
- 静态变量或代码块初始化早于非静态块和域
- 没使用的类根本不会被初始化,因为他没有被使用
再来看一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Another Java program example to demonstrate class initialization and loading in Java.
*/
public
class
ClassInitializationTest {
public
static
void
main(String args[])
throws
InterruptedException {
//accessing static field of Parent through child, should only initialize Parent
System.out.println(Child.familyName);
}
}
class
Parent {
//compile time constant, accessing this will not trigger class initialization
//protected static final String familyName = "Lawson";
protected
static
String familyName =
"Lawson"
;
static
{ System.out.println(
"static block of Super class is initialized"
); }
{System.out.println(
"non static blocks in super class is initialized"
);}
}
Output:
static
block of Super
class
is initialized
Lawson
分析:
- 这里的初始化发生是因为有静态域被访问,而且不一个编译时常量。如果声明的”familyName”是使用final关键字修饰的编译时常量使用(就是上面的注释代码块部分)超类的初始化就不会发生。
- 尽管静态与被子类所引用但是也仅仅是超类被初始化
0 0
- 单例模式之类的加载
- 单例模式之类定义
- 延迟加载的单例设计模式
- 延迟加载的单例设计模式
- 单例模式的延迟加载
- 单例模式的延迟加载
- 单例模式懒加载
- 单例延迟加载模式
- 单例模式加载配置文件
- 由延时加载的单例模式引发的思考
- 通过Singleton单例模式,理解Java的类加载
- 黑马程序员,延迟加载的单例设计模式
- 支持并发和延迟加载的单例模式
- java编写一个延迟加载的单例设计模式
- Java的单例模式与延时加载
- Glide图片加载 使用的单例模式
- 通过单例模式去加载可配置的常量
- java实现多线程延迟加载的单例模式
- 深入理解ThreadLocal
- 列表魔板与详情魔板标签
- 观止云技术实践| 可追溯日志:视频云时代的新运维大胸器
- DAY03_FQ+QS
- ListView扩展上拉加载更多,下拉刷新
- 单例模式之类的加载
- 设计模式GOF23——单例模式
- UltraEdit语法高亮配制方法
- 搭建SSH框架时遇到的问题及解决方法
- python 文件拷贝copy操作 shutill
- 解决: Gradle DSL method not found: 'apt()'
- C语言函数sscanf()的用法
- 这是关于RadioButton一个坑爹的问题,请让我自杀好吗!
- 机器学习面试问题3