对象创建的五种方式详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/QQ2899349953/article/details/82143414
            </div>
                                                <!--一个博主专栏付费入口-->
         
         <!--一个博主专栏付费入口结束-->
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-4a3473df85.css">
                                    <div id="content_views" class="markdown_views prism-atelier-sulphurpool-light">
                <!-- flowchart 箭头图标 勿删 -->
                <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                    <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                </svg>
                                        <p></p><div class="toc"><h3><a name="t0"></a>目录</h3><ul><li><a href="#Java_2" rel="nofollow" target="_self">一、Java中创建(实例化)对象的五种方式</a></li><ul><li><a href="#1new_2clone_11" rel="nofollow" target="_self">1、new关键字创建对象; 2、调用对象的clone()方法创建对象</a></li><li><a href="#3_82" rel="nofollow" target="_self">3、通过反射对对象进行初始化</a></li><li><a href="#4_182" rel="nofollow" target="_self">4、序列化</a></li><li><a href="#5_275" rel="nofollow" target="_self">5、通过工厂方法返回对象</a></li></ul><li><a href="#Java_278" rel="nofollow" target="_self">二、Java中,类的实例化方法有四种途径:</a></li></ul></div><p></p>

一、Java中创建(实例化)对象的五种方式

  1. 用new语句创建对象,这是最常见的创建对象的方法;
  2. 调用对象的clone()方法;
  3. 运用反射手段,调用java.lang.Class或者java.lang。 reflect.Constructor类的newInstance()实例方法。如:Object obj = Class.forName(“java.lang.Object”)。newInstance();
  4. 通过I / O流(包括反序列化),如运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法;
  5. 通过工厂方法返回对象,如:String str = String.valueOf(23);

1、new关键字创建对象; 2、调用对象的clone()方法创建对象

/**
 * @ClassName Bigwig
 * @Description new关键字创建对象;
 *              调用对象的clone()方法创建对象
 *              测试Cloneable接口的使用
 *              实例化对象
 * @Author lzq
 * @Date 2019/6/15 19:53
 * @Version 1.0
 **/
public class Bigwig implements Cloneable{
    private String name;
    private int age;
public Bigwig(String name,int age) {
    this.name = name;
    this.age = age;
}

public String getName () {
    return name;
}

public int getAge () {
    return age;
}

public void setName(String name) {
    this.name = name;
}

public void setAge(int age) {
    this.age = age;
}

@Override
protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

@Override
public String toString() {
    String s = "姓名是:"+this.name+"\t年龄是:"+this.age;
    return s;
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
public static void main(String[] args) throws CloneNotSupportedException {
        Bigwig p1 = new Bigwig("诸葛亮", 30);  //new关键字创建的对象
        System.out.println(p1);
        Bigwig p2 = null;
        p2 = (Bigwig) p1.clone(); 调用对象的clone()方法创建对象
        System.out.println(p2);
        p2.setAge(51);
        p2.setName("司马懿");
        System.out.println(p2);
    }

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

运行结果:

姓名是:诸葛亮	年龄是:30
姓名是:诸葛亮	年龄是:30
姓名是:司马懿	年龄是:51

 
 
  • 1
  • 2
  • 3

3、通过反射对对象进行初始化


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*

  • 通过反射对对象进行初始化
  • 注意必须有无参数的Constructor
  • 实例化Class类然后调用newInstance()方法

*/

class Student{
private Integer age;
private String name;

public Student() {
System.out.println(“无参构造”);
}

public Student(String name) {
System.out.println(“一参构造”);
}

public Student(String name,Integer age) {
System.out.println(“双参构造”);
}

}
public class TestClass {
public static void main(String[] args) {
try{
Class clazz = Class.forName(“com.xagy.lianxi.Student”);
/**
* 调用无参构造函数,
* 效果上和使用class.newInstance()差不多
* 构造函数无参的情况下,可以传入一个空数组,也可以不传入数组
*/
Constructor<Student> con = clazz.getConstructor();
Student thisIsTestClass = con.newInstance();
System.out.println("-------------------------------------");

       //依然是无参构造函数
       Class[] paramTypeEmpty = {};
       Constructor&lt;Student&gt; con0 = clazz.getConstructor(paramTypeEmpty);
       Object[] paramEmpty = {};
       Student thisIsTestClassEmpty = con0.newInstance(paramEmpty);
       System.out.println("-------------------------------------");
       
       //getConstructor接受变长参数,以Class数组形式传入,
       //告诉jdk我们要调用哪个构造器
       Class[] paramType1 = {String.class};
       Constructor&lt;Student&gt; con1 = clazz.getConstructor(paramType1);

       //Constructor实例的newInstance同样也是接受一个变长参数,
       //参数数组中类型要和getConstructor的类型对应
       Object[] params1 = {"ParamOne"};
       Student thisIsTestClass1 = con1.newInstance(params1);
       System.out.println("-------------------------------------");

       //params2中的数据类型要和paramTypes2中的类型相对应
       Class[] paramTypes2 = {String.class,Integer.class};
       Constructor&lt;Student&gt; con2 = clazz.getConstructor(paramTypes2);
       Object[] params2 = {"ParamOne",2};
       Student thisIsTestClass2 = con2.newInstance(params2);
       System.out.println("-------------------------------------");
    }catch(ClassNotFoundException e){
        e.printStackTrace();
    }catch (NoSuchMethodException e){
        e.printStackTrace();
    }catch (SecurityException e){
        e.printStackTrace();
    }catch (InstantiationException e){
        e.printStackTrace();
    }catch (IllegalAccessException e){
        e.printStackTrace();
    }catch (IllegalArgumentException e){
        e.printStackTrace();
    }catch (InvocationTargetException e){
        e.printStackTrace();
    }
  }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

运行结果:

无参构造
-------------------------------------
无参构造
-------------------------------------
一参构造
-------------------------------------
双参构造
-------------------------------------

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4、序列化

①、序列化是干什么的?
简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自 己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。

②、什么情况下需要序列化
a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;

③、相关注意事项
a)序列化时,只对对象的状态进行保存,而不管对象的方法;
b)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;
c)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
d)并非所有的对象都可以序列化,,至于为什么不可以,有很多原因了,比如:
Ⅰ.安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行rmi传输 等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的。
Ⅱ. 资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分 配,而且,也是没有必要这样实现。

