Java对象的生命周期

// 在堆区中的对象一个个被陆续的创建,又一个个被销毁,在对象生命周期的开始阶段,需要为对象分配内存
// 并且初始化他的实例变量,当程序不再使用某个对象时,他就会结束生命周期,他的内存可以被Java虚拟机的垃圾回收器回收
// 创建对象的方式,new,运用反射Class类或者Constructor类的newInstance(),调用对象的clone方法,运用反序列化手段,调用ObjectInputStream对象的readObject()方法
// new语句和Class对象的newInstance()方法创建对象时会调用其构造方法,而clone()方法创建对象时不会执行其构造方法,clone()对象和原来的对象具有不同的内存地址,不过他们的属性值相同
// 不管何种方式创建对象,java虚拟机创建一个对象都包含以下步骤:1.给对象分配内存,2.初始化实例变量为其赋默认值,3.初始化对象,给实例变量赋予正确的初始值
// java虚拟机会采用3种方式来初始化对象,1.通过clone,将原来被克隆对象的实例变量拷贝到新对象中,2.通过ObjectInputStream对象的readObject()方法,通过从流中读入的序列化数据来初始化那些非暂时性(non-transient)的实例变量
// 3.如果实例变量在申明时被显示的初始化,那么就把初始化值赋给实例变量,接着再执行构造方法,
// 构造方法,多数时,初始化一个对象的最终步骤是去调用这个对象的构造方法,构造方法负责对象的初始化工作,为实例变量赋予合适的初始值,构造方法不能被子类继承,使用final和abstract没有意义,构造方法用于初始化一个新建的对象,用static没有意义,
// 多个线程不会同时创建内存地址相同的同一个对象,synchronized修饰没有必要,此外,java语言不支持native类型的构造方法.
// java语言允许在构造方法中用this语句来调用另一个构造方法,this要放在构造方法的第一行,不能在实例方法中用this语句来调用类的其他构造方法
// 默认构造方法,有显示的创造就没有默认的构造方法了,父类的构造方法不能被子类继承,但在子类的构造方法中可以通过super语句调用父类的构造方法,super也必须放第一行,
// 构造方法的调用,在实例化子类时,指定通过super调用了父类的构造方法,那就会先执行父类的构造方法,当子类没有用super语句时,那么会调用父类的默认构造方法,如果父类没有构造方法,则创建子类的实例时会出现错误
// 构造方法的作用域,通过this,super和程序中通过new语句调用它,构造方法的访问级别,private时,只有在类中能访问,可以把类的所有构造方法都定义为private时,此时仅提供一些静态方法,没有任何实例方法,其他程序无须创建该类的实例,就能访问类的静态方法,例如Math
// Math类唯一的构造方法就是private类型。 abstract类型也是不允许实例化的,但是他可以拥有子类,而且可以创建具体子类的实例,如果不希望被继承那就使用private类型构造方法最合适,当定义一个类是final时,他不允许有子类,但是其他程序可以new语句来构造他的实例
// 既不允许new,也不允许子类就把所有构造方法声明为private类型,
// 不允许其他程序通过new语句创建这个类的实例,仅提供实例的静态方法,并控制自身实例的数目,这中方法称为静态工厂方法,
// 例如Class实例是java虚拟机在加载一个类时自动创建的,程序无法用new创建java.lang.Class类的实例,因为Class类没有提供public类型的构造方法,
// 为了使程序能获得代表某个类的Class实例,在Class类中提供了静态工厂方法forName(String name),Class c = Class.forName("sample");
// 构造方法和new语句调用的构造方法相比,有以下区别:
// 构造方法名字必须与类名相同,所以不能从名字上区分每个重载方法的作用,容易引起混淆
// 静态工厂方法名字可以随便,所以从方法名中能体现与实例有关的信息,缺点是与其他的静态方法没有明显的区别,用户不知道哪些静态方法负责返回类的实例,所以目前比较流行的是把静态工厂方法命名为valueOf或者getInstance,例如Integer.valueOf(),Calendar.getInstance()
// new语句都会创建一个新的对象,而静态工厂方法每次被调用,是否创建一个新的对象完全取决于方法的实现
// new语句只能创建当前类的实例,而静态工厂方法可以返回当前类的子类的实例,这一特性可以在创建松耦合的系统接口时发挥作用
// 静态工厂方法可以创建以下类的实例:单例类(只有唯一的实例的类),枚举类(实例的数量有限的类),具有实例缓存的类(能把已经创建的实例暂且存放在缓存中的类),具有实例缓存的不可变类(不可变类的实例一旦创建,其属性值就不会被改变)
// 单例类:是指仅有一个实例的类,Struts的ActionServlet类就是单例类,Hibernate的SessionFactory和Configuration类也是单例类,实现单例类的两种方式:构造方法定义为private类型,提供public static final类型的静态变量,该变量引用类的唯一实例,另一种是
// 构造方法定义为private类型,提供了public static类型的静态工厂方法,这种方法的优点是可以更灵活的决定如何创建类的实例,在不改变GlobalConfig类的接口的前提下,修改getInstance()的实现方式,比如把单例类改为每个线程分配一个实例,可以使用ThreadLocal
// 枚举类,例如Gender类,只有两个实例Gender.FEMALE和Gender.MALE,把构造方法定义为private类型,提供public static final类型的静态变量,每个静态变量引用类的一个实例,如果需要的话,提供静态工厂方法,允许用户根据特定参数获得与之匹配的实例
// 不可变类与可变类,不可变表示创建了这个类的实例后,就不允许修改他的属性值,在JDK中所有类型的包装类,如Integer和Long类,都是不可变类,以为Integer和Long类没有提供修改其属性值的接口
// 创建不可变类采用以下设计模式:1.把属性定义为private final类型,2.不对外公开set方法,3.在构造方法中初始化所有属性,
// 具有实例缓存的不可变类
// 松耦合的系统接口,一个静态工厂可以返回子类的实例,这样有助于松耦合的系统接口,不需要写死哪个子类与父类绑定,例如ShapeFactory就是一个静态工厂类,负责构造Shape类的实例,ShapeFactory类是一个静态工厂方法
// 该方法返回的是Shape类,而实际返回的是Shape子类的实例,例如可以在静态代码块中指定实现类的名称 serviceImpl = "ServiceImpl1",再通过静态工厂方法 getInstance()方法的Class.ForName(ServiceImpl1).newInstance创建实例。
// finalize()垃圾回收机制。

你可能感兴趣的:(Java基础)