zoukankan      html  css  js  c++  java
  • 反射

      反射是动态语言的关键,反射允许程序在执行期间借助Reflection API取得任何类的内部信息,并能直接操作任曦对象的内部属性及方法。

    1.Java反射提供的功能

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判断任意一个类具有的成员变量和方法
    • 在运行时调用任意一个对象的成员变量和方法

    2.放射常用的API

    • java.lang.Class : 代表一个类
    • java.lang.reflect.Method:代表类的方法
    • java.lang.reflect.Field:代表类的成员变量
    • java .lang.reflect.Construct:代表类的构造方法

    3.java.lang.Class

      我们创建一个类,通过编译(Javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM类加载器)此.class文件。此.class文件加载到内存以后,就是一个运行时类。存放在缓冲区,Class允许通过一个实例化对象找到一个类的完成信息。

      Class类的作用:

        1.每一个运行时类只加载一次!

        2.获取对应的运行时类的完整结构(属性,方法,构造器,内部类,父类,所在包,异常,注 解。。。。)

        3.调用对应的运行时类的指定结构(属性,方法,构造器)

        4.反射应用:动态代理

    4.获取Class对象。

    1.调用运行时类本身的.class属性

     Class<Person> personClass01 = Person.class;

    2.通过运行时类的一个对象

    Person person = new Person();
    Class<? extends Person> aClass = person.getClass();

    3.通过Class.forName("com.jdy.bean.Dog")

    Class<?> aClass1 = Class.forName("com.jdy.bean.Dog");

    4.通过类的加载器

    ClassLoader classLoader = this.getClass().getClassLoader();

    5.Class类的常用方法

    public Constructor<?>[] getConstructors() throws SecurityException //获取类的全部构造
    public Field[] getDeclaredFields() throws SecurityException//获取类中全部的属性
    public Field[] getFields() throws SecurityException //获取继承的全部属性
    public Method[] getMethods() throws SecurityException//获取一个类中的所有方法
    public Class<?>[] getInterfaces() //获取类实现的所有接口
    public native Class<? super T> getSuperclass();//获取类的父类

    6.Class应用

    (1)通过无参构造实例化对象

    String packageName ="com.jdy.bean.Dog";
    Class<?> aClass = Class.forName(packageName);
    Dog dog = (Dog)aClass.newInstance();
    //使用newInstance()必须保证实例化类中存在一个无参构造器

    (2)调用有参构造器实例化对象

    public int getModifiers()//获取构造方法的修饰符
    public String getName()//获取构造方法的名称
    public Class<?>[] getParameterTypes()//获取构造方法的参数类型
    public T newInstance(Object ... initargs)//像构造方法,传入参数实例化对象
    <Dog> constructor = (Constructor<Dog>) aClass.getConstructor(String.class, String.class, String.class);
    Dog dog1 = constructor.newInstance("二狗子", "黑背", "8");

    (3)获取类结构

    • Constructor:表示类的构造器
    • Field:表示类的属性
    • Method:表示类的方法

     取得所有实现的接口

    Class<?>[] interfaces = aClass.getInterfaces();

      取得父类

    Class<?> superclass = aClass.getSuperclass();

      取得全部构造器

    Constructor<?>[] constructors = aClass.getConstructors();

      将访问修饰符由数字转化成可看懂的

    int modifiers = declaredField.getModifiers();
    System.out.println("modifiers = " + Modifier.toString(modifiers));

      取得所有的方法

    Method[] methods = aClass.getMethods();

      取得全部属性

    //得到实现的接口或父类中的公共属性
    Field[] fields = aClass.getFields();
    //得到本类当中的全部属性
    Field[] declaredFields = aClass.getDeclaredFields();

      Field的常用方法

    //得到一个对象中属性的具体内容 
    public Object get(Object obj)throws IllegalArgumentException, IllegalAccessException
    //设置指定对象中属性的具体内容
    public void set(Object obj, Object value)
            throws IllegalArgumentException, IllegalAccessException
    //得到属性的修饰符
    public int getModifiers()
    //返回属性的名称
    public String getName()   
    //判断属性是否可悲外部访问
    public boolean isAccessible()
     //设置一个属性是否可被外部方法
    public void setAccessible(boolean flag) throws SecurityException 

    (4)通过反射待用类中的方法

    Method destory_method = aClass.getMethod("destory_method");
    //invoke方法的参数是一个实例化的对象
    Object invoke = destory_method.invoke(aClass.newInstance());

    (5)通过方法操作属性

      反射中通过Field类提供的set()/get()完成设置和取得属性内容的操作,但是类中的属性都设置成私有的访问权限,所以在使用set()/get()方法时首先要使用Field()中的setAccessible(true),方法将需要操作的属性设置成可被外部访问。

    Field field0 = personClass.getDeclaredField("address");
    //todo 什么校验
    field0.setAccessible(true);
    field0.set(person,"xian");
    System.out.println(person);

      一般给类的属性赋值,不建议使用以上方法,因为扩大了属性的访问权限,建议使用类中属性的getter/setter方法

    5.ClassLoader:类的加载器 类的加载器是用来把类(class)装载进内存的,JVM规范定义了两种类型的类加载器: 启动类加载器(bootstrap) 用户类加载器(user-defind class loader) JVM 在运行时会产生3个类加载器组成的初始化加载器层次结构

      

      Bootstrap ClassLoader:引导类加载器:用C++编写,时jVM自带的类加载器,负责JAVA平台核心类库的加载。该加载器无法直接获取

    //3.引导类加载器不能直接获取
    ClassLoader parent1 = parent.getParent();
    System.out.println("引导类加载器 = " + parent1);//null

       Extension ClassLoader:负责jre/lib/ext目录下的jar包或者 -D java.ext.dirs指定目录下的jar包装入工作库

    //2.获取扩展类加载器
    ClassLoader parent = loader.getParent();
    System.out.println("扩展类加载器 = " + parent);

      System ClassLoader:系统类加载器,负责java -classpath 或者 -D java.class.path所知的目录下的类与jar包装入工作,是最常用的加载器

    //1.获取系统类加载器
    ClassLoader loader = ClassLoader.getSystemClassLoader();
    System.out.println("系统类加载器 = " + loader);

      获取某个实例的类加载器

    Person person = new Person();
    Class<? extends Person> aClass = person.getClass();
    ClassLoader classLoader = aClass.getClassLoader();
    System.out.println("Perosn类的加载器 = " +classLoader);
    Class<?> aClass1 = Class.forName("com.jdy.bean.Dog");
    ClassLoader classLoader1 = aClass1.getClassLoader();
    System.out.println("Dog类的加载器 = " + classLoader1);

      类加载器配合IO

    ClassLoader classLoader2 = this.getClass().getClassLoader();
    InputStream resourceAsStream = classLoader2.getResourceAsStream("test.properties");
    Properties properties = new Properties();
    properties.load(resourceAsStream);
  • 相关阅读:
    jQuery检测滚动条(scroll)是否到达底部
    sql group by
    hbm.xml 详解总结
    net.sf.json 时间格式的转化
    经典SQL语句大全
    HashTable
    in与exist , not in与not exist 的区别
    网页布局常用的一些命名规则和书写
    什么是SOA?
    sql之left join、right join、inner join的区别
  • 原文地址:https://www.cnblogs.com/jdy1022/p/14819702.html
Copyright © 2011-2022 走看看