1、Java反射
反射是一种动态机制,它允许我们在程序运行起来后再确定实例化对象,调用方法和操作属性,可以提供代码的灵活度,但是反射会带来较慢的运行速度和更多的系统开销,所以不能过度的依赖反射
2、获取类对象的方式
1、类名.class
2、Class.forName(String classname)参数为类的完全限定名
3、使用类加载器classloader,调用loadclass(String name)
ClassLoader loader=ClassLoader.getSystemClassLoader(); loader.loadClass("java.lang.String")
这3中返回与字符串相应的Class对象(Class类重写了object的tostring方法,输出对象就是输出调用tostring方法,方法中有Class其他方法属性操作后返回的值)因为有重写方法,所以Class对象代表着类对象,其实返回的依旧是class对象,就算没有重写tostring方法,获取类对象的值依旧保存在属性中,输出对象也同样是object类的tostring方法,也可以当作普通类看待。
3、Class类中的方法
String getName() 获取class对象表示的类的完全限定名 String getSimpleName() 获取类名 Field[] getFields()获取所有非私有属性,包括父类的 Field[] getDeclaredFields()获取本类中所有属性,包括私有的 Method[] getMethods()获取本类和父类中的非私有方法 Method[] getDeclaredMethods()获取本类中的所有方法,包括私有的 Constructor<?>[] getConstructors()获取所有的非私有的构造方法 Constructor<?>[] getDeclaredConstructors()获取本类中的所有的构造方法包括私有的
4、使用反射进行实例化
通过反射中的类对象或者构造器对象调用newInstance方法创建实例
1、类对象创建:
Class cls=Class.forName("api11_reflect.Person"); Object o=cls.newInstance();
仅在要实例化的类有无参数的构造方法时有效
如果没有无参构造 会抛出实例化异常:InstantiationException
2、因为class类的方法只能有无参构造才能创建实例,那么有参数的构造方法就不行,
可以通过构造器对象来创建实例
Constructor c=cls.getConstructor(String.class,int.class);
Object o1=c.newInstance("lisi",5);
System.out.println(o1);
使用反射中类对象或者构造器对象的newInstance方法实例化对象,执行构造方法
5、使用反射调用方法
//调用无参数的方法,先获取方法,后用invoke执行方法
//方法的值m为调用方法h的返回值,如没有返回值则为null
Method mi=cls.getMethod("h");
Object m=mi.invoke(o);
调用有参数的方法
//调用有参方法 Method m2=cls.getMethod("setAge", int.class); Object o2=m2.invoke(o,5);
o为这个类的类对象,即class对象
/* Method getMethod(String name, Class<?>... parameterTypes) 获取指定方法,第一个参数是方法名,第二个可变参数为方法的参数类型 */
/* Object invoke(Object obj, Object... args) 调用指定方法,第一个参数为方法所属对象,第二个参数为方法实参,接受类型为object,所有类型的父类 该方法的返回值就是调用方法的返回值,如果方法没有返回值则返回null */
//调用私有方法
mi=cls.getDeclaredMethod("a");
System.out.println(mi);
/*
void setAccessible(boolean flag)
直接使用invoke调用私有方法会抛出非法访问异常IllegalAccessException
需要现设置访问权限
*/
mi.setAccessible(true);
mi.invoke(o);