Java中创建对象的四种方式
- 用new语句创建对象,这是最常见的创建对象的方法。
1 | User user = new User(); |
- 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
通过反射来生成对象有如下两种方式:
①使用Class对象的newInstance()方法来创建该Class对象对应类的实例。但是这种方式要求该Class对象的对应类有默认的构造器,而执行newInstance()方法时实际上是利用默认构造器来创建该类的实例。
②先使用Class对象获取指定的Constructor对象,再调用Construtor对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用某个类的指定构造器来创建实例。
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 84 85 86 87 88 89 90 | package com.zwk.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; //动态的创建对象,通过反射 public class Test08 { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { //获得Class对象 Class c1 = Class.forName("com.zwk.reflection.User"); //构造一个对象 User user = (User) c1.newInstance();//本质是调用类的无参构造器 System.out.println(user); //通过构造器创建对象 Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user1 = (User) constructor.newInstance("张三", 001, 18); System.out.println(user1); //通过反射调用普通方法 User user2 = (User) c1.newInstance(); //通过反射获取一个方法 Method setName = c1.getDeclaredMethod("setName", String.class); //invoke:激活的意思 //(对象,"方法的值") setName.invoke(user2,"张三"); System.out.println(user2.getName()); //通过反射操作属性 User user3 = (User) c1.newInstance(); Field name = c1.getDeclaredField("name"); //不能直接操作私有属性, 我们需要关闭程序的安全检测,属性或者方法的setAccessible(true); name.setAccessible(true);// name.set(user3,"李四"); System.out.println(user3.getName()); } } class User{ private String name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } private void test(){ } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; } } |
- 调用对象的clone()方法。
- 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
- 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。(native为本地方法)
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 | package com.zwk.test; public class Test { public static void main(String[] args) { User user = new User(101,"张三",18,"男"); User user1 = (User)user.clone();//运用clone()方法产生新对象 System.out.println("user"+user.toString()); System.out.println("user1"+user1.toString()); } } class User implements Cloneable{//被复制的类需要实现Clonenable接口 private int id; private String name; private int age; private String sex; public Object clone(){//覆盖clone()方法,访问修饰符设为public User user = null; try { user = (User)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return user; } public User() { } public User(int id, String name, int age,String sex) { this.id = id; this.name = name; this.age = age; this.sex = sex; } public User born(int id, String name, int age,String sex){ this.id = id; this.name = name; this.age = age; this.sex = sex; return this; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } } |
结果:
user User{id=101, name=‘张三’, age=18, sex=‘男’}
user1 User{id=101, name=‘张三’, age=18, sex=‘男’}
- 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。
保存Person类的某三个对象的id,name、age、sex这四个成员变量
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 84 85 86 87 88 89 90 91 92 | package com.zwk.test; import java.io.*; /** * java对象的序列化和反序列化 */ public class SerializableTest { public static void main(String[] args) throws Exception { Person zhangsan = new Person(101, "张三", 18, "男"); Person lisi = new Person(102, "李四", 18, "男"); Person xiaohong = new Person(103, "小红", 18, "女"); //序列化 //需要一个文件输出流和对象输出流;文件输出流用于将字节输出到文件,对象输出流用于将对象输出为字节 ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("person.ser")); ous.writeObject(zhangsan); ous.writeObject(lisi); ous.writeObject(xiaohong); //反序列化 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser")); Person person1 = (Person) ois.readObject(); Person person2 = (Person) ois.readObject(); Person person3 = (Person) ois.readObject(); System.out.println(person1.toString()); System.out.println(person2.toString()); System.out.println(person3.toString()); ois.close(); ous.close(); } } class Person implements Serializable{//要序列化某个类的对象,这个类必须实现Serializable接口,该接口是个空接口,即该接口中没声明任何方法。 private int id; private String name; private int age; private String sex; public Person() { } public Person(int id, String name, int age, String sex) { this.id = id; this.name = name; this.age = age; this.sex = sex; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } } |
结果:
person1 Person{id=101, name=‘张三’, age=18, sex=‘男’}
person2 Person{id=102, name=‘李四’, age=18, sex=‘男’}
person3 Person{id=103, name=‘小红’, age=18, sex=‘女’}
- 进行对象序列化主要目的是为了保存对象的状态(成员变量)。
- 进行序列化主要用到的流是FileOutputStream和ObjectOutputStream。FileOutputStream主要用于连接磁盘文件,并把字节写出到该磁盘文件;ObjectOutputStream主要用于将对象写出为可转化为字节的数据。
- 要将某类的对象序列化,则该类必须实现Serializable接口,该接口仅是一个标志,告诉JVM该类的对象可以被序列化。如果某类未实现Serializable接口,则该类对象不能实现序列化。
- 保存状态的目的就是为了在未来的某个时候再恢复保存的内容,这可以通过反序列化来实现。对象的反序列化过程与序列化正好相反,主要用到的两个流是FileInputstream和ObjectInputStream。
- 反序列化后得到的对象的顺序与保存时的顺序一致。