反射
一个Class实例包含了该class的所有完整信息:
在实例中保存了该class的所有信息,包括类名、包名、父类、
实现的接口、所有方法、字段等,因此,如果获取了某个Class实例,
我们就可以通过这个Class实例获取到该实例对应的class的所有信息
这种通过Class实例获取class信息的方法称为反射Reflection
┌───────────────────────────┐
* │ Class Instance
* ├───────────────────────────┤
* │name = "java.lang.String" │
* ├───────────────────────────┤
* │package = "java.lang" │
* ├───────────────────────────┤
* │super = "java.lang.Object" │
* ├───────────────────────────┤
* │interface = CharSequence...│
* ├───────────────────────────┤
* │field = value[],hash,... │
* ├───────────────────────────┤
* │method = indexOf()... │
* └───────────────────────────┘
*/
1.获取class对象,三种方式
静态变量class获取
Class class = String.class;
实例变量获取提供的getClass()方法获取
User user = new User();
Class class = user.getClass()
Class的完整包路径名获取Class.forName()方法
Class class = Class.forName("java.lang.String");
获取该类中父类的class就不一样啦,下面这样就可以获取了
Class superClass = String.class.getSuerclass();
2.获取构造方法,创建新的实例
通过反射创建新的实例,可以用Class提供的newInstance()方法
but 它只能调用该类的public无参构造方法,有参和私有的构造你是无法通过 他去创建实例的
User user = User.class.newInstance();
为了调用任意的构造方法,java的反射提供了Constructor对象
Constructor<String> const = String.class.getConstructor(String.class);
通过它创建实例,并通过构造方法赋值
String hello = const.newInstance("hello");
but构造方法私有后还是无法用上面的方式获取的,让后就有了暴力反射获取
Constructor<User> userConst = User.class.getDeclaredConstructor(String.class,String.class);
userConst.setAccessible(ture) //通过这一步设置允许进入访问,强制获取
这一步很重要,没有设置私有构造你去获取就会报错
User user = userConost.newInstance("username","password");
好了现在我们就创建了对象并可以使用了
user.username获取字段值
3.反射获取字段
还是上面说的获取到了对象的Class,就可以获取它的一切信息
我在User中定义的两个String类型的username和password字段
username是private修饰的而password是用public修饰的
Class<User> userClass = User.class;
//通过字段名去获取对应的字段信息
Filed password = userClass.getFiled("password")
输出如下public java.lang.String com.example.demo.reflected.User.password
//获取私字段名有字段
Filed username = userClass.getDeclaredFiled("username");
username中还可以获取很对信息,如type,name,Modifiers等这里就不一一列举了自己动手才是最容易理解的
//User继承了一个基础类Person类,那怎么获取父类中的字段呢,如下
获取父类中的私有id字段
Field declaredField = userClass.getSuperclass().getDeclaredField("id");
//获取所有私有字段字段,不包括父类
Field[] fields = aClass.getDeclaredFields();
//获取所有共有字段包括父类的
Field[] fields = aClass.getFields();
4.反射获取方法
Method getMethod(name, Class...):获取某个public的Method(包括父类)
获取有一个int参数的get方法
Method username = User.class.getMethod("getUsername",int.class);
Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
获取私有的String的get方法,第一个参数是方法名,第二个参数是方法入参类型
Method password = User.class.getDeclareMethod("getPassword",String.class);
获取没有参数的方法不用传入后面的参数类型,因为是无入参的
Method username = User.class.getMethod("print");
Method[] getMethods():获取所有public的Method(包括父类)
Method[] methods = p.getClass().getMethods();
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)
Method[] declaredMethods = p.getClass().getDeclaredMethods();
获取到方法当然最重要的是执行调用啦,我们用invoke方法
User user = User.class.newInstance();
Method method = User.class.getDeclareMethod("getPassword",String.class);
参数一是调用的对象,第二参数是该方法需要传入的对象
调用后是方法的返回值
Object o = method.invoke(user,"123456");
这里要注意的是调用私有方法的时候要执行下面一步
Method.setAccessible(true)允许其调用这一步很重要
使用反射调用方法时,仍然遵循多态原则:即总是调用实际类型的覆写方(如果存在)
好了反射就到这里了其中还有很多内容需要自己去探索,反射对以后学习框架spring aop是很重要的good luck!