zoukankan      html  css  js  c++  java
  • 反射

    java的反射机制

    在运行过程中动态的获取信息和调用对象方法的功能称为java的反射机制。

    通过反射可以获得类的属性,方法,父类,接口,包相关的信息。因为类在加载的时候,会在内存中生成一个代表这个.class文件的java.lang.Class对象,.class文件包含类的所有信息。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    实例

    package algorithm;
    
    import java.io.Serializable;
    
    public class Student extends Man implements Cloneable, Serializable{
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    	private String str;
    	
    	private static double d;
        public boolean b;
        public static short s; 
    
    	public Student(){
    		
    	}
    	public Student(String str){
    		this.str = str;
    	}
    	public Student(boolean b){
    		this.b = b;
    	}
    	public Student(double d){
    		this.d = d;
    	}
    	
    	private void privateMethod(){
            System.out.println("privateMethod");
        }
        
        public String publicMethod(){
            return null;
        }
    	
        public String publicMethod(String str,double d){
            return "str="+str+",double="+d;
        }
        
    	public static long getSerialversionuid() {
    		return serialVersionUID;
    	}
    	public String toString()
        {
            return "str = " + str + ", d = " + d + ", b = " + b;
        }
    	
    }
    
    public class Man {
    	private String man1;
    	
    	public int man2;
    
    	public void hello(){
    		System.out.println("hello man");
    	}
    	
    }
    

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    class和classloader

    public static void main(String[] args) throws Exception{
            Class<Student> c = Student.class;
            Student[] students = new Student[2];
            System.out.println("Class.getClass():" + c.getClass()); // 获取java.lang.Class的Class对象
            System.out.println("Class.getClassLoader():" + c.getClassLoader()); // 获取类的加载器
            System.out.println("Class.getSuperclass():" + c.getSuperclass()); // 获取父类Class对象
            System.out.println("Class.getInterfaces():" + c.getInterfaces()[0] + ", " + c.getInterfaces()[1]); // 获取类的接口列表,注意返回的是一个数组
            System.out.println("ArrayClass.getClass():" + students.getClass()); // 获取该数组的Class对象            
            System.out.println("ArrayClass.getComponentType():" + students.getClass().getComponentType());//数组中对象的类型
            Student student = (Student)c.newInstance(); // 根据Class实例化出一个类实例来,默认调用无参构造方法
            System.out.println("student:"+student);//student的tostring方法
        }
    

    结果是

    Class.getClass():class java.lang.Class
    Class.getClassLoader():sun.misc.Launcher$AppClassLoader@23137792
    Class.getSuperclass():class algorithm.Man
    Class.getInterfaces():interface java.lang.Cloneable, interface java.io.Serializable
    ArrayClass.getClass():class [Lalgorithm.Student;    //数组类型的class的表现方式
    ArrayClass.getComponentType():class algorithm.Student
    student:null
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    package

    public static void main(String[] args) throws Exception{
            Class<Student> c = Student.class;
            Package p = c.getPackage();
            System.out.println("Package.toString():" + p.toString()); //toString()
            System.out.println("Package.getName():" + p.getName());     // 获取包名    
            System.out.println("Package.getImplementationTitle():" + p.getImplementationTitle()); // 获取包标题
            System.out.println("Package.getImplementationVendor():" + p.getImplementationVendor()); // 获取提供该实现的组织、供应商或公司的名称
            System.out.println("Package.getImplementationVersion():" + p.getImplementationVersion()); // 获取该实现的版本
            System.out.println("Package.isSealed():" + p.isSealed()); // 获取包是否密封的
        }
    

    结果是

    Package.toString():package algorithm
    Package.getName():algorithm
    Package.getImplementationTitle():null
    Package.getImplementationVendor():null
    Package.getImplementationVersion():null
    Package.isSealed():false

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    field

    反射是直接获得属性,而不是通过get set方法

    	public static void main(String[] args) throws Exception{
    		
    		Class<Student> c = Student.class;
    		Field f1 = c.getField("b");
    		Field f2 = c.getDeclaredField("d");
    		Field[] fs1 = c.getFields();
    		Field[] fs2 = c.getDeclaredFields();
    		Student student = new Student();
    		System.out.print("Class.getFields():"); // 获取类中所有public字段,顺序即public的Field定义的顺序,包括父类的
    	    for (Field f : fs1)
    	        System.out.print(f+"
    ");
    	    System.out.println("-----------------------------------------------");
    	    System.out.print("Class.getDeclaredFields():"); // 获取类中所有声明的字段,顺序即所有Field定义的顺序,父类的无法获取
    	    for (Field f : fs2)
    	        System.out.print(f + "
    ");
    	    System.out.println("-----------------------------------------------");
    	    System.out.println("Class.getField(String name):" + f1); // 根据name获取类中一个访问权限为public的字段,包括父类的
    	    System.out.println("-----------------------------------------------");
    	    System.out.println("Class.getDeclaredField(String name):" + f2); // 根据name获取类中声明的字段,父类的无法获取。
    	    System.out.println("-----------------------------------------------");
    	    System.out.println("Field.getName():" + f1.getName()); // 获取字段名
    	    System.out.println("Field.getType():" + f1.getType()); // 获取该属性返回类型
    	    System.out.println("Field.getModifiers():" + f1.getModifiers()); // 以整数形式返回此Field对象的Java语言修饰符,返回的值是全部修饰符对应值的和。具体对应值在下面。
    	    System.out.println("Field.getBoolean():" + f1.getBoolean(student));    // 获取某个实例对象该Field的值,什么类型的Field就是getXXX(Object obj)也可以获得高精度结果。
    	    System.out.println("Field.isAccessible():" + f1.isAccessible()); // 返回Field的访问权限,默认都是false。如果访问权限满足调用时的访问条件则没有什么用处。
    	    f2.setAccessible(true);
    	    System.out.println("Field.get():" + f2.get(student)); //获取某实例对象任意类型的field的值。要求调用该方法时对应属性的访问权限必须满足访问条件。如果不满足时,比如权限为private时,
    	    //执行对应field的setAccessible(true)方法,在任何地方都可以获取值,否则抛异常。
    	    System.out.println("student:"+student);
    	    f1.set(student, true);
    	    System.out.println("student:"+student);
    	}
    

     结果是

    Class.getFields():public boolean algorithm.Student.b
    public static short algorithm.Student.s
    public int algorithm.Man.man2
    -----------------------------------------------
    Class.getDeclaredFields():private static final long algorithm.Student.serialVersionUID
    private java.lang.String algorithm.Student.str
    private static double algorithm.Student.d
    public boolean algorithm.Student.b
    public static short algorithm.Student.s
    -----------------------------------------------
    Class.getField(String name):public boolean algorithm.Student.b
    -----------------------------------------------
    Class.getDeclaredField(String name):private static double algorithm.Student.d
    -----------------------------------------------
    Field.getName():b
    Field.getType():boolean
    Field.getModifiers():1
    Field.getBoolean():false
    Field.isAccessible():false
    Field.get():0.0
    student:str = null, d = 0.0, b = false
    student:str = null, d = 0.0, b = true

     ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    constructor

    public static void main(String[] args) throws Exception{
    	    Class<Student> c = Student.class;
    	    Constructor<?> constructor = c.getConstructor(String.class);
    	    Constructor<?>[] constructors = c.getConstructors();
    	    System.out.println("Class.getConstructor(String):" + constructor); // 获取指定参数列表的构造函数
    	    System.out.print("Class.getConstructors():"); // 获取所有的构造函数
    	    for (Constructor<?> con : constructors)
    	        System.out.print(con + "
    ");
    	    System.out.println("Constructor.getName():" + constructor.getName()); // 获取构造函数名,没什么意义,肯定是和类同名
    	    System.out.println("Constructor.getModifiers():" + constructor.getModifiers()); // 获取以整数形式返回的此Constructor对象的Java语言修饰符,如public、static、final等
    	    System.out.println("Constructor.isAccessible():" + constructor.isAccessible()); // 获取该Constructor的访问权限
    	    System.out.println("Constructor.getParameterTypes():" + constructor.getParameterTypes()[0]); // 获取Constructor的参数类型,是个数组
    	    System.out.println("Constructor.isVarArgs():" + constructor.isVarArgs()); // 获取此Constructor中是否带了可变数量的参数,即例如"String... str"类型的参数
    	    Student student = (Student)constructor.newInstance("tp");//使用构造方法是constructor来实例化对象。这里的参数是String类型,如果传入int类型进去,编译时没错,但是运行时报错
    	    System.out.println("student:"+student);
    	}
    

     结果是

    Class.getConstructor(String):public algorithm.Student(java.lang.String)
    Class.getConstructors():public algorithm.Student(double)
    public algorithm.Student(boolean)
    public algorithm.Student(java.lang.String)
    public algorithm.Student()
    Constructor.getName():algorithm.Student
    Constructor.getModifiers():1
    Constructor.isAccessible():false
    Constructor.getParameterTypes():class java.lang.String
    Constructor.isVarArgs():false
    student:str = tp, d = 0.0, b = false

      ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     method

    public static void main(String[] args) throws Exception{
    		Class<Student> c = Student.class;
    		Student student = new Student();
    		Method md0 = c.getMethod("publicMethod", String.class, double.class);
    	    Method md1 = c.getDeclaredMethod("privateMethod", new Class[0]);//对于没有参数的方法就这么写。
    	    Method[] mds0 = c.getMethods();
    	    Method[] mds1 = c.getDeclaredMethods();
    	    System.out.println("Method.getMethod():" + md0); // 根据方法名和参数列表获取指定的public方法,继承的方法也可以。
    	    System.out.println("Method.getDeclaredMethod():" + md1); // 根据方法名和参数列表获取指定的任意访问权限的方法,继承的方法不可以获取
    	    System.out.println("-----------------------------------------------");
    	    System.out.print("Method.getMethods():"); // 获取此类包括其父类中所有的public方法
    	    for (Method m : mds0)
    	        System.out.print(m + "
    ");
    	    System.out.println("-----------------------------------------------");
    	    System.out.print("Method.getDeclaredMethods():"); // 返回此类中所有的方法(无访问权限限制),继承的方法没有
    	    for (Method m : mds1)
    	        System.out.print(m + "
    ");
    	    System.out.println("-----------------------------------------------");
    	    System.out.println("Method.getName():" + md0.getName()); // 获取方法的名字
    	    System.out.println("Method.isAccessible():" + md0.isAccessible()); // 获取方法的访问属性
    	    System.out.println("Method.isVarArgs():" + md0.isVarArgs()); // 获取方法是否带有可变数量的参数
    	    System.out.println("Method.getReturnType():" + md0.getReturnType()); // 获取方法的返回类型
    	    System.out.println("Method.getParameterTypes():" + md0.getParameterTypes()[0] + ", " + md0.getParameterTypes()[1]); // 获取方法的参数类型,数组形式,注意一下和下面的方法的区别
    	    System.out.println("Method.getGenericParameterTypes():" + md0.getGenericParameterTypes()[0] + ", " + md0.getGenericParameterTypes()[1]); // 获取方法的参数化(带泛型)类型,数组形式
    	    System.out.println(md0.invoke(student, "tp", 2.2));
    	}
    

     结果是

     Method.getMethod():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
    Method.getDeclaredMethod():private void algorithm.Student.privateMethod()
    -----------------------------------------------
    Method.getMethods():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
    public java.lang.String algorithm.Student.publicMethod()
    public static long algorithm.Student.getSerialversionuid()
    public java.lang.String algorithm.Student.toString()
    public void algorithm.Man.hello()
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    -----------------------------------------------
    Method.getDeclaredMethods():public java.lang.String algorithm.Student.publicMethod(java.lang.String,double)
    public java.lang.String algorithm.Student.publicMethod()
    private void algorithm.Student.privateMethod()
    public static long algorithm.Student.getSerialversionuid()
    public java.lang.String algorithm.Student.toString()
    -----------------------------------------------
    Method.getName():publicMethod
    Method.isAccessible():false
    Method.isVarArgs():false
    Method.getReturnType():class java.lang.String
    Method.getParameterTypes():class java.lang.String, double
    Method.getGenericParameterTypes():class java.lang.String, double
    str=tp,double=2.2
    student:str = null, d = 0.0, b = false

      ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    getModifiers()方法的枚举

    Field、Constructor、Method中都有getModifiers()方法,返回的是表示此对象的Java语言修饰符,详细看下每个修饰符对应的枚举值:

    修饰符 枚举值
    public 1
    private 2
    protected 4
    static 8
    final 16
    synchronized 32
    volatile 64
    transient 128
    native 256
    interface 512
    abstract 1024
    strict

    2048

    getModifiers()方法是把所有的权限值加上的和。比如public static final synchronized,结果是1+8+16+32=57。每一个修饰符的值对应12位二进制的每一个位置,所以如果给出一个权限值,把它转换为二进制,那个位置上有值,就对应有哪个权限。

    参考借鉴http://www.cnblogs.com/xrq730/p/4862111.html

  • 相关阅读:
    自定义指令directive
    angular中的表单验证
    ng-init,ng-controller,ng-model
    Redis执行lua脚本,key不存在的返回值
    消息队列对比
    数据库设计范式
    网络IO模型
    .NET 线程、线程池
    异步和多线程
    Memcache知识点
  • 原文地址:https://www.cnblogs.com/tp123/p/6386705.html
Copyright © 2011-2022 走看看