【Java学习笔记】对象生命周期
作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/
1.创建对象
1)显示创建:
a.用new创建对象。
b.使用反射手段,即调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
c.调用对象的clone()方法。注意,这种方法不会调用类的构造函数
d.使用反序列化的方法。
对于clone方法注意:
a.Object中的clone方法时protected,若希望对外公开clone()方法,就必须扩大访问范围,改为public
b.返回Object类型。
c.若类没有实现Cloneable接口,clone()方法会抛出异常,Object的子类若是允许客户程序调用其clone()方法,那么这个类必须实现Cloneable方法。
2)隐式创建:
a.String str= "hello";这种属于String类型直接数对应一个String对象,引用一个String对象。若此时运行String str2=
"hello";则str和str1是同一个对象。
b.String中+的使用。
c.JVM加载一个类的时候,会隐含创建描述这个类的Class实例。
3)创建步骤:
a.给对象分配内存。
b.将对象的实例变量自动初始化为其变量类型的默认值。
c.初始化对象,给实例变量赋予正确的初始值。
2.构造方法
注意:
没有返回类型(有的话,即使函数名同名也被视为一般函数而非构造方法),不能被static、final、synchronized、abstract和native修饰。
用this可以重载构造方法:必须在第一条语句使用this。且必须在构造方法中使用this调用其他构造方法。
在类中没有构造方法的时候JAVA会给每个类一个默认的构造方法,但是若类中显式的添加了构造方法,并且所有的构造方法都带参数,那么这个类除非也显式的定义一个默认构造方法,否则默认的构造方法就缺失了。
子类的构造方法中,可以通过super语句调用父类的构造方法,因为构造函数是不继承的。例如:super("Something is OK");
在构建子类对象的时候,JVM首先执行父类的构造方法,然后再执行子类的构造方法。在多级继承的时候,从继承树的最上层的父类开始,依次执行各个类的构造方法。
构造方法的调用:
当前类的其他构造方式通过this语句调用它。其子类的构造方法通过super调用。在程序中使用new调用。
构造方法的访问级别:
一般的我们的构造方法都是public级别的(以上我们讨论的情况),但是我们现在要讨论的是在private级别的,这就意味着只能在当前类中或在当前类的其他构造方法中通过this语句调用它。当然,在当前类的成员方法中使用new也会调用)
a.这个类只提供一些静态方法给外部,所以为了禁止外部程序创建类的实例(因为静态方法无需创建实例),所以将构造方法设为private。
b.禁止这个类被继承。当然是用final也可以解决,但它同时也禁止了外部使用new进行创建实例(同a所述)
c.这个类需要把构造自身实例的细节封装起来,而向其他程序提供了获得自身实例的静态方法——静态工厂方法。
3.静态工厂方法:
假如类需要进一步封装创建自身实例的细节,并且控制自身实例数目,那么可以提供静态工厂方法。
使用举例:
public class Gender{
private String description;
private static final Gender female = new Gender("female");
private static final Gender male = new Gender("male");
private Gender(String description){this.description=description;}
public static Gender getFemale(){
return female;
}
}
特点:
a.静态工厂方法名可以不与类名相同,程序代码可读性增强。比较流行的是将这样的代码命名为valueOf或者getInstance
b.使用时是否会创建一个新的对象完全取决于方法的实现。
c.可以返回当前类的子类的实例。
应用:创建以下各种类。
a.单例类:系统中具有唯一性的组件。
实现方法:
1)把构造方法定义为private类型,提供public static final 类型的静态变量。该变量引用类的唯一的实例。
2)在方法1)的基础上添加getInstance方法,返回那个静态变量,使用的是静态工厂方法。这个的好处在于可以不修改方法名的前提下修改实现getInstance的实现方式,以适应变更的需求。
b.自定义枚举类:实例数目有限的类。
c.不可变类:指创建了这个类的实例后就不允许修改它的属性值。
创建时把属性定义为private final类型,不对外公开setXXX()方法,只对外公开getXXX()方法。在构造方法中初始化所有属性。覆盖Object的equals()方法和hashCode()方法。若是需要就提供实例缓存和静态工厂方法。
类的设计优先考虑不可变类。在创建不可变类的时候,若其属性是可变类型,则需要提供保护性拷贝。
具有实例缓存的不可变类,比如Integer实例,有一个静态工厂方法valueOf(int i),这样创建的一个Integer对象,要是发现前边有值是相同创建好的实例的话,那么直接使用以前创建的。这样的特性可以通过Java集合来作为实例缓存。
public class Ghost{
private static final Map<String,Ghost> ghosts = new HashMap<String,Ghost>();
private final String name;
private Ghost(String name){
this.name = name;
}
public String getName(){
return name;
}
public static Ghost getInstance(String name){
Ghost ghost = ghosts.get(name);
if(ghost == null){
ghosts=new Ghost(name);
ghosts.put(name,ghost);
}
return ghost;
}
public static void removeInstance(String name){
ghosts.remove(name);
}
在分层的软件系统中,业务逻辑层向客户层提供服务,静态工程类可以进一步削弱这两层间的耦合关系。