Java 创建对象方法
2015-08-04 13:28
387 查看
本文主要介绍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创建。
1.JVM首先检查该类是否加载,没有加载会先加载类,对类进行加载,解析和初始化;
2.加载类后,JVM对该对象在Java堆中分配内存,
3.设置对象,先对对象的初始化零值,就是对象字段初始化为零值;再对对象的对象头部分初始化,就是设置该对象的JVM相关属性,比如该对象属于哪个类,hash值,GC年代等。至此,从JVM看,对象创建了。
4.执行<init>方法,按照程序员的意愿对对象的各个属性设置。比如,设置各个域的初始值。
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。例如:
其实,clone方法分三种情况处理。
1.对象只包含基本类型的域或者域指向了一个不可变对象,这种情况只需实现cloneable接口即可。
2.域中包含数组的对象,只需调用数组的clone方法。
3.域包含可变对象。这就是需要我们特别关照的情况,我们必须将这些可变的部分手动。比如,List。
下面有例子(有些正确clone,有些没有):
反序列化往往是对于类在remote或者是一串特殊文本等的情况。简单说,Java自带的反序列化就是读取字节流,然后通过反射调用class的newInstance()方法,构造出新对象。反射构造对象具体见这里。
下面是关于创建速度的文章,有兴趣可以一看。http://my.oschina.net/u/1428349/blog/299205
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
相关文章推荐
- spring tool suite导入Dynamic web project后,无法export出war包
- JAVA修饰符类型(public,protected,private,friendly)
- java文件的上传与下载
- struts2拦截器注解<struts> <package name="default" extends="struts-default"> <interceptors> <interc
- 重学java23种设计模式(12)代理模式
- trie树Java实现
- myeclipse导入java EE 5 Library
- Understanding Java Garbage Collection
- java小总结
- Spring的多事务配置(多个Transaction Manager)和使用方法
- JAVA正则表达式 Pattern和Matcher
- java的装箱与拆箱
- Java_Web三大框架之Hibernate操作数据库(三)
- java使用cookies
- JAVA动态代理的作用
- Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)
- Spring AOP 使用注解为API引入新功能
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- MyBatis3整合Spring3、SpringMVC3
- myeclipse 配置resin 4