• 反射


    1、Class类

    在面向对象的世界里,万事万物皆对象。类是对象,类是java.lang.Class类的实例对象。

    任何一个类都是Class的实例对象,这个实例对象有三种表示方法:

    1. //1、任何一个类都有一个隐含的静态成员class  
    2.     Class c1 = Foo.class;  
    3.   
    4. //2、已经知道该类的对象,通过getClass方法  
    5.     Class c2 = f.getClass();  
    6.   
    7. /** 
    8.     * c1,c2表示了Foo类的类类型(Class Type) 
    9.     * 类是class类的实例对象 
    10.     * 我们称这个对象为该类的的类类 
    11.     */  
    12.   
    13. //3、通过Class.forName方法  
    14.     Class c3 = null;  
    15.     try {  
    16.         c3 = Class.forName("cn.fedomn.demo.Foo");  
    17.     } catch (Exception e) {  
    18.         e.printStackTrace();  
    19.     }  
    20.           
    21. /** 
    22.  * 我们可以通过类的类类型创建该类的对象实例-->通过c1,c2,c3创建Foo类型的对象 
    23.  */  
    24.     try {  
    25.         Foo f2 = (Foo)c1.newInstance();//需要有无参数的构造方法  
    26.     } catch (InstantiationException e) {  
    27.         e.printStackTrace();  
    28.     } catch (IllegalAccessException e) {  
    29.         e.printStackTrace();  
    30.     }            
    //1、任何一个类都有一个隐含的静态成员class
    	Class c1 = Foo.class;
    
    //2、已经知道该类的对象,通过getClass方法
    	Class c2 = f.getClass();
    
    /**
    	* c1,c2表示了Foo类的类类型(Class Type)
    	* 类是class类的实例对象
    	* 我们称这个对象为该类的的类类
    	*/
    
    //3、通过Class.forName方法
    	Class c3 = null;
    	try {
    		c3 = Class.forName("cn.fedomn.demo.Foo");
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    		
    /**
     * 我们可以通过类的类类型创建该类的对象实例-->通过c1,c2,c3创建Foo类型的对象
     */
    	try {
    		Foo f2 = (Foo)c1.newInstance();//需要有无参数的构造方法
    	} catch (InstantiationException e) {
    		e.printStackTrace();
    	} catch (IllegalAccessException e) {
    		e.printStackTrace();
    	}	       
    

    2、动态加载类

    首先搞清楚,动态加载类和静态加载类的区别

    • 静态加载类:编译时刻加载类
    • 动态加载类:运行时刻加载类(如功能型类 数据库驱动,需要用时才加载进来)

    注意:new 创建对象 是静态加载类,在编译时刻就需要加载所有的可能使用到的类

    动态加载类,解决用的时候才加载该类,如下

    其中cn.fedomn.demo.Word类implements OfficeAble

    1. public class Office {  
    2.     public static void main(String[] args){  
    3.         try {  
    4.             //动态加载类,在运行时刻加载  
    5.             Class c = Class.forName("cn.fedomn.demo.Word");  
    6.             //通过类型转换,创建该类对象  
    7.             OfficeAble oa = (OfficeAble)c.newInstance();  
    8.             oa.start();  
    9.         } catch (Exception e) {  
    10.             e.printStackTrace();  
    11.         }  
    12.     }  
    13. }  
    public class Office {
    	public static void main(String[] args){
    		try {
    			//动态加载类,在运行时刻加载
    			Class c = Class.forName("cn.fedomn.demo.Word");
    			//通过类型转换,创建该类对象
    			OfficeAble oa = (OfficeAble)c.newInstance();
    			oa.start();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }

    3、获取方法信息

    1. public class ClassUtil {  
    2.     public static void printClassMessage(Object obj){  
    3.         //首先获取类的类类型  
    4.         Class c = obj.getClass();  
    5.         //获取类的名称  
    6.         System.out.println("类的名称是:"+c.getName());  
    7.         /** 
    8.          * Method类,方法对象 
    9.          * 一个成员对象就是一个Method对象 
    10.          * getMethods()方法获取的是所以public的函数,包括父类继承而来的 
    11.          * getDeclaredMethods()方法获取的是所有该类自己声明的方法,不问访问权限 
    12.          */  
    13.         Method[] ms = c.getMethods();c.getDeclaredMethods();  
    14.         for(int i=0;i<ms.length;i++){  
    15.             //获取方法返回值类型--->得到方法的返回值类型 的 类类型  
    16.             Class returnType = ms[i].getReturnType();  
    17.             System.out.print(returnType.getName()+" ");  
    18.             //得到方法的名称  
    19.             System.out.print(ms[i].getName()+"(");  
    20.             //获取参数类型--->得到的是参数列表类型 的 类类型  
    21.             Class[] paramTypes = ms[i].getParameterTypes();  
    22.             for(Class class1 : paramTypes){  
    23.                 System.out.print(class1.getName()+",");  
    24.             }  
    25.             System.out.println(")");  
    26.         }  
    27.     }  
    28. }  
    public class ClassUtil {
    	public static void printClassMessage(Object obj){
    		//首先获取类的类类型
    		Class c = obj.getClass();
    		//获取类的名称
    		System.out.println("类的名称是:"+c.getName());
    		/**
    		 * Method类,方法对象
    		 * 一个成员对象就是一个Method对象
    		 * getMethods()方法获取的是所以public的函数,包括父类继承而来的
    		 * getDeclaredMethods()方法获取的是所有该类自己声明的方法,不问访问权限
    		 */
    		Method[] ms = c.getMethods();c.getDeclaredMethods();
    		for(int i=0;i<ms.length;i++){
    			//获取方法返回值类型--->得到方法的返回值类型 的 类类型
    			Class returnType = ms[i].getReturnType();
    			System.out.print(returnType.getName()+" ");
    			//得到方法的名称
    			System.out.print(ms[i].getName()+"(");
    			//获取参数类型--->得到的是参数列表类型 的 类类型
    			Class[] paramTypes = ms[i].getParameterTypes();
    			for(Class class1 : paramTypes){
    				System.out.print(class1.getName()+",");
    			}
    			System.out.println(")");
    		}
    	}
    }

    4、获取成员变量和构造函数信息

    1. /** 
    2.      *获取成员变量信息  
    3.      */  
    4.     public static void printFieldMessage(Object obj) {  
    5.         Class c = obj.getClass();  
    6.         /** 
    7.          * 成员变量也是对象 
    8.          * java.lang.reflect.Field 
    9.          * Field类封装了关于成员变量的操作 
    10.          * getField()方法获取所有public的成员变量的信息 
    11.          * getDeclaredField()获取的是该类自己声明的成员变量的信息 
    12.          */  
    13.         Field[] fs = c.getDeclaredFields();  
    14.         for(Field field : fs){  
    15.             //得到成员变量的类型的类类型  
    16.             Class fieldType = field.getType();  
    17.             String typeName = fieldType.getName();  
    18.             //得到成员变量的名称  
    19.             String fieldName = field.getName();  
    20.             System.out.println(typeName+" "+fieldName);               
    21.         }  
    22.     }  
    23.       
    24.     /** 
    25.      * 获取对象构造函数的信息 
    26.      */  
    27.     public static void printConMessage(Object obj){  
    28.         Class c = obj.getClass();  
    29.         /** 
    30.          * 构造函数也是对象 
    31.          * java.lang.Constructor中封装了构造函数的信息 
    32.          * getConstructors获取所有的public的构造函数 
    33.          * getDeclaredConstructors得到所有的构造函数 
    34.          */  
    35.         Constructor[] cs = c.getDeclaredConstructors();  
    36.         for(Constructor constructor : cs){  
    37.             System.out.print(constructor.getName()+"(");  
    38.             //获取构造函数的参数列表-->得到参数列表的类类型  
    39.             Class[] paramTypes = constructor.getParameterTypes();  
    40.             for(Class class1 : paramTypes){  
    41.                 System.out.print(class1.getName()+",");  
    42.             }  
    43.             System.out.println(")");  
    44.         }  
    45.     }  
    /**
    	 *获取成员变量信息 
    	 */
    	public static void printFieldMessage(Object obj) {
    		Class c = obj.getClass();
    		/**
    		 * 成员变量也是对象
    		 * java.lang.reflect.Field
    		 * Field类封装了关于成员变量的操作
    		 * getField()方法获取所有public的成员变量的信息
    		 * getDeclaredField()获取的是该类自己声明的成员变量的信息
    		 */
    		Field[] fs = c.getDeclaredFields();
    		for(Field field : fs){
    			//得到成员变量的类型的类类型
    			Class fieldType = field.getType();
    			String typeName = fieldType.getName();
    			//得到成员变量的名称
    			String fieldName = field.getName();
    			System.out.println(typeName+" "+fieldName);				
    		}
    	}
    	
    	/**
    	 * 获取对象构造函数的信息
    	 */
    	public static void printConMessage(Object obj){
    		Class c = obj.getClass();
    		/**
    		 * 构造函数也是对象
    		 * java.lang.Constructor中封装了构造函数的信息
    		 * getConstructors获取所有的public的构造函数
    		 * getDeclaredConstructors得到所有的构造函数
    		 */
    		Constructor[] cs = c.getDeclaredConstructors();
    		for(Constructor constructor : cs){
    			System.out.print(constructor.getName()+"(");
    			//获取构造函数的参数列表-->得到参数列表的类类型
    			Class[] paramTypes = constructor.getParameterTypes();
    			for(Class class1 : paramTypes){
    				System.out.print(class1.getName()+",");
    			}
    			System.out.println(")");
    		}
    	}

    5、方法反射操作

    method.invoke(对象,参数列表)

    1. public class MethodDemo1 {  
    2.     public static void main(String args[]){  
    3.         //要获取print(int,int)方法  
    4.         //1、要获取一个方法就是获取类的信息,获取类的信息 首先获取类的类类型  
    5.         A a = new A();  
    6.         Class c = a.getClass();  
    7.         /** 
    8.          * 2、获取方法 名称和参数列表来决定 
    9.          * getMethod获取的是public方法 
    10.          * getDeclaredMethod获取自己声明的方法 
    11.          */  
    12.         try {  
    13.             Method m = c.getMethod("print", int.class,int.class);  
    14.             //方法的反射操作  
    15.             //用m对象来进行方法调用  
    16.             //等同于a.print(10, 20);  
    17.             //方法如果没有返回值返回null,有返回值返回具体返回值  
    18.             try {  
    19.                 Object o = m.invoke(a, 10,20);  
    20.             } catch (IllegalAccessException | IllegalArgumentException  
    21.                     | InvocationTargetException e) {  
    22.                 e.printStackTrace();  
    23.             }  
    24.         } catch (NoSuchMethodException e) {  
    25.             e.printStackTrace();  
    26.         } catch (SecurityException e) {  
    27.             e.printStackTrace();  
    28.         }  
    29.     }  
    30. }  
    31.   
    32. class A{  
    33.     public void print(int a,int b){  
    34.         System.out.println(a+b);  
    35.     }  
    36.     public void print(String a,String b){  
    37.         System.out.println(a.toUpperCase()+","+b.toLowerCase());  
    38.     }  
    39. }  
    public class MethodDemo1 {
    	public static void main(String args[]){
    		//要获取print(int,int)方法
    		//1、要获取一个方法就是获取类的信息,获取类的信息 首先获取类的类类型
    		A a = new A();
    		Class c = a.getClass();
    		/**
    		 * 2、获取方法 名称和参数列表来决定
    		 * getMethod获取的是public方法
    		 * getDeclaredMethod获取自己声明的方法
    		 */
    		try {
    			Method m = c.getMethod("print", int.class,int.class);
    			//方法的反射操作
    			//用m对象来进行方法调用
    			//等同于a.print(10, 20);
    			//方法如果没有返回值返回null,有返回值返回具体返回值
    			try {
    				Object o = m.invoke(a, 10,20);
    			} catch (IllegalAccessException | IllegalArgumentException
    					| InvocationTargetException e) {
    				e.printStackTrace();
    			}
    		} catch (NoSuchMethodException e) {
    			e.printStackTrace();
    		} catch (SecurityException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    class A{
    	public void print(int a,int b){
    		System.out.println(a+b);
    	}
    	public void print(String a,String b){
    		System.out.println(a.toUpperCase()+","+b.toLowerCase());
    	}
    }

    6、通过反射了解集合泛型的本质

    注意:反射的操作(class method field)都是在编译时候的操作,是运行时刻执行的

    下例中:对ArrayList<String>插入int类型的值,就是利用反射invoke,绕过编译实现插入。

    1. public static void main(String args[]){  
    2.         ArrayList list1 = new ArrayList();  
    3.         ArrayList<String> list2 = new ArrayList<String>();  
    4.           
    5.         //list2.add(20);错误只能插入String  
    6.         list2.add("hello");  
    7.           
    8.         Class c1 = list1.getClass();  
    9.         Class c2 = list2.getClass();  
    10.         System.out.println(c1==c2);  
    11.         //反射的操作都是编译之后的操作  
    12.         /** 
    13.          * c1==c2返回true,说明编译之后集合的泛型是去泛型化的 
    14.          * Java中集合的泛型,是防止错误输入的,只在编译阶段有效  编译后就无效了 
    15.          * 验证:通过方法的反射来操作,绕过编译 
    16.          */  
    17.         try {  
    18.             Method m = c2.getMethod("add", Object.class);  
    19.             m.invoke(list2, 10);//绕过编译操作 就绕过了泛型 插入成功  
    20.             //这个时候就不能for-each遍历了  
    21.             System.out.println(list2);  
    22.         } catch (Exception e) {  
    23.         }  
    24.     }  
  • 相关阅读:
    查看程序设计语言排行榜的网站
    转:Android开发实践:用脚本编译Android工程
    ant 自动构建血泪史
    Android ant自动打包 crunch 报错
    android strings.xml 报 is not translated in af,
    HDU 5319
    hdu4405--Aeroplane chess(概率dp第七弹:飞行棋游戏--2012年网络赛)
    Linux 截图
    西工大10级保研机试 柱状图
    Codeforces Round #256 (Div. 2) B. Suffix Structures(模拟)
  • 原文地址:https://www.cnblogs.com/caogang/p/4382561.html
Copyright © 2020-2023  润新知