关于反射
什么是反射?
反射是Java程序开发语言的特征之一,它允许运行中的java程序对自身进行检查,并能直接操作程序的内部属性和方法
通过以下类实现反射:
Field
Constructor
Method
Class
Object
一.获取Class对象
获取Class对象就是让Class对象获得一个类内部属性和方法,有三种方式
方式一
通过Object类的getClass()获取反射对象
Book book = new Book();
Class bookClass = book.getClass();
System.out.println("完全限定名:" + bookClass.toString());
System.out.println("类的包名:" + bookClass.getPackage()); // 包名
System.out.println("类的包名+类名:" + bookClass.getName());
System.out.println("类名: " + bookClass.getSimpleName());
方式二
通过类名访问class关键字属性,获取该类型的Class对象
Class bookClass = Book.class;
方式三
通过Class类的forName()静态方法获取,需传入类的完全限定名(包名.类名)
Class bookClass = Class.forName("reflect.Book");//包名.类名
二.通过Class对象调用对应类的构造方法
1.调用无参构造方法
通过Class对象 . newInstance()
OObject obj=bookClass.newInstance();//通过反射创建对象
2.获得有参构造方法并调用
通过Class对象 . getDeclaredConstructor(构造方法参数 . class)获得构造方法的构造器对象
通过构造器对象 . newInstance(传入构造方法参数)调用构造方法
对于private私有构造方法的调用必须使用构造器对象 . setAccessible(true)把权限设置为true使权限检查机制关闭
Constructor constuctor =bookClass.getDeclaredConstructor(String.class, String.class);//传入参数类型.class
constuctor.setAccessible(true);//权限检查机制关闭
Object obj = constuctor.newInstance("张碧晨", "华晨宇");//调用有参构造
3.获得所有参构造方法并打印
通过这种方式把所有构造方法对象放入构造器数组中
Constructor[] constructros = bookClass.getDeclaredConstructors();
for(Constructor c : constructros) {
System.out.println(c);
}
三.获取当前Class类型中成员变量并赋值
1.获得所有成员变量
通过这种方式把所有成员变量放入数组中并打印
Field[] fields = bookClass.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
System.out.println("访问修饰符:" + f.getModifiers());
System.out.println("类型:" + f.getType());
System.out.println("名称:" + f.getName());
System.out.println();
}
2.按照成员变量的名称获取成员变量Field对象并赋值
对于private私有成员变量通过Field对象 . setAccessible(true)把权限设置为true使权限检查机制关闭
Field descField = bookClass.getDeclaredField("desc");//传入成员变量名字
descField.set(bookClass, "这个是desc成员变量");//传入类对象和赋值的内容
Field bookNameField = bookClass.getDeclaredField("bookName");//传入成员变量名字
bookNameField .setAccessible(true);//私有成员变量
bookNameField.set(bookClass, "这是bookName成员变量");//传入类对象和赋值的内容
四.获取当前Class类型中成员方法并调用
1.获得所有成员方法
通过这种方式把所有成员方法放入方法数组中
bookClass.getDeclaredMethods()方法
Method[] methods = bookClass.getDeclaredMethods();
for (Method m : methods) {
System.out.println(m);
System.out.println("访问范围:" + (m.getModifiers() == Modifier.PUBLIC ? "公有" : "其它"));
System.out.println("返回类型:" + m.getReturnType());
System.out.println("方法名称:" + m.getName());
}
2.获得指定成员方法(指定参数类型)并调用
对于private私有成员方法通过Method 对象 . setAccessible(true)把权限设置为true使权限检查机制关闭
Method methodDosth2 = bookClass.getDeclaredMethod("dosth2", String.class, double.class);//传入方法名和方法参数.class
methodDosth2.setAccessible(true);
methodDosth2.invoke(bookClass, "平凡的世界", 75.6);//调用方法,传入类类对象和方法参数
五.获取一个类继承的父类和实现的接口(单继承多实现)
Class arrayListClass = ArrayList.class;//获取ArrayList类的Class对象
Class superClass = arrayListClass.getSuperclass();// 获取直接父类,单继承
System.out.println("ArrayList的父类: " + superClass);
System.out.println("ArrayList实现的接口:");//获取接口,多实现
Class[] interfaces = arrayListClass.getInterfaces();
for(Class interfacex : interfaces) {
System.out.println(interfacex);
}
六.反射的优缺点
优点:
运行期类型的判断,动态加载类,代码灵活度高;
缺点:
性能低,安全性被破坏