zoukankan      html  css  js  c++  java
  • java反射机制

    java反射机制

       很喜欢这句话——“当我们面对一项新的知识时,我们往往需要知道三方面,它是什么,它能做什么,它比原有知识强在哪里,我们该怎么使用它。当你能够解决这些问题时,便意味着你已经对这项知识入门了。”

     


     

     一、定义(是什么)

      Java反射机制是在运行状态中,对任意一个类,都能够知道这个类的属性和方法,对任意一个对象,都能够调用这个对象的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

       一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl、Python、Ruby是动态语言,C++、Java、C#不是动态语言。

      尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)

     

     

     二、功能

       1)在运行时判断任意一个对象所属的类

      2)在运行时构造任意一个类的对象

      3)在运行时判断任意一个类所属的成员变量和方法

      4)在运行时调用类的任意方法

      5)生成动态代理

     

     

    三、为什么用

      一般情况下,我们使用一个事先知道的类或方法,如通过new方法获取对应对象。当某些类经常变化,或者不确定,或者编译期未知时,可以通过反射,在运行时获取该类的属性、方法,或者调用某些方法。

     

     

    四、Class(Java反射的起源)

       Class类是Java反射的起源,如果没有Class,就不能调用反射相关的api。

      在Java应用中,Class类的实例代表了classes和interfaces,也包括enum, annotation, array, 8种原生数据类型(byte, short, int, long, float, double, char, boolean)以及 void。Class类的构造器是私有的,意味着Class对象只能由JVM自动生成,每当class字节码被JVM加载或者defineClass()方法被调用时,Class对象就会由JVM自动生成。

      

    public final class Class<T> implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement {
    
    /*
         * Private constructor. Only the Java Virtual Machine creates Class objects.
         * This constructor is not used and prevents the default constructor being
         * generated.
         */
        private Class(ClassLoader loader) {
            // Initialize final field for classLoader.  The initialization value of non-null
            // prevents future JIT optimizations from assuming this final field is null.
            classLoader = loader;
        }
    
        ... ...
    }

     

     五、获取Class对象的途径

    package com.ttx.java.reflect;
    
    /**
     * 使用java中的反射
     * @author TimFruit
     * @date 18-9-23 下午9:06
     */
    public class TestReflect {
    
        //http://www.importnew.com/23902.html
        public static void main(String[] args) throws ClassNotFoundException {
            ClassPathway pathway=new ClassPathway();
            System.out.println(pathway.getClassByClass());   //==>  class com.ttx.java.reflect.ClassPathway
            System.out.println(pathway.getClassByGetClassMethod());   //==>  class com.ttx.java.reflect.ClassPathway
            System.out.println(pathway.getClassByGetSupperClassMethod());    //==>  class java.lang.Object
            System.out.println(pathway.getClassByForNameMethod());    //==>  class com.ttx.java.reflect.ClassPathway
        }
    
    }
    
    
    /**
     * 获取class对象的途径
     */
    class ClassPathway{
    
    
        Class getClassByClass(){
            return ClassPathway.class;
        }
    
    
        Class getClassByGetClassMethod(){//常用,由对象获取对应的类
            ClassPathway pathway=new ClassPathway();
            return pathway.getClass();
        }
    
    
        Class getClassByGetSupperClassMethod(){
            ClassPathway pathway=new ClassPathway();
            Class pathwayClazz=pathway.getClass();
            return pathwayClazz.getSuperclass();
        }
    
    
        Class getClassByForNameMethod() throws ClassNotFoundException {//常用,通过静态方法以及对应的类名获取
            return Class.forName("com.ttx.java.reflect.ClassPathway");
        }
    
    }

     六、反射可使用的api (怎样用)

     

    package com.ttx.java.reflect;
    
    import java.lang.annotation.Annotation;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * 使用反射中的api
     * @author TimFruit
     * @date 18-10-5 上午12:13
     */
    public class ClassAPITests {
    
        public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
            //反射的主要作用是运行时观察类的属性、方法,并且调用方法
    
            People tim=new People("tim");
            Class clazz=tim.getClass();
    
    
            //1.获取构造器 并构造实例
            constructInstance(clazz);                        // ==>  张三 - com.ttx.java.reflect.People@4f47d241
    
            //2.获取方法  并调用方法
            invokeMethod(clazz,"work",tim);      // ==>  tim正在工作...
    
            //3.识别标注的注解,调用对应的方法
            invokeMethod(clazz,InvokeMethod.class,tim);     // ==>  tim正在工作...
    
            //4.设置属性
            setProperty(clazz,tim,"name","ttx-new-name");
            System.out.println(tim.getName());              // ==>  ttx-new-name
    
    
            //5.
            methodsAndDeclaredMethodsDifferences(clazz);
            /*  ==>
    
            getMethods()...
            个数:12
            work | toString | getName | setName | wait | wait | wait | equals | hashCode | getClass | notify | notifyAll |
    
            getDeclaredMethods()...
            个数:5
            work | testMethod | toString | getName | setName |
             */
    
        }
    
    
        public static void constructInstance(Class targetClazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
            //1.获取构造器 并构造实例
            Constructor constructor=targetClazz.getConstructor(String.class);
            Object obj=constructor.newInstance("张三");//新建实例
            System.out.println(obj);
        }
    
    
        public static void invokeMethod(Class targetClazz,String methodName,Object invokeObj) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
            //2.获取方法  并调用方法
            Method workMethod=targetClazz.getMethod(methodName);
            workMethod.invoke(invokeObj);  //第一个参数为调用的对象   类似tim.work()
        }
    
    
        public static void invokeMethod(Class targetClazz, Class annotationClazz,Object invokeObj) throws InvocationTargetException, IllegalAccessException {
            //3.识别标注的注解,调用对应的方法
            Method[] methods=targetClazz.getMethods();
            for(Method method : methods){
                Annotation annotation=method.getAnnotation(annotationClazz);
                if(annotation!=null){
                    method.invoke(invokeObj);
                }
            }
        }
    
        public static void setProperty(Class targetClazz, Object targetObj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
            Field field=targetClazz.getDeclaredField(propertyName); //获取属性
    
            field.setAccessible(true); //设置私有(private)属性可以直接访问
            field.set(targetObj,value);
        }
    
    
        public static void methodsAndDeclaredMethodsDifferences(Class targetClazz){
    
            Method[] methods=targetClazz.getMethods();  //用于获取类所有public的方法,包括继承的方法
            System.out.println("
    getMethods()...");
            System.out.println("个数:"+methods.length);
            for(Method method: methods){
                System.out.print(method.getName() +" | ");
            }
    
            Method[] declaredMethods=targetClazz.getDeclaredMethods(); //用于获取自身类声明的方法,包括public, protected, private的方法
            System.out.println("
    getDeclaredMethods()...");
            System.out.println("个数:"+declaredMethods.length);
            for(Method method: declaredMethods){
                System.out.print(method.getName() +" | ");
            }
    
        }
    
    }

     

    public class People {
    
        private String name;
    
        public People() {
        }
    
        public People(String name) {
            this.name=name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @InvokeMethod
        public void work(){
            System.out.println(name+"正在工作...");
        }
    
        @Override
        public String toString() {
            return name+" - "+super.toString();
        }
    
    
        private void testMethod(){
            System.out.println("用于测试getMethods和getDeclaredMethods的区别");
        }
    
    }
    /**
     * 用于反射识别方法
     * @author TimFruit
     * @date 18-10-5 上午12:48
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface InvokeMethod {
    }

     

    学习资料:

      JAVA反射机制_百度百科

      Java反射机制

    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    07月26日总结
    07月25日总结
    07月24日总结
    07月23日总结
    07月22日总结
    07月20日总结
    07月19日总结
    spinlock in c++11 based on atomic_flag std::memory_order_acquire
    c++ nullptr
    C++11 新特性: unordered_map 与 map 的对比
  • 原文地址:https://www.cnblogs.com/timfruit/p/9693932.html
Copyright © 2011-2022 走看看