Java中的反射机制(一)

Class类

在程序运行的时候,Java运行时系统会为所有的对象维护一个被称为运行时的类型标识,这个信息跟踪着每一个对象所属的类,JVM利用运行时类型的信息选择相应的方法执行,保存这些信息的类被称为Class类(java.lang.Class);

利用反射生成类的实例

    //定义一个User类
    public class User{
        //User类的两个属性
        private Integer id;
        private String name;
        //...省略的get()\set()方法
    }

    //测试类
    public class App {
        public static void main(String[] args) throws Exception{  
            //填写类的全限定名称(既是包括包名.类名),得到保存这个类(User)信息的Class
            Class clazz = Class.forName("demo.User");
            //调用Class类中的newInstance()方法为User生成对象实例
            User user = (User)clazz.newInstance();
        }
    }

特别注意
newInstance();方法调用的是无参构造器来创建对象实例,如果这个类没有无参构造器就是抛出以下异常:

java.lang.InstantiationException: demo0.User

通过反射生成类的实例的实际应用
* struts2中Action的配置文件的class属性,就是利用类的全限定名称来反射生成类的实例
* hibernate中实体的配置文件中的class属性同理
* spring中的配置文件也是通过反射来得到类的实例

利用反射分析类的能力

在java.lang.reflection包中有三个类:
* Field : 描述类的域
* Method : 描述类中定义的方法
* Constructor : 描述类的构造器

Field

  • 得到类中定义的属性域
//根据上述的User类做测试
    @Test
    public void testFiled() throws Exception {
        //得到封装User类信息的Class类
        Class clazz = Class.forName("demo0.User");

        //调用getDeclaredFields()方法得到User类中所声明的所有属性,包括private
        Field[] fields = clazz.getDeclaredFields();
        //遍历
        for (Field field : fields) {
            System.out.println(field.getName());//得到属性名称
        }
    }
    @Test
    public void testFiled2() throws Exception {
        Class clazz = Class.forName("demo0.User");

        //不能够得到private修饰符修饰的属性
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }
Field类的实际应用
  • 组装一个SQL语句:select id ,name from user
    @Test
    public void testSql() throws Exception {
        Class clazz = Class.forName("demo0.User");
        //利用StringBuilder组装字符串:sql
        StringBuilder sql = new StringBuilder();
        //得到类中所有声明的属性
        Field[] fields = clazz.getDeclaredFields();

        //执行完for循环后:sql="select id,name,"
        sql.append("select ");
        for (Field field : fields) {
            sql.append(field.getName());
            sql.append(",");
        }

        //去掉sql中的最后一个逗号,此时的sql="sql="select id,name"
        String ss = sql.substring(0, sql.length()-1);
        StringBuilder sb = new StringBuilder(ss);

        //得到User类的简单名称,此时sql="select id,name from user"
        sb.append(" from " + clazz.getSimpleName().toLowerCase());

        //打印
        System.out.println(sb.toString());
    }
Field类中的其他方法
  • class getType() : 得到这个字段声明时的类型
  • int getModifiers() : 得到这个字段的修饰符
  • …..

Method

  • 得到类中所定义的方法
    @Test
    public void testMethod() throws Exception{
        Class clazz = Class.forName("demo0.User");
        //包含本类的所有方法,包括private修饰的方法
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            //打印出方法名:setId getId setName getName
            System.out.println(method.getName());
        }
    }
    @Test
    public void testMethod2() throws Exception{
        Class clazz = Class.forName("demo0.User");

        //包括父类的方法一并获得,public修饰的方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.print(method.getName());
        }
    }
Method类中的其他方法
  • class[] getParameterTypes() : 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。

Constructors

  • 得到类的构造方法中的参数
    @Test
    public void testConstructor() throws Exception {
        Class clazz = Class.forName("demo0.User");
        Constructor[] cons = clazz.getDeclaredConstructors();
        for (Constructor constructor : cons) {
        //得到构造方法中的参数类型数组
            Class[] c = constructor.getParameterTypes();
            for (Class class1 : c) {
                System.out.println(class1.getName());
            }
        }
    }

综合实例

//TODO

你可能感兴趣的:(反射,基础,java,Java反射,Java基础)