反射是为了解决在运行期,对某个实例一无所知的情况下,如何获取和使用类的属性方法等信息。
是一种代理模式,不用自己new对象
反射
一、Class类
通过反射获取类信息(拿到Class实例)有以下三种方式(用String类做案例):
1、直接通过一个class的静态变量class获取:
Class cls = String.class;
2、如果有一个实例变量,可以通过该实例变量提供的getClass()方法获取:
String s = "Hello";
Class cls = s.getClass();
3、如果知道一个class的完整类名,可以通过静态方法Class.forName()获取:
Class cls = Class.forName("java.lang.String");
二、获取类信息后,解析类中属性的信息
1、可以用其中的get…方法获取类的多种信息
System.out.println(cls1.getName());
...
2、访问字段信息和赋值
步骤1:得到类信息后,
Student s = new Student("xiaoming");
Class c = s.getClass();
步骤2:通过Field类解析出字段信息,
Field f = c.getDeclaredField("name");
步骤3:调用Field方法获取字段信息或对其赋值
f.setAccessible(true);//意思是,别管这个字段是不是public,一律允许访问
System.out.println(f.get(s));
f.set(s,"xiaohei");
System.out.println(f.get(s));
3、小结:
#Java的反射API提供的Field类封装了字段的所有信息:
#通过Class实例的方法可以获取Field实例:getField(),getFields(),getDeclaredField(),getDeclaredFields();
#通过Field实例可以获取字段信息:getName(),getType(),getModifiers();
#通过Field实例可以读取或设置某个对象的字段,如果存在访问限制,要首先调用setAccessible(true)来访问非public字段。
#通过反射读写字段是一种非常规方法,它会破坏对象的封装。
三、访问和调用方法
1、这里以String类的substring方法为例,先通过String.class方法获取到类信息后,然后调用其getMethod方法。getMethod方法的第一个参数是要调用的方法名的字符串格式
String s = "Hello world";
Method m = String.class.getMethod("substring", int.class);
2、获取到Method实例后,调用Method的invoke方法即可实现substring方法的调用
String r = (String) m.invoke(s, 7);
System.out.println(r);
3、如果该方法是非公开方法,则需要加m.setAccessible(true);才可以访问该方法
4、小结:
#Java的反射API提供的Method对象封装了方法的所有信息:
#通过Class实例的方法可以获取Method实例:getMethod(),getMethods(),getDeclaredMethod(),getDeclaredMethods();
#通过Method实例可以获取方法信息:getName(),getReturnType(),getParameterTypes(),getModifiers();
#通过Method实例可以调用某个对象的方法:Object invoke(Object instance, Object… parameters);
#通过设置setAccessible(true)来访问非public方法;
通过反射调用方法时,仍然遵循多态原则。
四、调用构造方法
1、这里以Integer包装类为例,获取构造方法Integer(int);
Constructor<Integer> con1 = Integer.class.getConstructor(int.class);
调用构造方法:
Integer n1 = con1.newInstance(123);
System.out.println(n1);
2、获取构造方法Integer(String)
Constructor<Integer> con2 = Integer.class.getConstructor(String.class);
调用构造方法:
Integer n2 = con2.newInstance("456");
System.out.println(n2);
3、小结:
#Constructor对象封装了构造方法的所有信息;
#通过Class实例的方法可以获取Constructor实例:getConstructor(),getConstructors(),getDeclaredConstructor(),getDeclaredConstructors();
#通过Constructor实例可以创建一个实例对象:newInstance(Object… parameters); 通过设置setAccessible(true)来访问非public构造方法。