反射机制是JAVA的核心知识点之一,大多数框架的实现原理就是利用了反射机制,掌握反射机制会使你学习框架更加轻松高效
回答上面这个问题的时候,我们先讨论下class的加载方式和流程
1、一个java文件通过javac编译后得到class文件
2、当我们执行了初始化操作的时候(可能时new,也有可能时父类初始化,子类初始化,反射...),会将class文件通过类加载器加载到jvm中,
3、将.class文件加载到JVM中,会分成好几个步骤,中间有加载,链接,初始化
4、在加载的过程中,会在java堆中创建一个java.lang.Class的对象,这个对象就代表这类相关的信息
5、java中的反射就是利用了Class这个类去实现的
如下图:
这时候就引发了一个问题?常见的new对象的方式和这种有什么区别呢?
new对象的方式:编译期已经确定类型,且性能会比反射好,但是灵活性不强,尤其在现代工业中(PS:需求一天一变)
反射:使用时动态调用创建,性能略差但是灵活,在现在框架中大量使用
1、用于获取与类相关的各种信息, 提供了获取类信息的相关方法
2、Class类继承自Object类
3、Class类是所有类的共同的图纸
4、每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。
5、没有构造方法,通过jvm加载而出
要想操作反射,必须先拿到反射的入口
1,通过通过Class.forName("全类名")
try {
Class perClazz = Class.forName("reflect_fanshe.Person");
System.out.println(perClazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2、类名.class
Class perClazz2 = Person.class;
3、对象.getClass()
Person person = new Person();
Class perClazz3 = person.getClass();
1:perClazz.getMethods() 获取此类的所有public方法(父类的,实现接口的,自己的)
Class perClazz = null;
try {
perClazz = Class.forName("reflect_fanshe.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Method[] methods = perClazz.getMethods();
//遍历所有方法
for (Method method : methods) {
System.out.println(method);
}
}
2:获取所有的构造方法
3、 获取父类
4、获取当前类(只有本类的)的所有方法和属性,包括私有的
暴力反射?
获取类的私有成员。通过setAccessible(true)方法,设置成可访问。
field.setAccessible(true); // 私有变量必须设置访问权限为true
例:对工厂模式的改进
常规工厂模式
interface Fruit {
void eat();
}
class Apple implements Fruit {
public void eat(){
System.out.println("Eat Apple");
}
}
class Orange implements Fruit {
public void eat(){
System.out.println("Eat Orange");
}
}
//编译时就确定类型,不够灵活,不好新增,如果我要新增一个实现类,就要在工厂类中改代码,耦合度较高。
public class Factory {
public static Fruit getInstance(String fruitName){
Fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
改进后
public class ReflexFactory {
public static Fruit2 getInstances(String className) {
Fruit2 f2 =null;
try {
//利用反射
f2 = (Fruit2)Class.forName(className).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f2;
}
}
当如果要新增实现类的话,只要将传入的参数改变就好,无需更改工厂内的代码。
IO技术、ServerSocket技术和反射技术。
(1).对外暴露接口---->著名的Servlet (服务器脚本片段)
[1]. 对外提供接口的原因:具体处理客户端应答请求的方式是不一样的。应该根据具体的请求来进行具体的处理。向上抽取形成Servlet接口并提供给客户端使用。
[2]. 由开发者来实现Servlet接口中定义的具体应答请求的处理方式。
(2).提供配置文件---->web.xml (WEB宏观部署描述文件)
每个Web应用程序都有自己的配置文件web.xml来告知Tomcat服务器(App)有哪些用户自定义的Servlet实现类。
(1). Tomcat(App)首先读取配置文件web.xml中配置好的Servlet的子类名称
(2).Tomcat根据读取到的客户端实现的Servlet子类的类名字符串去寻找对应的字节码文件。如果找到就将其加载到内存。
(3).Tomcat通过预先设置好的Java反射处理机制解析字节码文件并创建相应的实例对象。之后调用所需要的方法。
【最后】Tomcat一启动,用户自定义的Servlet的子类通过Tomcat内部的反射框架也随之运行。
例:拦截器,注解、XML文档、token登录拦截
参考博客
https://blog.csdn.net/weixin_42724467/article/details/84311385
https://blog.csdn.net/21aspnet/article/details/89402714
https://blog.csdn.net/u010349644/article/details/82498452
https://blog.csdn.net/qq_23143621/article/details/100537532
https://blog.csdn.net/jinwufeiyang/article/details/80115119
https://blog.csdn.net/qq_37469998/article/details/88729423