此博客主要是在观看张孝祥老师的教学视频的过程中,自己所做的学习笔记,在此以博客的形式分享出来,方便大家学习,建议大家观看视频,以此笔记作为回顾资料。参考资料张孝祥2010年贺岁视频:Java高新技术 视频下载疯狂Java讲义 /************************************17,18 节视频**************************************/ Class 用来描述Java中的各个类
将类的.class文件从硬盘上加载到内存中,并为之生成相应的java.lang.Class对象
得到java.lang.Class的方法有三种:
类名.class 例如:System.class 对象.getClass() 例如:new Date().getClass() Class.forName("类名") 例如:Class.forName("java.util.Date")
java中的八种基本类型也有对应的Class,void也有Class对象,即可以同过void.class获得void的字节码
字节码.isPrimitive() 通过这个方法判断字节码对应的类是不是基本类型
反射就是把java类中的各种成份映射成相应的类
编译时错误,运行时错误 ;classpath
对字节码的比较用==比较专业(只有一份) field.getType() == String.class /******************************传智播客web day01视频中讲解的***************************/ 通过getXxxxx()只能取得该类public的类型通过getDeclaredXxxxxx()可以取得该类非public的类型设置非public类型的可访问性,默认为false,不可访问c.setAccessible(true); /************************************19节视频********************************************/
构造方法的反射 得到多个构造方法 Constructor[] constructor1 = String.class.getConstructors();
得到一个构造方法 Constructor constructor1 = String.class.getConstructor(StringBuffer.class); String str2 = (String)constructor1.newInstance(new StringBuffer("abc")); System.out.println(str2.charAt(2)); 注意:很少通过反射来创建对象,因为通过反射来创建对象时性能要稍微低一些,实际上,只有当程序需要动态的创建某个类的对象的时候才会考虑使用反射,通常在开发通用性比较广的框架,基础平台的时候可能会大量使用反射。
/************************************20,21 节视频**************************************/ 成员变量的反射 public class ReflectPoint { private int x; public int y; public String str1 = "hhhhhhhh"; public String str1 = "abdcdecc";
public String str1 = "baseras";
public ReflectPoint(int x, int y) { super(); this.x = x; this.y = y; } }
ReflectPoint pt1 = new ReflectPoint(3,5); Field fieldY = pt1.getClass().getField("y"); //fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上,要用它去取某个对象上对应的值 System.out.println(fieldY.get(pt1)); Field fieldX = pt1.getClass().getDeclaredField("x");//使私用成员变得可见 fieldX.setAccessible(true);//暴力映射,使私有成员变的可以访问 System.out.println(fieldX.get(pt1));
ReflectPoint pt1 = new ReflectPoint(3,5); //得到所有的字段
Field[] fields = pt1.getClass().getFields(); //遍历所有字段,并将String类型的字段的里面的b替换成a for(Filed field:fields){
if(field.getType()==String.class){ String oldValue = (String)field.get(pt1); String newValue = oldValue.replace('b','a'); field.set(pt1,newValue);
} }
/************************************22,23 节视频**************************************/ 6 成员方法的反射
Method methodCharAt = String.class.getMethod("charAt",int.class); System.out.println(methodCharAt.invoke("abcdefg",1));//打印结果为b
如果invoke(null,1)第一个参数传入的是null,则表明这个方法是一个静态方法
7 在一个类中调用另一个类的main方法 String startingClassName = args[0]; Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}}); //因为是静态方法,所以第一个参数是null mainMethod.invoke(null, (Object)new String[]{"111","222","333"}); //因为是静态方法,所以第一个参数是null
之所以写成 new Object[]{new String[]{"111","222","333"}} 是为了兼容其他版本的jdk
/************************************24,25 节视频**************************************/ 维数相同,存储的元素的类型的相同的数组,在内存中对应的类的字节码是相同的; int [] a1 = new int[]{1,2,3}; int [] a2 = new int[4]; int[][] a3 = new int[2][3]; String [] a4 = new String[]{"a","b","c"}; System.out.println(a1.getClass() == a2.getClass()); //true System.out.println(a1.getClass() == a4.getClass()); //false System.out.println(a1.getClass() == a3.getClass()); //false
数组元素对应的父类都是Object System.out.println(a1.getClass().getSuperclass().getName()); //object System.out.println(a4.getClass().getSuperclass().getName());//object
Object aObj1 = a1; Object aObj2 = a4; //Object[] aObj3 = a1; //基本类型的数组不能赋给Object类型的数组 Object[] aObj4 = a3; Object[] aObj5 = a4;
不能直接打印数组里的值 System.out.println(a1); System.out.println(a4); 采用此方法打印数组里的值,注意基本类型的数组采用此方法也无法打印出数组值 System.out.println(Arrays.asList(a1)); // 仍然无法打印 System.out.println(Arrays.asList(a4));//打印成功
数组反射的应用

《1》 private static void printObject(Object obj) { Class clazz = obj.getClass(); if(clazz.isArray()){ int len = Array.getLength(obj); for(int i=0;i<len;i++){ System.out.println(Array.get(obj, i)); } }else{ System.out.println(obj); } } 《2》 // 创建一个元素类型为String ,长度为10的数组 Object arr = Array.newInstance(String.class, 10); // 依次为arr数组中index为5、6的元素赋值 Array.set(arr, 5, "疯狂Java讲义"); Array.set(arr, 6, "轻量级Java EE企业应用实战"); // 依次取出arr数组中index为5、6的元素的值 Object book1 = Array.get(arr , 5); Object book2 = Array.get(arr , 6); // 输出arr数组中index为5、6的元素 System.out.println(book1); System.out.println(book2); 完整代码链接 http://pan.baidu.com/s/1sjSgAJj /************************************26 节视频**************************************/
HashCode的值得作用 /************************************27 节视频**************************************/ 反射用的最多的地方是框架
框架-----调用你的代码 工具类----你的代码调用的类
采用框架可以加快开发速度提高效率
反射在框架中的使用: 利用反射通过读取配置文件进行类声明 config.properties文件的内容 className=java.util.HashSet
<一> //InputStream ips = new FileInputStream("config.properties");//获取绝对路径+配置文件名字
<二> //InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
<三> InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties"); // InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties"); // InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");
<二>,<三> 方法不能完全代替<一>方法,因为<二>,<三>方法是只读的,只能读取配置文件的内容
Properties props = new Properties(); props.load(ips); ips.close(); //props.StringPropertyNames();该方法返回所有的name到一个集合中,可以进行遍历 // String[] strArray = props.StringPropertyNames(); 返回所有的name以数组的形式 String className = props.getProperty("className"); Collection collections = (Collection)Class.forName(className).newInstance();
26节视频
路径问题