import java.io.*;

/**

  • @ClassName TestDemo7
  • @Description 对象序列化
  • @Author lzq
  • @Date 2018/12/11 11:36
  • @Version 1.0
    **/

class Student implements Serializable {
private static final long serialVersionUID = -88175599799432325L;
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String toString() {
return “name=” + name + “, age=” + age;
}
}

public class TestDemo7 {
public static void main(String[] args) {
String filename = “F:/FHB/serialize.txt”;
serialize(filename);
reverse_serialize(filename);
}

/**
 * 序列化
 */
public static void serialize(String filename) {
    try {
        OutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeInt(12345);
        oos.writeObject("Today");
        oos.writeObject(new Student("lzq",20));
        oos.close();
        fos.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 反序列化
 */
public static void reverse_serialize(String filename) {
    try {
        InputStream in = new FileInputStream(filename);
        ObjectInputStream obj = new ObjectInputStream(in);
        int i = obj.readInt();
        String str = (String)obj.readObject();
        Student student = (Student)obj.readObject();
        System.out.println(i);
        System.out.println(str);
        System.out.println(student);
        obj.close();
        in.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
12345
Today
name=lzq, age=20

 
 
  • 1
  • 2
  • 3

5、通过工厂方法返回对象

单例模式

二、Java中,类的实例化方法有四种途径:

1)使用new关键字

2)利用反射,调用Class对象的newInstance()方法

3)调用clone()方法,对现有实例的拷贝

4)利用反序列化,通过ObjectInputStream的readObject()方法反序列化类

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

class ClassInstance implements Cloneable, Serializable {
private String str = “测试…”;
public void fun(){
System.out.println(str);
}

public ClassInstance(String str) {
	 System.out.println("有参类的实例化");
	 this.str += str;
}

public ClassInstance() {
	 System.out.println("无参类的实例化");
}

public Object clone() {
	 return this;
}

}
public class ClassInstanceTest{
public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, IOException,InvocationTargetException, NoSuchMethodException{
//第一种类的实例化方式
ClassInstance ci01 = new ClassInstance(“01”);
ci01.fun();

    //第二种类的实例化方式
    ClassInstance ci02 = (ClassInstance) Class.forName("com.xagy.lianxi.ClassInstance").newInstance();
    ci02.fun();

   //第三种类的实例化方式
   ClassInstance ci03 = (ClassInstance) ci01.clone();
   ci03.fun();

   //第四种类的实例化方式
   FileOutputStream fos = new FileOutputStream("D:\\ci.txt");
   ObjectOutputStream oos = new ObjectOutputStream(fos);
   oos.writeObject(ci01);
   oos.close();
   fos.close();
   FileInputStream fis = new FileInputStream("D:\\ci.txt");
   ObjectInputStream ois = new ObjectInputStream(fis);
   ClassInstance ci04  = (ClassInstance) ois.readObject();
   ois.close();
   fis.close();
   ci04.fun();
   
   System.out.println("--------------------额外测试--------------------");
   ClassInstance ci05 = null;
   //额外的思考 在第二种类实例化的方式中有没有一种方法实现有参数的构造方式
   //获得类的构造信息
   Constructor[] ctor = Class.forName("com.xagy.lianxi.ClassInstance").getDeclaredConstructors();
   //找到我们需要的构造方法
   for(int i=0;i&lt;ctor.length;i++ ){
       Class[] cl = ctor[i].getParameterTypes();
       if(cl.length == 1){
          //实例化对象
           ci05 = (ClassInstance) Class.forName("com.xagy.lianxi.ClassInstance").getConstructor(cl).newInstance(new Object[]{"05"});
       }
   }
   ci05.fun();
  }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
有参类的实例化
测试...01
无参类的实例化
测试...
测试...01
测试...01
--------------------额外测试--------------------
有参类的实例化
测试...05
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
                                </div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-b6c3c6d139.css" rel="stylesheet">
                </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值