java第五篇 java反射的学习

1.java反射是什么?

    java反射机制:指的是程序运行时能够获取自身的信息。在Java中只要给定类的名字,那么就可以通过反射机制来获取类的所有信息。

2.反射有什么用?

    增加程序的灵活性,避免将程序写死到代码里.
    优点:可以实现动态创建对象和编译,体现出很大的灵活性。

3.反射一般用在哪里?

    一般用在框架体层比较多,如:初始化一些程序配置,配置文件properties可以由用户自己修改,这样就不需要一有问题就发新包给用户,
    让用户进行卸载更新应用程序,提高了灵活性。


*不过直接读取properties配置文件即可,为啥还需要用反射呢?*


    拿到properties,这样的话你想取里面的值就需要在应用的全局变量中存储properties,否则每次都要去getProperties(),
    然后根据properties.getProperty("name"),这样子很麻烦,可以直接把配置文件中的内容反射到一个类里,这个类专门存放与配置
    文件相应的变量,这样我们代码中就可以通过类的变量来获取properties配置文件中的值。

4.如何使用反射?

第一步:获取Class对象。

Class类:Java中java.lang.Class类用于表示一个类的字节码(.class)文件.


如何得到某个class文件对应的Class对象
    已知类和对象的情况下
        类名.class 
        对象.getClass() ---- Object类提供

    未知类和对象的情况下
        Class.forName(“包名.类名”) 


Class类代表某个类的字节码,并提供了加载字节码的方法:forName(“包名.类名”)
forName方法用于加载类字节码到内存中,并封装成一个Class对象.


第二步:通过Class对象中的方法获取类中构造方法、成员变量、方法,拿到后对外提供都是对象,有Constructor、Field、Method对象。

    1.创建实例(获得构造器).

    Constructor类
        Constructor类的实例对象代表类的一个构造方法

    得到某个类所有的构造方法
        Constructor [] constructors=        Class.forName("java.lang.String").getConstructors();

    得到指定的构造方法并调用
        Constructor constructor = Class.forName(“java.lang.String”).getConstructor(String.class);
        String str = (String)constructor.newInstance(“abc”);

    Class类的newInstance()方法用来调用类的默认构造方法
        String obj =(String)Class.forName("java.lang.String").newInstance();

1).class.newInstance()创建实例,相对于无参数的构造方法,如:
Person p = (Person)clazz.newInstance();

2).Constructor c = class.getConstructor(int.class,String.class);//创建实例,相对于一个带(int,String)参数的有参构造方法.
//通过构造器来创建实例。
Person p2 = (Person)c.newInstance(28,”张三”);

3)class.getConstructors();//获取说有构造器。

    2.获取属性的对象。

    Field类
        Field类代表某个类中的一个成员变量,并提供动态的访问权限

        Field对象的获得
        得到所有的成员变量
        Field[] fields = c.getFields(); // 取得所有public属性(包括父类继承)
        Field[] fields = c.getDeclaredFields(); // 取得所有声明的属性

        得到指定的成员变量
        Field name = c. getField("name");
        Field name = c. getDeclaredField("name");

        设置Filed变量是否可以访问
        field. setAccessible(boolean);

        Field变量值的读取、设置
        field.get(obj)
        filed.set(obj,value);

获取属性:
1).class.getField(“name”);//获取公有的name的属性,即Person类中的name属性必须声明为public才行,如果是private String name声明为private私有的,获取不到。

2).Field name = class.getDeclaredField(“name”);//可以获取公有的和私有的
//拿到name的属性之后,可以设置属性的内容
name.setAccessible(true);//设置操作属性,就是允许你去操作name属性,因为name是私有的,你不是他,你操作不了。
//设置属性内容,需要传一个实例
Person person = (Person)class.newInstansnce();
name.set(person,”张三”);//这句话相当于 p.name = “张三’;

//获取属性值
System.out.println(name.get(person));//输出: 张三
//获取属性名称
System.out.println(name.getName());//输出: name

    3.获取方法的对象。

        Method类
            Method类代表某个类中的一个成员方法

            Method对象的获得
            获得所有方法 
            getDeclaredMethods() 
            getMethods()

            获得指定的方法
            getDeclaredMethod(String?name, Class<?>...?parameterTypes) 
            getMethod(String?name, Class<?>...?parameterTypes) 

            m.setAccessible(true);

            通过反射执行方法
            invoke(Object?obj, Object...?args) 

            注意:如果执行static方法 ,第一个参数obj 传入 null

