zoukankan      html  css  js  c++  java
  • java-反射

    class

    class本身是一种数据类型,class/interface的数据类型是Class,JVM为每个加载的类、接口创建唯一的Class实例。

    Class实例包含该class的所有信息,通过Class实例获取class信息的方法称为反射(Reflection)。反射的目的是当获得某个Object实例时,我们可以获得该Object的class信息。

    获取一个class的Class实例:

    Class cls = String.class;
    Class cls = "str".getClass();
    Class cls = Class.forName("java.lang.String");
    

    Class实例在JVM中是唯一的

    • == 比较两个实例(只能精确的判断数据类型,不能做子类的比较)

        Class cls1 = String.class;
        String s = "Hello";
        Class cls2 = s.getClass();
        Class cls3 = Class.forName("java.lang.String");
        
        boolean b1 = cls1==cls2;  //true
        boolean b1 = cls1==cls3;  //true
      
    • 使用instanceof(不但匹配当前类型,还匹配当前类型的子类)

        Integer n = new Integer(123);
        boolean b3 = n instanceof Integer; //true
        boolean b4 = n instanceof Number;  //true
        //Integer是Number的子类
        boolean b1 = n.getClass() == Integer.class; //true
        boolean b2 = n.getClass() == Number.class;  //false
      
    • 通常情况下我们使用instanceof进行比较。

    从Class实例获取class信息:

    • getName()

    • getSimpleName()

    • getPackage()

        Class cls = String.class;
        String name =  cls.getName();				//"java.lang.String"
        String sname = cls.getSimpleName();			//"String"
        String pkg = cls.getPackage().getName();	//"java.lang"
      

    从Class实例判断class类型:

    • isInterface()

    • isEnum()

    • isArray()

    • isPrimitive()

        Runnable.class.isInterface(); 	//true
        java.time.Month.class.isEnum(); //true
        String [].class.isArray();		//true
        int.class.isprimitive();		//true
      

    创建class实例:

    • cls.newInstance()

        Class cls = String.class;
        //new String();
        String s = (String)cs.newInstance();
        这里的局限在于,只能调用String类的public、无参的默认构造方法,带参数的构造方法我们没有办法调用。
      

    JVM总是动态加载class,可以在运行期根据条件控制加载class。

    • 利用JVM动态加载class的特性,可以在运行期间跟据条件不同加载不同的实现类。

        //Commons logging优先使用Log4j:
        LogFactory factory;
        if(isClassPresent("org.apache.logging.log4j.LOgger")){
        	factory =  createLog4j();
        }else{
        	factory = createJDKLog();
        }
      
        boolean isClassPresent(String name){
        	try{
        		Class.forName(name);
        		return true;
        	}catch(Exception e){
        		return false;
        	}
        }
      

    访问字段 Field对象封装了字段的所有信息

    通过Class实例获取字段field信息:

    • getField(name):获取某个public的field(包括父类)

    • getDeclaredField(name):获取当前类的某个field(不包括父类)

    • getFields():获取所有public的field(包括父类)

    • getDeclaredFields():获取当前类的所有field(不包括父类)

        Integer n = new Integer(123);
        Class cls = n.getClass();
        Field []fs = cls.getFields();
        for(Field f: fs){
      
        	f.getName();
        	f.getType();
        	f.getModeifiers();
        }
      

    Field对象包含一个field的所有信息:

    • getName()
    • getType()
    • getModifiers() 获得修饰符(private、public、protect)

    获取和设置field的值:

    • get(Object obj)

    • set(Object, Object)设置一个实例的该字段的值

        Integer n = new Integer(234);
        Class cls = n.getClass();
        Field f = cls.getDeclaredField("value");
        f.get(n);  //234   相当于n.value
        f.set(n,123);   //相当于n.value=456;
      

    通过反射访问Field需要通过SecurityManager设置的规则。

    • SecurityManager的规则阻止对该Field设置accessible:

        例如,规则应用于所有java和javax开头的package的类
      

    通过设置setAccessible(true)来访问非public字段(可能会失败)

    f.setAccessible(true);
    

    调用方法 Method

    通过Class实例获取方法Method信息:

    • getMethod(name, Class...):获取某个public的method(包括父类)
    • getDeclaredMethod(name, Class...):获取当前类的某个method(不包括父类)
    • getMethods():获取所有public的method(包括父类)
    • getDeclaredMethods():获取当前类的所有method(不包括父类)

    Method对象包含一个method的所有信息:

    • getName()
    • getReturnType()
    • getParameterTypes()
    • getModifiers()

    调用Method:

    • Object invoke(Object obj, Object... args)

    通过设置setAccessible(true)来访问非public方法。

    反射调用Method也遵守多态的规则。


    调用构造方法 Constructor

    调用public无参数构造方法:

    • Class.newInstance()

    通过Class实例获取Constructor信息:

    • getConstructor(Class...):获取某个public的Constructor
    • getDeclaredConstructor(Class...):获取某个Constructor
    • getConstructors():获取所有public的Constructor
    • getDeclaredConstructors():获取所有Constructor

    通过Constructor实例可以创建一个实例对象:

    • newInstance(Object… parameters)

    通过设置setAccessible(true)来访问非public构造方法。


    获取继承关系

    获取父类的Class:

    • Class getSuperclass()
    • Object的父类是null
    • interface的父类是null

    获取当前类直接实现的interface:

    • Class[] getInterfaces()
    • 不包括间接实现的interface
    • 没有interface的class返回空数组
    • interface返回继承的interface

    判断一个向上转型是否成立:

    • bool isAssignableFrom(Class)

        Integer.isAssignableFrom(Number.class);		//false
        Number.isAssignableFrom(Integer.class);		//true
  • 相关阅读:
    Java 判断日期的方法
    HTTP Session例子
    Unity3D性能优化
    TCP学习之二:客户端与服务端的连接
    TCP学习之一:TCP网络编程概念
    TCP学习之三:客户端、服务端同步传输字符串
    TCP学习之四:传输协议
    Lua与.net的CLR相互调用
    HTC vive开发:关于手柄按键
    JavaSESocket编程之简易聊天系统
  • 原文地址:https://www.cnblogs.com/rogersma/p/11484138.html
Copyright © 2011-2022 走看看