反射机制
个人理解:
在运行代码/编译代码时,在此期间通过调用(.class)方式,得到你想要的类,任意构造器,方法,属性等,特别的,私有的方法也可以被得到。
不使用反射的类,就要考虑类的封装性,例如person类,就不可以调用person里面私有的类
在实际开发中,很少使用反射。
在设计框架的时候就经常使用反射,所以在学习框架源码时,就需要学习反射,体现了反射的动态性;
框架 = 注解 + 反射 + 设计模式
封装性:体现的是建议我们是否调用里面的方法,如果是建议的话,就是用public,不建议就使用private
反射:类是全部完整的存在内存中,所以我们就有能去调用里面的所有方法
以下图就是反射例子,好比一个镜子:
反射最重要的用途就是开发各种通用框架。
反射的应用:
1、创建运行时类的对象:通过Class的实例调用newInstance()方法即可;
Class<?> c = String.class;
Object str = c.newInstance();
注意:创建对象成功,需要满足:
-
要求运行时类中必须提供一个空参的构造函数
-
要求提供的空参构造函数的权限要足够
2、JavaBean中要求给当前类提供一个公共的空参的构造函数,有什么用?
-
子类对象在实例化时,子类的构造器的首行是先调用父类的构造器
-
在反射中,经常用来创建运行时的对象。所以我们在编写代码时,要在pojo包下的类写一个空参构造器,便于我们创建运行代码时类的对象。
3、调用指定的属性,方法,构造函数
public class test01 { /* 调用运行时的属性: 主要是这几个方法,在此不再赘述: getFiled:访问公有的成员变量 getDeclaredField:所有已声明的成员变量,但不能得到其父类的成员变量 getFileds 和 getDeclaredFields 方法用法同上(参照 Method)。 */ @Test public void test1() throws Exception { //在运行时创建类对象 Class clazz = Person.class; Person per = (Person) clazz.newInstance(); //getDeclaredField 获得运行时的某一属性 Field field = clazz.getDeclaredField("name"); //确保此属性是可以访问的 field.setAccessible(true); //set/get 设置和获取操作 field.set(per,"ljx"); System.out.println(field.get(per)); } /* 调用运行时的方法: 获取某个Class对象的方法集合,主要有以下几个方法: getDeclaredMethods 方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包 括继承的方法。 public Method[] getDeclaredMethods() throws SecurityException getMethods 方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。 public Method[] getMethods() throws SecurityException getMethod 方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象。 public Method getMethod(String name, Class<?>... parameterTypes) */ @Test public void test2() throws Exception { Class clazz = Person.class; Person per = (Person) clazz.newInstance(); //通过getDeclaredMethod指定是方法 Method method = clazz.getDeclaredMethod("Method", int.class); //确保此方法是可以访问的 method.setAccessible(true); //通过invoke设置类方法中的值 Object invoke = method.invoke(per, 15); System.out.println(invoke); } /* 调用运行时的构造函数: 获取类构造器的用法与上述获取方法的用法类似。主要是通过Class类的getConstructor方法得到Constructor 类的一个实例, 而Constructor类有一个newInstance方法可以创建一个对象实例: public T newInstance(Object ... initargs) 此方法可以根据传入的参数来调用对应的Constructor创建对象实例。 */ @Test public void test3() throws Exception { Class clazz = Person.class; //通过getDeclaredConstructor获得构造函数的参数类型 Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class); //确保此构造函数是可以访问的 constructor.setAccessible(true); //通过newInstance获得构造函数的参数 Person person = (Person) constructor.newInstance("ljx", 15); System.out.println(person); } }
问题:
-
对反射有了解吗?反射有什么好处?为什么需要反射?
-
反射是如何实现的?
从class说起。
-
class类的作用?生成class对象的方法有哪些?
反射的源头。
方法有三种:
(1) 使用 Class 类的
forName
静态方法:public static Class<?> forName(String className)
```
比如在 JDBC 开发中常用此方法加载数据库驱动:
```java
Class.forName(driver);(2)直接获取某一个对象的 class,比如:
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;(3)调用某个对象的
getClass()
方法,比如:StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass(); -
Class.forName("全路径")会调用哪些方法?会调用构造函数吗?加载类会放在哪里?
Class.forName()会执行执行类构造器<clinit>()方法。
不会调用构造函数。
加载的类放在方法区。
-
如何找到对象的实际类?
对象.getclass( )
Object date = new Date();
date.getClass();
//获取到的是Date -