获取方法:
1).Method m = class.getDeclaredMethod(“setName”,String.class);//获取公有的和私有的方法
m.setAccessible(true);

Person p = (person)clazz.newInstance();
m.invoke(p,”张三”);//相当于 p.setName(“张三”);

//获取方法名称
System.out.println(m.getName());//输出: setName

其他方法:

        boolean isArray():是否为数组类型;
      ? boolean isAnnotation():是否为注解类型;
      ? boolean isAnnotationPresent(Class annotationClass):当前类是否被annotationClass注解了;
      ? boolean isEnum():是否为枚举类型;
      ? boolean isInterface():是否为接口类型;
      ? boolean isPrimitive():是否为基本类型;
      ? boolean isSynthetic():是否为引用类型;

其他反射类:

        其他反射类都在java.lang.reflect包下
        1.AccessibleObject

        AccessibleObject类是Constructor、Method、Field三个类的父类。

        ? Annotation getAnnotation(Class annotationClass):获取作用在当前成员上的annotationClass类型的注解对象;
        ? Annotation[] getAnnotations():获取作用在当前成员上的所有注解对象;
        ? boolean isAccessible():判断当前成员是否可访问;
        ? void setAccessible(boolean flag):设置当前成员是否可访问。


        2.Construcator

        ? String getName():获取构造器名;
        ? int getModifiers():获取构造器上的所有修饰符信息;
        ? Class getDeclaringClass():获取构造器所属的类型;
        ? Class[] getParameterTypes():获取构造器的所有参数的类型;
        ? Class[] getExceptionTypes():获取构造器上声明的所有异常类型;
        ? T newInstance(Object… initargs):通过构造器反射对象调用构造器。


        3.Method

        ? String getName():获取方法名;
        ? int getModifiers():获取方法上的所有修饰符信息;
        ? Class getDeclaringClass():获取方法所属的类型;
        ? Class[] getParameterTypes():获取方法的所有参数的类型;
        ? Class[] getExceptionTypes():获取方法上声明的所有异常类型;
        ? Class getReturnType():获取方法的返回值类型;
        ? Object invode(Object obj, Object… args):通过方法反射对象调用方法,如果当前方法是实例方法,那么当前对象就是obj,
        如果当前方法是static方法,那么可以给obj传递null。args表示是方法的参数;
        ? setAccessible(true);


        4.Field

        ? String getName():获取属性名;
        ? int getModifiers():获取属性上的所有修饰符信息;
        ? Class getDeclaringClass():获取属性所属的类型;
        ? Class getType():获取当前属性的类型;
        ? Object get(Object obj):获取obj对象的当前属性值;
        ? void set(Object obj, Object value):设置obj对象的当前属性值为value;
        ? XXX getXXX(Object obj):如果当前属性为基本类型,可以使用getXXX()系列方法获取基本类型属性值。假如当前属性为int类型,
        那么可以使用getInt(Object obj)方法获取obj对象的当前属性值;
        ? void setXXX(Object obj, XXX value):如果当前属性为基本类型,可以使用setXXX()系统方法基本类型属性值。假如当前属性为int类型,
        那么可以使用setInt(Object obj, int value)方法设置obj对象的当前属性值为value。


        5.Modifier
        Modifier类有一系列的static方法用来解析其他getModifiers()方法返回的int值。
        Method m = …
        int m = m.getModifiers();
        boolean b1 = Modifier.isAbstract(m);//解析m中是否包含abstract修饰
        boolean b2 = Modifier.isStatic(m);//解析m中是否包含static修饰
        String s = Modifiers.toString(m);//把所有修饰都转换成字符串

    其他补充:isAssignableFrom 是用来判断一个类Class1和另一个类Class2是否相同或是另一个类的超类或接口。   
      通常调用格式是:   
          Class1.isAssignableFrom (Class2)   
          调用者和参数都是   java.lang.Class   类型。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值