您的位置:首页 > 编程语言 > Java开发

Java 创建对象方法

2015-08-04 13:28 387 查看
本文主要介绍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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: