黑马程序员-笔记-反射与内省,黑马内省
分享于 点击 48528 次 点评:170
黑马程序员-笔记-反射与内省,黑马内省
-----------
java反射就是讲java的各个组成成员反射成为单独的一个个java类。
[java] view plaincopy
- public class ReflectTest {
- /**
- * class类:java程序中各个java类其实是同一类事物,描述这些事物的类就叫Class
- *
- * 反射:将类中的每一个成分解析成为一个相应的类。
- *
- * @throws ClassNotFoundException
- * @throws NoSuchMethodException
- * @throws SecurityException
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws IllegalArgumentException
- * @throws NoSuchFieldException
- *
- *
- *
- *
- *
- */
- public static void main(String[] args) throws ClassNotFoundException,
- SecurityException, NoSuchMethodException, IllegalArgumentException,
- InstantiationException, IllegalAccessException,
- InvocationTargetException, NoSuchFieldException {
- // classTest();
- // constructorTest();
- // fieldTest();
- // methodTest();
- // startBase("itcast.day1.Base");
- //arrayTest();
- arrayReflect(new int[]{1,2,3});
- }
- //利用数组的反射,这个也就是前面讲的Main方法获取数组元素的方案。
- //数组的反射是不能获得数组类型的,只能获得各个元素的类型。
- public static void arrayReflect(Object obj){
- Class clazz = obj.getClass();
- if(clazz.isArray()){
- int length = Array.getLength(obj);
- for(int i=0;i<length;i++){
- System.out.println(Array.get(obj, i));
- }
- }else{
- System.out.println(obj);
- }
- }
- // 数组与Object的关系
- public static void arrayTest() {
- int[] i1 = new int[]{1,2,4};
- int[] i2 = new int[4];
- int[][] i3 = new int[3][2];
- String[] i4 = new String[]{"a","b","c","d"};
- System.out.println(i1.getClass() == i2.getClass());
- //System.out.println(i1.getClass() == i3.getClass());?
- //System.out.println(i1.getClass() == i4.getClass());
- System.out.println(i1.getClass().getName());
- System.out.println(i1.getClass().getSuperclass().getName());
- System.out.println(i3.getClass().getName());
- System.out.println(i3.getClass().getSuperclass().getName());
- Object o1 = i1;
- Object o2 = i3;
- Object[] o3 = i3;
- Object[] o4 = i4;
- //Object[] o5 = i1;//基本类型的数组不能转换成为Object的数组。只能当做一个Object
- System.out.println(Arrays.asList(i1));
- System.out.println(Arrays.asList(i3));
- System.out.println(Arrays.asList(i4));
- }
- // 使用反射启动某一个java
- public static void startBase(String javaFile) throws SecurityException,
- NoSuchMethodException, ClassNotFoundException,
- IllegalArgumentException, IllegalAccessException,
- InvocationTargetException {
- Method main = Class.forName(javaFile).getMethod("main", String[].class);
- // 不能使用new String[]{"123","abc"}来当做一个String[]进行单一的数据,
- // 因为为了兼容JDK1.4,jvm会自动对这个String数组拆开,拆成两个String(Object),"123","abc"
- // main.invoke(null, new String[]{"123","abc"});
- main.invoke(null, new Object[] { new String[] { "123", "abc" } });// 预装
- main.invoke(null, (Object) new String[] { "123", "abc" });// 强制告诉java,不需要拆箱。
- }
- // 成员方法的反射。
- public static void methodTest() throws SecurityException,
- NoSuchMethodException, IllegalArgumentException,
- IllegalAccessException, InvocationTargetException {
- Method method1 = String.class.getMethod("charAt", int.class);
- System.out.println(method1.invoke("abc", 1));
- // java自动装箱功能,new int[]{1,2,4}只是一个Object,new
- // Object[]{1,2,4}则是传入了3个Objcet
- // System.out.println(method1.invoke("xyz", new int[]{1} ));
- System.out.println(method1.invoke("xyz", new Object[] { 1 }));
- // 静态方法的反射调用。不需要传入对象。
- // method1.invoke(null, 1);
- }
- // 成员变量的反射。
- public static void fieldTest() throws SecurityException,
- NoSuchFieldException, IllegalArgumentException,
- IllegalAccessException {
- ReflectPoint pt1 = new ReflectPoint(1, 5);
- Field filedy = pt1.getClass().getField("y");
- // 取出pt1中y成员变量的值。
- System.out.println(filedy.get(pt1));
- // 通过反射获取私有成员字段。强制取出该字段。但该字段不能使用。
- Field filedx = pt1.getClass().getDeclaredField("x");
- // 暴力反射强制使用私有的字段。
- filedx.setAccessible(true);
- System.out.println(filedx.get(pt1));
- // 将一个对象中String类型的成员变量的a全部换为b。
- Field[] fileds = pt1.getClass().getFields();
- for (Field f : fileds) {
- // 字节码的比较使用==更专业
- if (f.getType() == String.class) {
- String oldStr = (String) f.get(pt1);
- String newStr = oldStr.replace("a", "b");
- f.set(pt1, newStr);
- }
- }
- System.out.println(pt1);
- }
- // 构造方法的反射。Class.newInstace();方法就是调用无参构造方法来实例一个对象,
- // 这个方法使用了缓存机制,他缓存了无参构造器,源码可以分析反射是一个比较耗时的算法。
- public static void constructorTest() throws SecurityException,
- NoSuchMethodException, IllegalArgumentException,
- InstantiationException, IllegalAccessException,
- InvocationTargetException {
- Constructor cons = String.class.getConstructor(StringBuffer.class);
- System.out.println(cons.getDeclaringClass());// 返回该构造器对应的类。
- String obj = (String) cons.newInstance(new StringBuffer("abc"));
- System.out.println(obj);
- }
- // 获得Class对象的方法。以及一些关键点。
- public static void classTest() throws ClassNotFoundException {
- Class c1 = ReflectTest.class;
- c1 = new ReflectTest().getClass();
- try {
- c1 = Class.forName("itcast.day1.ReflectTest");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- // 存在九个预定义的Class对象,他们是八个基本类型以及Void。
- c1 = void.class;
- System.out.println(c1);
- Class c2 = int.class;
- Class c3 = Integer.class;
- Class c4 = Integer.TYPE;// Integer中的一个常量,他是int的字节码。
- // int 与 Integer的字节码是不同的。
- System.out.println(c2 == c3);
- System.out.println(c3 == c4);
- System.out.println(c2 == c4);
- // 相同的字节码在内存中只会存在一份。
- Class c5 = String.class;
- Class c6 = "abc".getClass();
- Class c7 = Class.forName("java.lang.String");
- System.out.println(c5 == c6);
- System.out.println(c6 == c7);
- System.out.println(c4.isPrimitive());
- // 数组本身是一个对象。
- System.out.println(int[].class.isPrimitive());// 查看一个字节码是否是基本类型。
- System.out.println(int[].class.isArray());// 判断一个字节码是否是一个数组。
- }
- }
上面反射中使用到的点类:ReflectPoints,由于反射示例:
[java] view plaincopy
- // 用于反射的点。
- public class ReflectPoint {
- private Date date = new Date();
- private int x;
- public int y;
- public String str1 = "aaabbb";
- public String str2 = "ababab";
- public ReflectPoint(int x, int y) {
- super();
- this.x = x;
- this.y = y;
- }
- public String toString() {
- return str1 + "|||" + str2;
- }
- public Date getDate() {
- return date;
- }
- public void setDate(Date date) {
- this.date = date;
- }
- public int getX() {
- return x;
- }
- public void setX(int x) {
- this.x = x;
- }
- public int getY() {
- return y;
- }
- public void setY(int y) {
- this.y = y;
- }
- }
利用类加载器来读取配置文件:
[java] view plaincopy
- /*
- * 在实际中,是如何读取那个配置的config.properties文件的。
- * java中new FileInputStream("config.properties");
- * 这个相对目录,是相对与谁?是相对于当前的操作目录。(工程目录。)
- * 并不是相当于当前类,或者java.exe
- * 使用绝对路径的话需要路径不能写死,需要传入。
- * 使用类加载器来解决这个方案。
- */
- public static void pathTest() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException{
- //使用类加载器加载文件,就是在classPath配置的根目录位置,开始找文件。
- //不能以斜杠大头,直接从根目录查找起。
- InputStream is= ReflectTest2.class.getClassLoader().getResourceAsStream("itcast/day1/config.properties");
- /*下面写法的,是相对于ReflectTest2.class这个文件的文件位置。
- * ReflectTest2.class.getResourceAsStream("config.properties");//ReflectTest2.class同目录下的配置文件。
- * 这个写法又等同于:
- * ReflectTest2.class.getResourceAsStream("/itcast/day1/config.properties");绝对路径。
- *
- */
- Properties prop = new Properties();
- prop.load(is);
- is.close();
- String className = prop.getProperty("className");
- Test13 base = (Test13)Class.forName(className).newInstance();
- base.main(null);
- }
内省与BeanUtils的使用:
[java] view plaincopy
- public class IntroSpectorTest {
- /**
- * 内省:IntroSpector
- *
- * JavaBean:特殊的java类,符合一系列规范,set/get方法。 javaBean依然可以当做普通类处理。
- * javaBean只与set,get有关,其属性名是get/set方法后边的部分 如果第二个字母是小写,则把第一个字母变成小的。
- * 第二个字母是大的,则依然是大写。
- *
- * getAge()-->age getCPU()-->CPU
- *
- * @throws IntrospectionException
- * @throws InvocationTargetException
- * @throws IllegalAccessException
- * @throws IllegalArgumentException
- * @throws NoSuchMethodException
- *
- */
- public static void main(String[] args) throws IntrospectionException,
- IllegalArgumentException, IllegalAccessException,
- InvocationTargetException, NoSuchMethodException {
- ReflectPoint pt1 = new ReflectPoint(3, 5);
- String propertyName = "x";
- Object retVal = getProperty(pt1, propertyName);
- System.out.println(retVal);
- setProperty(pt1, propertyName, 7);
- System.out.println(pt1.getX());
- //BeanUtils要求所操作的bean必须是public类。
- //甚至可以操作并不存在的属性。
- BeanUtils.setProperty(pt1, "tt", "9");//这个位置并没有异常。
- System.out.println(pt1.getX());
- BeanUtils.setProperty(pt1, "date.time", "9999");//支持级联操作,属性链。
- System.out.println(BeanUtils.getProperty(pt1, "date.time"));
- System.out.println(pt1.getDate().getTime());
- //BeanUtils对Map的操作。
- Map<String,String> map= new HashMap<String,String> ();
- map.put("i", "555");
- BeanUtils.setProperty(map, "i", "444");
- //System.out.println(map.get("myself"));
- System.out.println(BeanUtils.getProperty(map, "i"));
- System.out.println(map.get("i"));
- PropertyUtils.setProperty(pt1, "x", 999);//PropertyUtils不会进行类型的转换。后边不能写成字符串形式。
- System.out.println(pt1.getX());
- }
- // javaBean的复杂操作。
- private static Object getProperty(Object obj, String propertyName)
- throws IntrospectionException, IllegalAccessException,
- InvocationTargetException {
- /*PropertyDescriptor pd = new PropertyDescriptor(propertyName,
- obj.getClass());
- Method methodGetX = pd.getReadMethod();
- Object retVal = methodGetX.invoke(obj);
- */
- BeanInfo info = Introspector.getBeanInfo(obj.getClass());
- PropertyDescriptor[] pds = info.getPropertyDescriptors();
- Object retVal =null;
- for(PropertyDescriptor pd :pds){
- if(pd.getName().equals(propertyName)){
- retVal = pd.getReadMethod().invoke(obj);
- break;
- }
- }
- return retVal;
- }
- // 方法的抽取:Refactor->重构。Extract Method
- private static void setProperty(Object obj, String propertyName,
- Object value) throws IntrospectionException,
- IllegalAccessException, InvocationTargetException {
- PropertyDescriptor pd = new PropertyDescriptor(propertyName,
- obj.getClass());
- Method methodSetX = pd.getWriteMethod();
- methodSetX.invoke(obj, value);
- }
- }
相关文章
- 暂无相关文章
用户点评