• Java中的反射


    *传统方式:
       只能静态的创建java对象
    * 反射的特点:
      实现了java对象的动态创建.(可以在不确定类的时候动态创建)
    * 反射的缺点:
       反射的代码效率低,影响程序性能.
    *开发使用:
       反射和传统结合的方式

      

    1.反射创建类对象
      第一种方式--->创建类对象
        Class clazz=Class.forName(全限定路径名);

        eg

           Class clazz=Class.forName("pojo.Person");

      第二种方式---->调用底层使用反射封装的方法
        Class cla02=类.class;

        eg

          Class clazz=Person.class;
    

      


      第三种方式---->调用底层使用反射封装的方法
        Class cla03=对象.getClass();

        eg

        Class cla03=new Person().getClass();
    

      2.反射调用类的基本信息

        获取类对象的包名---->clazz.getPackage()
        获取类的修饰符----->clazz.getModifiers()
        获取类的名称(全限定)----->clazz.getName()
        获取类的名称(类名)----->clazz.getSimpleName()
        获取类的父类的类对象----->clazz.getSuperclass()

      3.反射获取操作类的属性

      获取类属性
        * getFields() 获取所有的公共字段包括父类 返回Field[]
        * getDeclaredFields() 获取所有声明的字段(不包括父类) 返回Field[]
        * getField("属性名") 获取指定的公共字段包括父类 返回Field
        * getDeclaredField("属性名") 获取指定的声明的字段(不包括父类) 返回Field

      

      操作类属性
        * 操作静态属性
        * 类属性对象.get(null) 返回静态属性的值
        * 类属性对象.set(null,"值") 赋值
        * 操作非静态属性
        * 类属性对象.get(Object obj);
        * 类属性对象.set(Object obj,"值");

    public static void operField() throws ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException{
    		//获取类对象
    		Class cla=Class.forName("com.bjsxt.pojo.Student");
    		//获取反射类属性
    			//获取类及其父类的公共字段
    				Field[] fds = cla.getFields();
    				for(Field f:fds){
    					System.out.println("获取属性名------>"+f.getName());
    					System.out.println("获取修饰符------>"+f.getModifiers());
    					System.out.println("获取类型------>"+f.getType());//返回的是类型的Class对象
    				}
    				System.out.println("******************************");
    			//获取类声明的所有字段
    				Field[] fds2=cla.getDeclaredFields();
    				for(Field f:fds2){
    					System.out.println("获取属性名----->"+f.getName());
    					System.out.println("获取修饰符------>"+f.getModifiers());
    					System.out.println("获取类型------>"+f.getType());//返回的是类型的Class对象
    				}
    				System.out.println("******************************");
    			//获取指定的字段
    				Field f=cla.getField("pname");//指定获取类及其父类的公共字段
    				System.out.println(f.getName());
    				Field f2=cla.getDeclaredField("money");//指定获取类的所有字段
    				System.out.println(f2.getName());
    				Field f3=cla.getSuperclass().getDeclaredField("pname");//指定获取父类声明的字段
    				System.out.println(f3.getName());
    			//操作字段值
    				System.out.println("************操作静态字段**********************");
    				//操作静态属性
    				Field fs=cla.getDeclaredField("money");
    				fs.set(null,2000);
    				System.out.println(fs.get(null));
    				System.out.println("************操作非静态字段**********************");
    				//操作非静态属性
    				Field fd=cla.getDeclaredField("sname");
    				Object obj=cla.newInstance();
    				fd.set(obj, "李四");
    				System.out.println(fd.get(obj));	
    				//暴力反射操作私有化属性(了解)
    				Field fd2=cla.getDeclaredField("ssex");
    				fd2.setAccessible(true);//暴力反射,操作私有化属性,不安全
    				Object obj2=cla.newInstance();//获取实例化对象
    				System.out.println(fd2.get(obj2));
    				
    	}
    

      3.反射操作类方法

      操作方法:
        * 获取类对象
        * 获取方法对象
        * getMethods() 获取所有的公共方法包括父类
        * getDeclaredMethods() 获取所有声明的方法不包括父类
        * getMethod(String name,Class...cla) 获取指定的公共方法
        * String name 表示方法名
        * Class...cla 表示方法接收的参数类型的类对象
        * getDeclaredMethod(String name,Class...cla) 获取指定的声明方法
        * String name 表示方法名
        * Class...cla 表示方法接收的参数类型的类对象
      操作方法
        * 静态方法
        * 方法对象.invoke(null,参数值1,参数值2,....);
        * 方法对象.invoke(null,null);
        * 非静态方法
        * Object obj=cla.newInstance();
        * 方法对象.invoke(obj,参数值1,参数值2,....)
        * 方法对象.invoke(obj,null)

    //操作方法
    	private static void operMethod() throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
    		//获取类对象
    		Class cla=Class.forName("com.bjsxt.pojo.Student");
    		//获取类方法对象
    			//获取所有的公共方法包括父类
    			Method[] ms=cla.getMethods();
    			for(Method m:ms){
    				System.out.println("获取方法名--->"+m.getName());
    
    			}
    			System.out.println("************************************");
    			//获取所有声明的方法不包括父类
    			Method[] ms2=cla.getDeclaredMethods();
    			for(Method m:ms2){
    				System.out.println("获取方法名--->"+m.getName());
                                    System.out.println("方法的修饰符类型" + m.getModifiers());
                                    System.out.println("方法的返回值类型" + m.getReturnType());
            
    			}
    			//获取指定的公共方法包括父类
    				Method m=cla.getMethod("pHi", int.class,String.class);
    				System.out.println(m.getReturnType());
    			//获取指定的声明的方法,不包括父类
    				Method m2=cla.getDeclaredMethod("sHello",null);
    				System.out.println(m2.getName());
    			//执行方法
    				//静态方法
    					Method m3=cla.getDeclaredMethod("sHi",String.class);
    					m3.invoke(null, "今天学了反射");
    				//非静态
    					Method m4=cla.getDeclaredMethod("sHi",int.class,String.class);
    					m4.invoke(cla.newInstance(), 3,"反射");
    	}                                
    

      4.获取构造器为了创建该类的实例对象

        直接用 cla.newInstance("形参")创建对象

    理解:类是对象的抽象,Class也是类,Class类是对类的一直抽象。

  • 相关阅读:
    单用户模式启动SQL Server实例总结
    MySQL下perror工具查看System Error Code信息
    ERROR 1050 (42S01): Table xxx already exists
    RMAN-06172 Troubleshooting
    [翻译]LVM中逻辑卷的最大大小限制
    如何定位那些SQL产生了大量的redo日志
    MySQL的自动提交模式
    MySQL服务读取参数文件my.cnf的规律研究探索
    SQL Server等待事件—RESOURCE_SEMAPHORE_QUERY_COMPILE
    Azure SQL Virtual Machine报Login failed for user 'NT ServiceSqlIaaSExtension'. Reason: Could not find a login matching the name provided
  • 原文地址:https://www.cnblogs.com/kilig/p/12116219.html
Copyright © 2020-2023  润新知