目录
前言:
什么是反射?
哪里用到反射机制?
反射的案例:
反射练习之越过泛型检查:
什么叫对象序列化,什么是反序列化,实现对象序列化需要做哪些工作?
对象序列化流:
注意事项:
对象反序列化流:
反射的优缺点:
动态代理是什么?有哪些应用?
怎么实现动态代理?
Java反射机制的作用
想要快速了解Java中的反射,那么我们不妨花几分钟来看看反射中常见的一些问题。关于这些问题,博主自己总结了一些以及在各位优秀博主共同提到的问题相结合得到的。希望对爱学习的你有一丢丢帮助。
反射是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。
JDBC中,利用反射动态加载了数据库驱动程序。
Web服务器中利用反射调用了Sevlet的服务方法。
Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
很多框架都用到反射机制,注入属性,调用方法,如Spring。
通过反射技术,向一个泛型为Integer的集合中添加一些字符串数据。
public class ReflectTest01 {
public static void main(String[] args) throws Exception {
//创建集合
ArrayList array = new ArrayList();
// array.add(10);
// array.add(20);
// array.add("hello");
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
“
m.invoke(array,"hello");
m.invoke(array,"world");
m.invoke(array,"java");
System.out.println(array);
}
}
对象序列化:将对象中的数据编码为字节序列的过程。
反序列化:将对象的编码字节重新反向解码为对象的过程。
JAVA提供了API实现了对象的序列化和反序列化的功能,使用这些API时需要遵守如下约定:
被序列化的对象类型需要实现序列化接口,此接口是标志接口,没有声明任何的抽象方法,JAVA编译器识别这个接口,自动的为这个类添加序列化和反序列化方法。
为了保持序列化过程的稳定,建议在类中添加序列化版本号。
不想让字段放在硬盘上就加transient
以下情况需要使用 Java 序列化:
想把的内存中的对象状态保存到一个文件中或者数据库中时候;
想用套接字在网络上传送对象的时候;
想通过RMI(远程方法调用)传输对象的时候。
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
对象序列化流: ObjectOutputStream:
将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));
//创建对象
Student s = new Student("林青霞",30);
//void writeObject(Object obj):将指定的对象写入ObjectOutputStream
oos.writeObject(s);
//释放资源
oos.close();
}
}
一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口。
Serializable是一个标记接口,实现该接口,不需要重写任何方法。
对象反序列化流: ObjectInputStream。
构造方法:ObjectInputStream(InputStream in)
创建从指定的InputStream读取的ObjectInputStream
反序列化对象的方法:
Object readObject()
从ObjectInputStream读取一个对象
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));
//Object readObject():从ObjectInputStream读取一个对象
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
优点:可以动态执行,在运行期间根据业务功能动态执行方法、访问属性,最大限度发挥了java的灵活性。
缺点:对性能有影响,这类操作总是慢于直接执行java代码。
动态代理是运行时动态生成代理类。
动态代理的应用有 Spring AOP数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。
JDK 原生动态代理和 cglib 动态代理。
JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
感谢爱学习的你耐心看到了这里,那么这次的学习就到这里咯,下次见,拜拜~~