Java 创建对象方法

    本文主要介绍java创建对象的方法,闲话少叙。


Java创建对象的方法有多种,常见基本如下:


1、用new语句创建对象,这是最常见的创建对象的方法。

2、通过工厂方法返回对象,如:String str = String.valueOf(23); 
3、运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

      Object obj = Class.forName("java.lang.Object").newInstance(); 
4、调用对象的clone()方法。实现Cloneable接口,然后重写Object.clone()方法创建对象.
5、通过I/O流(包括反序列化),如运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

6、String str="abc" 直接由jvm创建 或者使用 字符串操作符"+"  String str1 = "a"+"bc"由jvm创建。

创建对象方法比较:


工厂方法往往是调用new的,所以可以看作new的一种变形,对于虚拟机,本质一致。反序列化就是将数据读入后,调用反射生成新对象,唯一需要注意的是反射调用了类的无参构造函数,反射需要保证类有无参构造函数。下面重点介绍new,clone和反射。


new: 


  1.JVM首先检查该类是否加载,没有加载会先加载类,对类进行加载,解析和初始化;

  2.加载类后,JVM对该对象在Java堆中分配内存,

  3.设置对象,先对对象的初始化零值,就是对象字段初始化为零值;再对对象的对象头部分初始化,就是设置该对象的JVM相关属性,比如该对象属于哪个类,hash值,GC年代等。至此,从JVM看,对象创建了。

  4.执行<init>方法,按照程序员的意愿对对象的各个属性设置。比如,设置各个域的初始值。


clone:


  clone目的是复制一个原对象的copy,简单的就是内存复制,所以简单的clone是很快的,即与原对象相同,但是不一样,对新对象的操作不会影响原对象。clone在java规范中要求 1. a.clone() != a; 2. a.clone().getClass = a.getClass(); 3. a.clone().equals(a).

clone要求对象实现clonable接口,Object的clone方法会检测对象是够实现了这个接口。Object方法的clone方法是protected,即只有子类和同包(自定义类自然做不到和Object同包)才能调用。

    clone分浅clone和深clone。 

    浅clone,Shallow Clone,就是逐域拷贝,默认实现cloneable接口或者简单覆盖clone方法就是浅clone。例如:

public class A implements Cloneable {  
    public String name;  
  
    public Object clone() {  
        A o = null;  
        try {  
            o = (A) super.clone();  
        } catch (CloneNotSupportedException e) {  
            e.printStackTrace();  
        }  
        return o;  
    }  
} 
    一个类如果只有基本类型和字符串这样的不可变对象,那么仅仅实现Cloneable就够了。但是如果类中包含数组或者复杂对象,就需要深clone,即正确生成新对象。例如:

public class A implements Cloneable {
	public String name[];
	public Vector<B> claB;
	
	public A(){
		name=new String[2];
		claB=new Vector<B>();
	}

	public Object clone() {
		A o = null;
		try {
			o = (A) super.clone();
            o.name==(String[])name.clone();//深度clone
            o.claB=new Vector<B>();//将clone进行到底
            for(int i=0;i<claB.size();i++){
	            B temp=(B)claB.get(i).clone();//当然Class B也要实现相应clone方法
	            o.claB.add(temp);
		    }
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
				return o;
	}
}


其实,clone方法分三种情况处理。

1.对象只包含基本类型的域或者域指向了一个不可变对象,这种情况只需实现cloneable接口即可。

2.域中包含数组的对象,只需调用数组的clone方法。

3.域包含可变对象。这就是需要我们特别关照的情况,我们必须将这些可变的部分手动。比如,List。

下面有例子(有些正确clone,有些没有):

package basic.objects.methods;

import java.util.ArrayList;
import java.util.List;

/**
 * 检测数组的clone的正确定。 c2的改变不应该引起c1对象的改变,这是clone的意义。
 */
public class Clones implements Cloneable {
	int[] ints;// 没有正确clone
	double[] doubles;// 正确处理
	List<String> strs;// 没有正确处理
	List<Character> chs; // 正确处理

	public Clones() {
		ints = new int[] { 0 };
		doubles = new double[] { 0 };
		strs = new ArrayList<String>();
		chs = new ArrayList<Character>();
	}

	@Override
	public Clones clone() {
		try {
			Clones c = (Clones) super.clone();
			c.doubles = doubles.clone();
			c.chs = new ArrayList<Character>(chs);
			return c;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws CloneNotSupportedException {
		Clones c1 = new Clones();
		Clones c2 = (Clones) c1.clone();
		c2.ints[0] = 1;
		c2.doubles[0] = 1;
		c2.strs.add("new str in c2 added");
		c2.chs.add('H');
		System.out.println(c1.ints[0]);
		System.out.println(c1.doubles[0]);
		System.out.println(c1.strs);
		System.out.println(c1.chs);
	}
}



反射:


    反序列化往往是对于类在remote或者是一串特殊文本等的情况。简单说,Java自带的反序列化就是读取字节流,然后通过反射调用class的newInstance()方法,构造出新对象。反射构造对象具体见 这里


下面是关于创建速度的文章,有兴趣可以一看。http://my.oschina.net/u/1428349/blog/299205

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值