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中。