反射的概述
JAVA 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java 语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是 Class 类中的方法.所以先要获取到每一个字节码文件对应的 Class 类型的对象.
反射的使用
获取 Class 对象的三种方式
1, 通过对象
Object.getClass();
2, 静态属性
Class clc = Dog.class;
3, Class.forName()
Class clb = Class.forName("com.zgjt.design.refect.Dog");
根据 Class 对象获取 实例对象
Class clb = Class.forName("com.zgjt.design.refect.Dog");
Dog dog = clb.newInstance();
构造方法
Class clb = Class.forName("com.zgjt.design.refect.Dog");
//获取所有公共构造方法
clb.getConstructors();
//获取所有构造方法
clb.getDeclaredConstructors();
//获取某个构造方法(根据参数)
Constructor c = clb.getConstructor(String.class,int.class)
Dog dog = (Dog)c.newInstance("1",2);
成员方法
Class clb = Class.forName("com.zgjt.design.refect.Dog");
//获取所有公共成员方法,包括继承的
Method[] list = clb.getMethods();
//获取所有的成员方法,不包括继承
Method[] list1 = clb.getDeclaredMethods();
//获取单个方法并调用
Dog dog = (Dog)clb.newInstance();
Method m = clb.getMethod("run",String.class);
m.invoke(dog,"测试");
成员变量
Class clb = Class.forName("com.zgjt.design.refect.Dog");
Dog dog = (Dog)clb.newInstance();
//获取私有变量
Field field = clb.getDeclaredField("name");
// 该方法表示取消java语言访问检查
field.setAccessible(true);
System.out.println(field.get(dog));
序列化的概述
序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
如果需要将某个对象保存到磁盘上或者通过网络传输,那么这个类应该实现Serializable接口或者Externalizable接口之一
创建一个 User 实体类
package com.zgjt.design.serializable;
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
@Override
public String toString() {
return new StringBuilder()
.append("name=")
.append(this.name)
.append("age=")
.append(this.age).toString();
}
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;
}
}
测试:
package com.zgjt.design.serializable;
import java.io.*;
public class TestDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = new User();
user.setName("张三");
user.setAge(23);
//序列化
File file = new File("C:\\Users\\GaoXin\\Desktop\\test.html");
ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(file));
o.writeObject(user);
o.close();
//非序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
User newUser = (User)ois.readObject();
ois.close();
System.out.println(newUser.toString());
}
}
深拷贝和浅拷贝
浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,
浅复制:仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
深复制:在计算机中开辟一块新的内存地址用于存放复制的对象。
package com.zgjt.design;
import java.io.Serializable;
import java.util.Date;
public class SerializableObject implements Serializable {
private static final long serialVersionUID = 1L;
private Date date = new Date();
private int age = 11;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public Date getDate() {
return date;
}
public int getAge() {
return age;
}
public void setDate(Date date) {
this.date = date;
}
public void setAge(int age) {
this.age = age;
}
}
package com.zgjt.design;
import java.io.*;
public class PrototypeDemo implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
private String string;
private SerializableObject obj;
/* 浅复制 */
public PrototypeDemo clone() throws CloneNotSupportedException {
PrototypeDemo proto = (PrototypeDemo) super.clone();
return proto;
}
/* 深复制 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 写入当前对象的二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 读出二进制流产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public String getString() {
return string;
}
public void setString(String string) {
this.string = string;
}
public SerializableObject getObj() {
return obj;
}
public void setObj(SerializableObject obj) {
this.obj = obj;
}
}
总结:浅拷贝是复制一个引用,深拷贝是新开辟一个内存地址。