JAVA创建对象的五种方式
Posted 古道子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA创建对象的五种方式相关的知识,希望对你有一定的参考价值。
最近在学习JAVA知识,通过网上翻看资料,发现原先有的理解不深的东西,渐渐明白了些。对象的使用,在编写软件过程中是必不可少的,不知道大家有没和我一样,几乎都是使用new来创建。那么,问题来了,JAVA有几种创建对象 的方式呢?
- 使用new关键字创建。
- 使用Class的newInstance()方法, 位于java.lang包,比如Person类,创建对象可以使用,但是下面的两种方式不能调用private构造函数,且构造对象的类中必须包含无参构造函数(构造器需可见 visible),否则会报错,对于捕获或者未捕获的异常均由构造器抛出;。
public class person { /** * */ private static final long serialVersionUID = 10L; String name = "Jack"; public person(){ this.name = name + " ma"; System.out.println("construct Person"); } private person(int a,int b) { System.out.println("a:"+a+ " b:" + b); } @Override public String toString() { return name; } } 方法一 //这里的testReflect为包名,Person类在此包下 Class clazz = Class.forName("testReflect.person "); person p = (person ) clazz.newInstance(); 方法二 person p =person .class.newInstance();
- 使用Constructor类的newInstance方法,此方法属于反射,位于 java.lang.reflect 包,可以调用任何作用域的构造函数,private也可以,且创建对象的类构造函数可以任意。
//调用无参构造函数 ,方式一 person p = person.class.getDeclaredConstructor().newInstance(); //调用无参构造函数 ,方式二 Constructor c1=person.class.getDeclaredConstructor(); c1.setAccessible(true); person p=(person)c1.newInstance();
这里大家思考下,在调用无参构造函数时,方式一和方式二有什么区别? 大家应该看到了c1.setAccessible(true); 这句代码吧,查看方法的定义包含如下:A value of true indicates that the reflected object should suppress Java language access checking when it is used,意思是为true的时候禁止验证授权,换句话的理解就是,private的无参构造也可以调用。这就是方式一和方式二的区别,方式一若private作用域修饰,则会报错。通常会把抛出的异常封装成InvocationTargetException抛出。
因为以上差异,所以很多框架使用的都是构造器反射的方式获取对象,像Spring, Guava, Zookeeper, Jackson, Servlet 等。
-
//调用有参构造函数 Constructor c1=person.class.getDeclaredConstructor(new Class[] {int.class,int.class}); 或 Constructor c1=person.class.getDeclaredConstructor(int.class,int.class);
-
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException
-
- Parameters:
parameterTypes
- the parameter array- Returns:
- The
Constructor
object for the constructor with the specified parameter list - 传入参数为数组。
-
- 使用Clone的方法:无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。要使用clone方法,创建对象的类必须实现Cloneable接口并实现其定义的clone方法。关于clone可参考我转载的JAVA深复制与浅复制。
- 使用反序列化:当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象,在反序列化时,JVM创建对象并不会调用任何构造函数。为了反序列化一个对象,对应类需实现Serializable接口,附上一段具体实现代码。
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class People implements Serializable{ private String name; public People(){ this.name = "6点A君"; System.out.println("construct people"); } @Override public String toString() { return this.name; } public static void main(String[] args) { People p = new People(); System.out.println(p); ObjectOutputStream oos = null; ObjectInputStream ois = null; try { FileOutputStream fos = new FileOutputStream("test.out"); oos = new ObjectOutputStream(fos); oos.writeObject(p); oos.close(); } catch (Exception e) { e.printStackTrace(); } People p1; try { FileInputStream fis = new FileInputStream("test.out"); ois = new ObjectInputStream(fis); p1 = (People)ois.readObject(); System.out.println(p1); } catch (Exception e) { e.printStackTrace(); } } }
以上是关于JAVA创建对象的五种方式的主要内容,如果未能解决你的问题,请参考以下文章
Carson带你学Java:解决生产者消费者问题的五种实现方式
Carson带你学Java:解决生产者消费者问题的五种实现方式