创建对象的几种方式
1,new
Student s = new Student();
在堆储存区开辟了一块空间,其对象的引用存储在栈存储区上。
2,反射 reflect
java的反射机制是指,在运行状态中,对于任意一个类,我们可以获取这个类的属性和方法,对于任意一个对象,我们可以调用这个对象的方法和属性。这种动态获取信息和动态调用对象的方法就是java 的反射机制。
Class 类,每个class 都会有一个Class对象,当我们完成一个类通过编译之后,就会生成一个.class 文件,在生成的.class 文件中,就会有个Class 对象,用于表示这个类的类型信息。
获得类的Class 对象的3中方法:
1,类名.class (任意数据类型,都会有一个class 属性)
2,Class.forName("java.lang.String"); 类的全路径
3,类的实例化对象下,有getClass() 方法。
反射创建对象:
不存在有参的构造函数:
方法1:
类名.class.newInstance(); 就算没有构造方法,也会调用默认的无参构造方法
Demo newInstance = Demo.class.newInstance();
newInstance.setUserName("chris");
newInstance.setPassword("12345");
System.out.println(newInstance.getUserName()+ newInstance.getPassword());
方法2:
和方法1本质相同,一个是使用类名.class ,一个是使用Class.forName("类的全路劲")来获取类的类对象,再通过newInstance()方法创建对象。
Class<Demo> clazz = (Class<Demo>) Class.forName("Demo");
Demo newInstance2 = clazz.newInstance();
newInstance2.setPassword("12345");
newInstance2.setUserName("Sarah");
System.out.println(newInstance2.getUserName()+ newInstance2.getPassword());
存在有参的构造函数:
先获取类的Class 对象,通过类对象获取到指定的构造器,可以是有参,可以是无参,通过指定的构造器,创建对象
Class<Demo> clazz3 = (Class<Demo>) Class.forName("Demo");
Constructor<Demo> con = clazz3.getDeclaredConstructor(String.class,String.class);
Demo newInstance3 = con.newInstance("Mike","12345");
//newInstance3.setUserName("vincent");可以通过反射是可以改变对象的值
//newInstance3.setPassword("12345");
System.out.println(newInstance3.getUserName()+ newInstance3.getPassword());
Class对象获取构造器比较:
Constructor<Demo> con = clazz3.getDeclaredConstructor(String.class,String.class); //能获取到指定参数的构造器,和访问修饰符无关,private,public 所有的可以获取到
Constructor<?>[] conn = clazz4.getConstructors();//所有public 修饰的构造器
Constructor<Demo> connn = clazz5.getConstructor(String.class,String.class);//所有public 修饰的带参数的指定构造器
反射的应用场景:
jdbc的连接
Class.forName("com.mysql.jdbc.Driver")
springIOC反射创建对象
mybatis
3,clone
调用clone,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
前提,必须要实现Cloneable 接口,本地实现 protected native Object clone() throws CloneNotSupportedException;
Demo clone = (Demo) newInstance.clone();
4,反序列化
序列化:将堆内存中的java 对象通过某种方式,存储到磁盘上或者传输给其他网络节点,也就是java对象转成二进制。
反序列化:与序列化相反,再将序列化之后的二进制串再转成数据结构或对象。
为什么需要做序列化?
1,网络节点的传输,java 对象需要转成二进制串。
2,服务器钝化:如果在内存中,一个对象长时间没有被调用,就会将其序列化存储在本地磁盘上,有需要活动的时候,就会现在内存中寻找,找不到,会将磁盘上的二进制再次反序列化成java 对象。可以节省服务器内存。
实现序列化?
1,需要做序列化的对象的类,必须实现序列化接口:Java.lang.Serializable 接口
通过反序列化创建对象。
//本地创建a.txt 文件,并且把对象序列化转成二进制写进文件中
File f = new File(String path)
OutputStream op = new FileOutputStream(file);
ObjectOutputStream ops = new ObjectOutputStream(op);
ops.writeObject(new Demo("Chris", "12345"));
ops.close();
//从写进的文件中,读取二进制串,用对象流将其读出
InputStream in = new FileInputStream(file);
ObjectInputStream os = new ObjectInputStream(in);
Demo d = (Demo) os.readObject();
System.out.println(d.getUserName()+ d.getPassword());
os.close();
反序列化 请注意深复制和浅复制