个性化阅读
专注于IT技术分析

用Java创建对象的几种方法

本文概述

用Java创建对象有五种不同的方法:

  • Java新运算符
  • Java Class.newInstance()方法
  • 构造函数的Java newInstance()方法
  • Java Object.clone()方法
  • Java对象序列化和反序列化

1)Java新操作员

这是用Java创建对象的最流行的方法。在新运算符之后, 还会调用构造函数, 以初始化新对象。创建对象时, 它会占用堆中的空间。

句法

class_name object_name = new class_name()

Java new运算符示例

public class A
{
String str="hello";
public static void main(String args[])
{
A obj=new A();	//creating object using new keyword
System.out.println(obj.str);
}
}

输出:

用Java创建对象的几种方法

2)Java Class.newInstance()方法

Java Class.newInstance()是Class类的方法。 Class类属于java.lang包。它创建此Class对象表示的类的新实例。它返回新创建的类实例。

句法

public T newInstance() throws IllegalAcccessException, InstantiationException

如果无法访问该类或其无效构造函数, 则抛出IllegalAccessException。如果Class表示抽象类, 接口, 数组类或原始类型, 则还会引发InstantiationException。

public class NewInstanceExample
{
String str="hello";
public static void main(String args[])
{
try
{
//creating object of class
NewInstanceExample obj= NewInstanceExample.class.newInstance(); 
System.out.println(obj.str);		
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

输出:

用Java创建对象的几种方法

3)构造器类的Java newInstance()方法

Java Constructor类还具有类似于Class类的newInstance()方法的newInstance()方法。 newInstance()方法属于java.lang.reflect.Constructor类。这两种newInstance()方法都被称为创建对象的反射方式。实际上, Class类的newInstance()方法在内部使用了Constructor类的newInstance()方法。该方法返回通过调用构造函数创建的新对象。

句法

public T newInstance(Objects...initargs)

newInstance()方法引发以下异常:

  • IllegalAccessException:如果构造函数不可访问。
  • IllegalArgumentException:如果实际参数和形式参数的数量不同。
  • InstantiationException:如果类构造函数表示一个抽象类。
  • InvocationTargetException:如果基础构造函数引发异常。
  • ExceptionInInitializerError:如果此方法引发的初始化失败。

import java.lang.reflect.Constructor;
public class NewInstanceExample1
{
String str="hello";
public static void main(String args[])
{
try
{
Constructor<NewInstanceExample1> obj =NewInstanceExample1.class.getConstructor();
NewInstanceExample1 obj1 = obj.newInstance();
System.out.println(obj1.str);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

输出:

用Java创建对象的几种方法

4)Java Object.clone()方法

Java clone()方法创建一个现有对象的副本。它在Object类中定义。它返回此实例的克隆。有关clone()方法的两个最重要的点是:

  • 使用clone()方法时, 必须实现Cloneable接口。它在java.lang包中定义。
  • clone()方法必须被其他类覆盖。

当我们在类中使用clone()方法时, 该类必须调用super.clone()以获得克隆的对象引用。

句法

protected Object clone() throws CloneNotSupportedException

如果Object类不支持Cloneable接口, 则此方法将引发CloneNotSupportedException。当覆盖clone()方法的子类指示无法克隆实例时, 也会引发此异常。

public class CloneExample implements Cloneable 
{ 
//creates and returns a copy of this object
protected Object clone() throws CloneNotSupportedException 
{ 
return super.clone(); 
} 
String name = "Microprocessor"; 
public static void main(String[] args) 
{ 
CloneExample obj1 = new CloneExample(); 	//creating object of class
try
{ 
CloneExample obj2 = (CloneExample) obj1.clone(); 
System.out.println(obj1.name); 
} 
catch (Exception e) 
{ 
e.printStackTrace(); 
} 
} 
}

输出:

用Java创建对象的几种方法

5)Java对象序列化和反序列化

一个类必须实现属于java.io包的Serializable接口。 Serializable接口没有任何方法和字段。它们为班级增加了特殊的行为。 Marker接口在Java 8中不使用。它被Annotations取代。

每当我们序列化和反序列化对象时, JVM都会创建一个单独的空间。它不使用任何构造函数来创建对象。

对象序列化

ObjectOutputStream类用于序列化对象。序列化是将对象转换为字节序列的过程。

ObjectOutputStream类的writeObject()方法序列化对象, 然后将指定的对象写入ObjectOutputStram类。该方法的签名是:

public final void writeObject(Object obj) throws IOException

该方法接受一个对象作为参数。

对象反序列化

根据字节序列创建对象的过程称为对象反序列化。 ObjectInputStream类的readObject()方法从ObjectInputStram类读取一个对象并将其反序列化。该方法的签名是:

public final Object readObject() throws IOException

该方法不接受任何参数。它返回从流中读取的对象。该方法引发以下异常:

  • ClassNotFoundException:如果找不到序列化的类。
  • InvalidClassException:序列化使用的类出了点问题。
  • IOException:任何与输入/输出相关的常规异常。
  • OptionalDataException:如果在流而不是对象中找到原始数据。

在下面的示例中, 我们首先序列化了对象, 然后反序列化了对象。

import java.io.*; 
class Demo implements Serializable 
{ 
public int i; 
public String s; 
public Demo(int i, String s) //default constructor
{ 
this.i = i; 
this.s = s; 
}   
} 
public class DeserializationExample 
{ 
public static void main(String[] args) 
{    
Demo object = new Demo(8, "srcmini"); 
String filename = "Demofile.ser"; 		//specified file name (must have extension .ser)
/*-----------------Serialization----------*/
try
{    
FileOutputStream file = new FileOutputStream(filename);  //Saving of object in the file 
ObjectOutputStream out = new ObjectOutputStream(file);   
out.writeObject(object); 			//serialize object
out.close(); 					//closes the ObjectOutputStream
file.close(); 					//closes the file
System.out.println("Object serialized"); 
} 
catch(IOException e) 
{ 
e.printStackTrace();
} 
Demo obj = null; 
/*-----------------Deserialization--------*/
try
{    
FileInputStream file = new FileInputStream(filename); // reading an object from a file 
ObjectInputStream is = new ObjectInputStream(file); 
obj = (Demo)is.readObject(); 		//deserialize object
is.close(); 					//closes the ObjectInputStream
file.close(); 					//closes the file
System.out.println("Object deserialized "); 
System.out.println("number = " + obj.i); 
System.out.println("string = " + obj.s); 
} 
catch(IOException e) 
{ 
System.out.println("IOException is caught"); 
} 
catch(ClassNotFoundException e) 
{ 
System.out.println("ClassNotFoundException is caught"); 
}
} 
}

输出:

用Java创建对象的几种方法

Java克隆的概念

在OOP中, 复制对象意味着创建现有对象的克隆。复制对象有很多方法。其中两个是-复制构造函数和克隆。 Java有两种类型的克隆:

  • 浅克隆
  • 深克隆

深拷贝和浅拷贝都是对象克隆的类型。当谈论一个对象时, 我们将其视为一个无法进一步细分的单元。

假设我们有一个Student对象。学生对象包含其他对象, 如下图所示。学生对象包含名称和地址对象。 Name包含FirstName和LastName对象, Address对象由Street和city对象组成。当我们谈论学生时, 我们所谈论的是整个对象网络。

用Java创建对象的几种方法

当我们想要修改或移动对象同时仍保留原始对象时, 将创建对象的克隆。

浅克隆

  • 每当我们使用clone()方法的默认实现时, Java都会使用浅层克隆。
  • 浅层克隆对象会创建主要对象的克隆, 但不会复制内部对象。
  • 内部对象在原始对象及其副本之间共享。

例如, 如果要创建学生的浅表副本, 则应创建学生的第二个对象。但是两个对象共享相同的名称和地址。考虑以下示例:

public class Student
{
private Name name ;
private Address address;
public Student(Student orgStudent)
{
this.name=orgStudent.name;
this.address=orgStudent.address;
}
}

浅表副本的缺点是两个对象不是独立的。当我们修改一个Student的Name对象时, 它也会同时修改另一个Student对象。

在下面的示例中, 我们有一个带有参考变量mba的Student对象;然后我们制作MBA的副本, 创建第二个Student对象mca。如果mca尝试通过修改其Address对象来移动moveOut(), 则mba随之移动。

Student mba=new Student(new Name(...), new Address(...));
Student mca=new Student(mba);
mca.moveOut(new Street(...), new City(...));

这是因为mba和mca对象共享相同的Address对象。如果我们更改一个对象中的地址, 它将同时修改两个对象。

深克隆

  • 深克隆是对象的完全独立的副本。
  • 因此, 对于深层复制, 我们需要确保所有成员类也都实现Cloneable接口, 并重写Object类的clone()方法。

当我们修改一个Student对象的Address对象时, 它不会修改另一个Student对象。在下面的代码中, 我们可以看到, 我们不仅在Student对象上使用了复制构造函数, 而且还在内部对象上使用了复制构造函数。

public class Student
{
private Name name ;
private Address address;
public Student(Student otherStudent)
{
this.name=new Name(otherStudent.name);
this.address=new Address(otherStudent.address);
}
}

要创建深度克隆, 我们需要继续复制所有Student对象的嵌套元素, 直到只有基本类型和Immutable为止。

public class Street
{
private String name;		//instance variable
private int number;
public Street(Street otherStreet)
{
this.name=otherStreet.name;
this.number=otherStreet.number;
}
}

Street对象具有两个实例变量名称和编号。该数字是原始整数值, 而不是对象。无法共享。创建第二个实例变量时, 我们将自动创建一个独立副本。在上面的代码中, 字符串是一个不可变的对象, 即一旦创建, 就无法再更改。因此, 我们可以共享它而无需创建它的深层副本。


赞(0)
未经允许不得转载:srcmini » 用Java创建对象的几种方法

评论 抢沙发

评论前必须登录!