java反射
来源:互联网 发布:淘宝团队建设 编辑:程序博客网 时间:2024/05/16 18:18
Java反射
1.通过反射查看类的信息
1.1 获取Class对象
每个类被加载之后,系统就会为该类生成一个对应的Class对象,通过Class对象就可以访问到JVM中的这个类,在java程序中获得Class对象通常有如下三种方式。
- 使用Class类的forName(String clazzName)静态方法, clazzName为某个类的全限定类名.
- 调用某个类的class属性获取该类对应的class对象,例如User.class
- 调用某个对象的getClass()方法
但如果程序只能获得一个字符串,则只能使用第一种方式,使用Class的forName(String clazzName)方法获取class对象时,该方法可能抛出一个ClassNotFoundException异常。
1.2 从Class中获取信息
获取Class中的信息提供了很多API方法,查阅API文档。列出几个常用的方法。
获取构造方法
Constructor<T>getConstructor(Class<?>..parameterTypes) Constructor<T> getConstructors();返回此Class对象的所有public构造器
获取Class对应类包含的方法
Method getMethod(String name,Class<?>...parameterTypes)返回指定的方法.Method getMethods();返回此Class对象表示类的所有 public方法
- 获取Class对应类的成员变量
Field getField(String name);返回指定名称的public成员变量Field getFields();返回此类所有public类型的成员变量
- 访问Class对应类上包含的Annotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass);获取指定类型的Annotation,如果该类型的注解不存在,则返回null. Annotation[] getAnnotations();返回修饰该Class对象对应类上存在的所有Annotation.
- 获取接口,包名,全路径名
Package getPackage()String getInterfaces();Package getPackage();String getSimpleName();boolean isAnnotation();
2.使用反射生成并操作对象
2.1 创建对象
通过反射来生成对象有如下两种方式。
- 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法实际上是利用默认构造器来创建该类的实例。
- 先使用Class对象获取指定的Constructor对象,然后在调用Constructor对象的newInstance()方法来创建Class对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。
2.2 调用方法
当获取得到某一个类对应的Class对象后,就可以通过该Class对象的getMethods()方法或者getMethod()方法来获取全部方法或指定方法。
Object invoke(Object obj,Object...args);obj是执行该方法的主调,后面的args是执行该方法时传入该方法的实参.
3.访问成员变量值
通过Class对象的getFields()或getField()方法可以获取该类所包括的全部成员变量或指定成员变量Field提供了设置与读取成员变量的值.
- getXxx(Object obj); 获取obj对象的改成员变量的值,此处的Xxx对应8中基本类型,如果该成员变量的类型是引用类型,则取消get后面的Xxx.
- setXxx(Object obj,Xxx val);将object对象的该成员变量设置成val值。
4. 使用反射生成JDK动态代理
Proxy提供了用于创建动态代理和代理对象的静态方法,它也是所有动态代理类的父类。
static Object newProxyInstance(ClassLoader loader,Class<?>...interfaces);创建一个动态代理类所对应的Class对象,classLoader参数指定生成动态代理类的类加载器,interfaces是该代理类将实现interfaces所指定的多个接口。static Class<?> getProxyClass(ClassLoader loader,Class<?>...interfaces)创建一个动态代理类所对应的Class对象。创建动态代理类:定义个类实现InvocationHandler,需要重写invoke()方法------调用代理对象的所有方法时都会被替换成调用该invoke()方法,该invoke()方法中三个参数proxy: 代表动态代理对象method:代表正在执行的方法args: 代表调用目标方法时传入的实参/***用户操作接口*/public interface UserDao { void addUser(); void deleteUser();}/***用户操作实现类*/public class UserDaoImpl implements UserDao{ /** * 添加用户 */ @Override public void addUser(){ System.out.println("添加用户操作"); } /** * 删除用户 */ @Override public void deleteUser(){ System.out.println("删除用户操作"); }}/*** 动态代理操作类*/public class UserDaoProxy implements InvocationHandler{ private UserDao userDao; public UserDaoProxy(UserDao userDao){ super(); this.userDao = userDao; } public UserDao createProxy(){ //第一种方式创建代理对象 UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),this); return proxy; /*//第二种方式创建代理对象 Class proxyClass = Proxy.getProxyClass(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces()); Constructor ctor = proxyClass.getConstructor(new Class[]{InvocationHandler.class}); UserDao proxy = (UserDao) ctor.newInstance(this); */ } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String name = method.getName(); if(name.equals("addUser")){ //记录该方法的日志 System.out.println("添加用户日志记录"); Object invoke = method.invoke(userDao, args); return invoke; }else if(name.equals("deleteUser")){ //记录该方法的日志 System.out.println("删除用户日志记录"); Object invoke = method.invoke(userDao, args); return invoke; }else{ return method.invoke(userDao,args); } }}//测试public class Test { public static void main(String[] args){ UserDao userDao = new UserDaoImpl(); UserDaoProxy userDaoProxy = new UserDaoProxy(userDao); UserDao proxy = userDaoProxy.createProxy(); proxy.addUser(); proxy.deleteUser(); }}
5. 反射和泛型
使用Class泛型可以避免强制类型转换,例如,下面提供一个简单的对象工厂,该对象工厂可以根据指定类来提供该类的实例。
public class ObjectFactory { public static Object getInstance(String clsName){ try{ Class cls = Class.forName(clsName); return cls; }catch (Exception e){ e.printStackTrace(); return null; } }// Date d = (Date)ObjectFactory.getInstance("java.util.Date");// 获取实例后需要强制类型转换// Date d = (Date)ObjectFactory.getInstance("java.util.Date");// 出现ClassCastException public static<T> T getInstance(Class<T> cls){ try { return cls.newInstance(); }catch (Exception e){ e.printStackTrace(); return null; } } /** * Date d = ObjectFactory.getInstance(Date.class); * getInstance()方法来产生对象时,无需使用强制类转换,系统会执行严格的检查 */}
阅读全文
0 0
- 【反射】JAVA反射机制
- JAVA 反射
- java 反射
- Java反射
- java反射
- java反射
- JAVA反射
- java 反射
- Java 反射
- java 反射
- Java反射
- java反射
- JAVA 反射
- java 反射
- Java反射
- java反射
- java 反射
- java 反射
- Android插件基础之类加载器学习
- 微信伪装他人
- cnn、rnn相结合进行文本分类
- JUnit学习笔记-IDEA编译器中JUnit的安装和使用
- 如何减肥之运动规则
- java反射
- 基于python+requests+unittest框架接口自动化测试设计开发
- Java笔记第十课(String&Object&Scanner)
- 11
- 《未来简史(下)》万维钢解读
- HDU 5988 Coding Contest(费用流)
- 2017.10.30工作日记
- 商品增删改查之分页显示
- 稳定排序与不稳定排序