java基础——反射

程序运行时,允许改变程序结构或变量类型的语言称为动态语言。

java不是动态语言,但他有一个动态相关机制:Reflection反射。反射让java语言活了起来。

在运行状态中:

1)对于任意一个类,可以指定他的所有属性和方法;
2)对于任意一个对象,可以调用他的方法和属性。

总结来说,动态获取信息以及动态调用对象方法的功能成为java反射机制。

查看类信息

每个类被加载后,系统会为该类生成一个对应的Class对象。获取Class对象的三种方式分别是:

public static void main(String[] args) {
        //方法一:
        try {
            Class.forName("Test1");  //必须是该类的完整路径
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //方法二:
        Class clazz=Test1.class;

        //方法三:调用对象的方法
        Test1 test1=new Test1();
        test1.getClass();
    }

比较:

前两种方式都是直接根据类来取得该类的Class对象,第二种方式更推荐使用。原因有两个:代码更安全,程序性能更好。

下面的例子我们只用第二种方式,第一种很类似,就不再展示了。这里只是测试获取部分类的信息。

//构造的测试类
public class ClassTest  {
    public ClassTest() {
    }
    public ClassTest(String name) {
        System.out.println("有参数");
    }
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "ClassTest [id=" + id + ", name=" + name + "]";
    }

    public void info() {
        System.out.println("执行无参数的info");
    }

    public void info(String str) {
        System.out.println("执行有参数的info" + str);
    }
   //两个内部类
    class Inner {

    }
    static class Student {

    }

    //main方法进行测试
    public static void main(String[] args) {
        // 获取该类的Class
        Class<ClassTest> clazz = ClassTest.class;
        //返回ClassLoader
        System.out.println(clazz.getClassLoader());
        // 全部构造器
        System.out.println("ClassTest的构造器" + "-----------------");
        Constructor[] ctors = clazz.getDeclaredConstructors();

        for (Constructor c : ctors) {
            System.out.println(c);
        }
        System.out.println();

        System.out.println("全部public方法"+"------------");
        Method[] meths = clazz.getMethods();

        for (Method c : meths) {
            System.out.println(c);
        }

        //加载内部类
        Class<?>[] inners=clazz.getDeclaredClasses();
        System.out.println("全部内部类如下:"+"----------");
        for(Class c:inners){
            System.out.println(c);
        }

    }
}



执行结果如下:

这里写图片描述

操作对象

Class对象可以操作类中的方法、构造器、变量等。
继续测试上面的例子

      // 操作对象
        System.out.println("操作对象-------");
        try {
            Class<?> class1 = Class.forName("ClassTest");
            ClassTest test = (ClassTest) class1.newInstance();
            System.out.println("调用方法-------");
            test.info();
            test.setId(1);
            test.setName("Sherry");
            System.out.println("增加对象:"+test.toString());
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException e) {
            e.printStackTrace();
        }

这里写图片描述

那些年,我们悄悄用过的

1、机房收费

第一次真正接触反射是在做机房收费系统的时候,当时使用的是抽象工厂+反射或者反射+配置文件。回到当年看大话的年代……

需求:能不能不换DB?

这里写图片描述

有没有感觉上面的写法其实跟java中的Class.forName差不多的,毕竟原理是一样的嘛。将程序集、命名空间、类名传入Reflection中,这样做使得配置更加灵活,不需要在写一堆if else,搭配配置文件就更好了。

2、抽取dao

在ssh架构中,将增删改查等方法抽取出来做成一个泛型类,运行时动态的传入具体的类。

抽取的方式:
1)通过类型

   // 通过反射获取具体对象
   private Class<T> classz;

    //由构造函数中确定class
    public DaoSupportImpl() {

    // 获取当前new对象的泛型的父类的类型
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.classz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型
        System.out.println(classz);
    }

确定了类之后,CRUD什么的就简单多了,来个例子就好。


//查询所有
@Override
    public List<T> findAll() {

        System.out.println(classz.getSimpleName());
        return getSession().createQuery( //
                "FROM " + classz.getSimpleName())//
                .list();

    }

2)通过类名

//通过构造器注入类名
public DaoSupportImpl(String className) {
        this.className = className;
    }

// 根据id 查询
    public T findById(Serializable id) {
        Class c = null;
        try {
            c = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) this.getHibernateTemplate().get(c, id);
    }
原文地址:https://www.cnblogs.com/saixing/p/6730209.html