[Effective Java Second Edition]创建实例的5种方式

new

例如:StringBuilder stringBuilder = new StringBuilder(“hi, zkpp1”);这条语句的就是创建了一个StringBuilder实例,其创建结果就是在内存为对象分配了内存空间以及指向内存空间的指针。

静态工厂方法

优点

  • 它们具有名称可以根据功能取名,而构造函数只能是它们的类名
  • 不必每次调用都返回不同的对象,通过静态方法可以让重复的调用返回相同的对象,例如单例模式的某种实现
  • 静态工厂方法可以返回任何子类型的对象
  • 创建参数化实例,代码更简洁,如下所示:
public static <K,V> HashMap<K, V> newInstance() {  
    return new HashMap<K, V>();  
}  

方法命名

  • valueOf,类型转换
  • getInstance,返回的实例是通过方法参数来描述的,每个实例不一定与其他实例不同
  • newInstance,与getInstance相同,每个实例一定与其他实例不同
  • getType,与getInstance相同,但是在工厂方法处于不同类的时候使用
  • newType,与newInstance相同,但是在工程方法处于不同类的时候使用

clone

深复制

深复制,是对对象中的对象本身也进行复制,而不仅仅是对象的引用得到拷贝

浅复制

浅复制不是真正所有的复制,如果对象中有对象,那么只是对对象中的引用进行复制

方法实现

clone()实例化方法需要实现Cloneable接口,实现的clone()方法中调用super.clone()即可。对于包含对象的类,如果需要深复制,还需要调用类中对象的clone()方法,并将方法返回的实例赋值给对象中的该对象。

反射

Class实例是Java应用程序运行时的类或接口,它是类级别的对象,而不是具体某个对象的实例。Class类级别对象的获取通过以下语句:

Class class = Class.forName("XXX");  
参数
XXX表示类的完全限定名
返回
完全限定类名的Class对象
异常
LinkageError连接失败
ExceptionInInitializeError方法触发的初始化失败
ClassNotFoundException根据限定类名找不到类

创建不带参数对象

调用Class类级别对象的newInstance()方法,就返回Class类所表示对象的一个实例,代码如下:

Class classType = Class.forName(Reflect.class);  
Object obj = classType.newInstance();  
返回
Class类对象所表示对象实例
异常
IllegalAccessException该类或其无参构造方法是不可访问的
InstantiationException此Class表示一个抽象类、接口、数组类、基本类型或void,或者该类没有无参构造方法,或者由于其他某种原因导致实例化失败
IllegalArgumentException参数不合法异常
InvocationTargetException调用异常
说明
调用newInstance()方法返回的是泛型模板对象,需要转换为实际类型

创建带参数对象

获取操作类的Class对象即字节码文件 ,再使用Class对象的getConstructor(parameterTypes)方法获取该对象构造方法的对象(注意括号中可以带不等的可变参数),使用构造方法对象的newInstance(initargs)方法就可以实例化一个对象,创建代码如下:

Class classType = Reflect.class; 
Constructor<Reflect> con = classType.getConstructor(String.class);
Object obj = con.newInstance("zkp");
返回
Class类对象所表示对象实例
异常
IllegalAccessException该类或其无参构造方法是不可访问的
InstantiationException此Class表示一个抽象类、接口、数组类、基本类型或void,或者该类没有无参构造方法,或者由于其他某种原因导致实例化失败
IllegalArgumentException参数不合法异常
InvocationTargetException调用异常
NoSuchMethodException方法不存在异常
SecurityException存在安全管理器 s,并满足拒绝创建新实例的条件
说明
调用newInstance()方法返回的是泛型模板对象,需要转换为实际类型

序列化与反序列化

认识序列化

序列化是一种将对象转换成字节数组的过程(注:认识序列化内容参考《深入分析Java Web技术内幕》)。复杂对象序列化总结如下:

  • 当父类继承Serializable接口时,所有子类都可以被序列化;
  • 子类实现了Serializable接口,父类没有,父类中属性不能序列化(不报错,数据会丢失),但是在子类中属性仍能正确序列化;
  • 如果序列化的属性是对象,则这个对象也必须实现Serializable接口,否则会报错;
  • 在反序列化时,如果对象的属性有修改或删减,则修改的部分属性会丢失,但不会报错;
  • 在反序列化时,如果serialVersionUID被修改,则反序列化时会失败。

反序列化创建对象实例

序列化与反序列化是一对逆操作,对象被序列化后,可以通过反序列化来生成实例对象,以Java SDK自带的序列化API进行说明如何序列化和反序列化,主要有以下三种方法:

  • 若类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化,ObjectOutputStream采用默认的序列化方式,对对象的非transient的实例变量进行序列化,ObjcetInputStream采用默认的反序列化方式,对对象的非transient的实例变量进行反序列化
  • 若类仅仅实现了Serializable接口,并且还定义了readObject()和writeObject(),则采用以下方式进行序列化与反序列化。
    ObjectOutputStream调用对象的writeObject()的方法进行序列化,ObjectInputStream会调用对象的readObject()的方法进行反序列化
  • 若类实现了Externalnalizable接口,且类必须实现readExternal()和writeExternal()方法,则按照以下方式进行序列化与反序列化。
    ObjectOutputStream调用对象的writeExternal()的方法进行序列化,ObjectInputStream会调用对象的readExternal()的方法进行反序列化。

按照上述方法可知,反序列化创建实例对象步骤如下:

  • 创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:
    ObjectInputStream in = new ObjectInputStream(new fileInputStream(“XXX”));
  • 通过对象输入流的readObject()或readExternal()方法进行反序列化

对于反序列化创建对象,为了防止反序列化造成非单例问题,需要对序列化类做如下处理:

package com.wizard.hello;  

import java.io.Serializable;  

/** 
 * Created by Administrator on 2015/8/29. 
 */  
public class Singleton implements Serializable{  
    private static final long serialVersionUID = 1L;  
    private static transient;
    private final Singleton INSTANCE = new Singleton();  

    private Singleton() {  

    }  

    public static Singleton getInstance() {  
        return INSTANCE;  
    }  

    private Object readResolve() {  
        return INSTANCE;  
    }
}  
package com.wizard.hello;  

import java.io.*;  

/** 
 * Created by Administrator on 2015/8/6. 
 */  
public class TestMain {  

    public static void main(String args[]){  
        Singleton singleton = Singleton.getInstance();  
        Singleton singleton1 = singleton;  
        try {  
            SerializeSingleton(singleton);  
            singleton = DeserializeSingleton();  
        } catch (Exception e) {  
            System.out.println("fail!");  
        }  
       System.out.println(singleton.equals(singleton1));  
    }  

    private static void SerializeSingleton(Singleton singleton) throws FileNotFoundException, IOException {  

        ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(new File("E:\\Singleton.txt")));  
        oo.writeObject(singleton);  
        System.out.println("Singleton serialize success!");  
        oo.close();  
    }  

    private static Singleton DeserializeSingleton() throws Exception, IOException {  
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("E:\\Singleton.txt")));  
        Singleton person = (Singleton) ois.readObject();  
        System.out.println("Singleton deserialize success!");  
        return person;  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值