反射机制--总结

1.反射的概念:

   Reflection(反射) 被视为 动态语言的关键,反射机制允许程序在执行的时候借助Reflection的API 获取任何类的内部信息,直接操作任何对象的内部属性和方法。

2.Object类中定义Class 类:反射从程序允许结果看:利用Java编译生成.class文件反编译原来的Java---通过对象反射求出类的名称

 

 1). 反射的理解:反射通过动态的设置内部的属性和方法,在反射的过程中,我们事先不知道 类的名称是什么,采用getClass() 方法获取一个实体的类型---在JavaBean过程中反射的类必须有一个无参的构造器:同时在反射的时候属性和方法的名称保持一致

对getClass(): Object 类一个方法名叫getClass,利用该方法获取一个实例的 类型类 类型类指的是代表一个类型的类,String类型的类String.class

java 中所有的类型类是Class的实体

   getClass():一个类的实例具备的方法.getClass() 是动态的;解释:返回这个对象正在运行是的类,直到这个对象属于什么类

   Class()方法是一个类的方法是静态的方法

总结:

   1. 对Class 实例的理解

     正常情况:创建一个类,通过编译(javac.exe),生成对应的class文件,之后使用Java.exe(JVm 类加载器)运行.class 文件

     反射情况:此class文件加载到内存以后就是一个运行时类 , 存在缓存区域,那么此运行时类就是一个Class 的实例;对某个对象.getClass() 为了得到这个运行时类  注意每一个运行类只加载一次  Person.Java--编译--Person.class(Class 的实例)

 2.获取Class 实例 clazz作用:

      1).创建对应的运行时类的对象 clazz.newInstance();

       2).对应运行时类的完整结构

       3).调用指定的属性,方法和构造器

       4).反射的应用 动态的代理


  1.Java中有四种方法获取反射的机制:

    1.调用运行时类的本身的.class的属性:静态

     Class clazz=Person.class;

   2.通过运行时对象获取:动态

     Person per=new Person();

     Class clazz=per.getClass();

 3. 通过Class 的静态的方法

  Class.forName("com.atug.Person");

4.通过类的加载器

Class clazz=this.getClass().getClassLoader().loadClass("com.atug.Person");

 1    Person person=new Person();
 2         // 1.第一种方式通过Object的getClass() 方法(需要实例化一个对象)
 3         Class clazz1=person.getClass();
 4         
 5         // 2.通过对象实例方法获取(需要实例化一个对象)
 6         Class clazz2=Person.class;
 7         
 8         // 类的全路径
 9         try {
10             Class clazz3=Class.forName("com.atug.reflection_1.Person");
11         } catch (ClassNotFoundException e) {
12             // TODO Auto-generated catch block
13             e.printStackTrace();
14         }
15         

2.Class 实例第一种作用:

   2.1创建类的对象:调用Class对象的new Instance()的方法:

     1)类必须误差构造器  2).类的构造器的访问权限必须足够

反射类没有空的构造器,报错 ;类的构造器是非private权限

通过反射获取对象的内部成员的属性,不理睬private

 1 // 1.第一种方式通过Object的getClass() 方法(需要实例化一个对象)
 2           Class clazz=Person.class;
 3         
 4           5          //.getFields 只能获取其中 public属性
 6           Field[] fields=clazz.getDeclaredFields();
 7         
 8           for(Field fi:fields)
 9           {
10               System.out.println(fi.getName());
11           }
12           
13           //同样获取运行的方法
14           Method[] m1=clazz.getDeclaredMethods();
15           for(Method m:m1)
16           {
17               System.out.println(m.getName());
18           }
19           

事实上:利用反射的主要目的不在获取内部属性或者是内部方法名称 在于利用反射动态的建立一个对象,在其中设置成员属性和调用其中成员方法

 2.2. 因此首先 反射动态的建立一个类的对象 Person p=clazz.newInstance(); 调用类型方法时候注意private 同时Method.invoke() 启动反射建立的实例的方法

 1  // 利用反射的主要目的不在获取内部属性或者是内部方法名称 在于利用反射动态的建立一个对象,在其中设置成员属性和调用其中成员方法
 2           // 1.利用反射调用指定的属性  私有成员Declared
 3           Person p=(Person) clazz.newInstance();
 4           Field f1=clazz.getDeclaredField("name");
 5           f1.setAccessible(true);
 6           f1.set(p,"HuHui");
 7           System.out.println(p);
 8           
 9           // 2.利用反射生成某个实例调用其中的方法 paramterTypes=show 类型 void null
10           Method M1=clazz.getDeclaredMethod("show");
11           M1.setAccessible(true);
12           M1.invoke(p);

 4.对加载器的理解:

  程序主动使用某个类的时候,该类没有被加载到内存,使用getClassLoader().loadClass();

类加载器将类加载到内存:启动型加载器和自定义加载器

   Java核心库String是引导类加载器

使用类加载器从 某个目录下得得到 properties

 1 ClassLoader loader1=this.getClass().getClassLoader();
 2         System.out.println(loader1);
 3         // 类加载器加载某个目录下的Java
 4         InputStream is=loader1.getResourceAsStream("com\atug\properties");
 5         // 当前工作空间小
 6         FileInputStream in=new FileInputStream(new File("jdbc.properties"));
 7         Properties pro=new Properties();
 8         pro.load(is);
 9         
10         String name=pro.getProperty("XXX");
11     }

 3.反射第二个事情: 反射获取类的完整的结构:实现全部接口,所继承的父类 全部的Field

    常用反射获取泛型的类型

  3.1 获取属性,获取权限修饰符 变量类型 变量名

  


 1         Class clazz=Person.class;
 2         
 3         //Person 类比较的复杂继承 和泛型接口
 4         Field [] fields=clazz.getFields();
 5         
 6         // 查看一下getFields 只能获取运行本类和父类中声明public属性 null
 7         for(Field field:fields)
 8         {
 9             System.out.println(field.getName());
10         }
11         
12         // 2. 获取所有声明的属性,如果修改属性值必须field.setAccessible(arg0);
13         Field [] fields1=clazz.getDeclaredFields();
14         for(Field field:fields1)
15         {
16             
17             System.out.println(field);
18             
19             System.out.println(field.getName());
20             // 1.获取修饰符
21             System.out.println(Modifier.toString(field.getModifiers()));
22             
23             // 2.获取属性的类型:
24             Class Type=field.getType();
25             System.out.println(Type.getName());


 

3.2 获取运行时候的父类---发现得到父类的名称 父类有泛型并没有显示出来

1 Class clazz=Person.class;
2         
3         Class superClass=clazz.getSuperclass();
4         System.out.println(superClass.getName());

3.3 获取带泛型的父类 父类的类型: getGenericsuperClass();获取父类泛型--返回Type类型

 1 Class clazz=Person.class;
 2         Type type=clazz.getGenericSuperclass();
 3         
 4         System.out.println(type);
 5         
 6         //--------重点:获取父类的泛型 String-----
 7         // ParameterizedType 是Type的子类 --带有参数化的Type
 8         
 9         if(type instanceof ParameterizedType)
10         {
11              ParameterizedType param=( ParameterizedType)type;
12              
13              // 获取带参数Type 中实际参数类型 返回数组有多个参数 
14              Type[] types=param.getActualTypeArguments();
15              if(types[0] instanceof Class)
16                     System.out.println(types[0].getTypeName());
17         }

DAO 直到操作的那个类,获取父类的泛型 反射建立对象将SQL中数据存到JavaBean中。

原文地址:https://www.cnblogs.com/woainifanfan/p/6715691.html