精华内容
下载资源
问答
  • 什么是反射以及反射作用

    千次阅读 2019-02-15 17:40:18
    什么是反射?  每个类都有对应的类对象,该类对象包含该类的属性方法等信息,这个类对象就是这个类的反射。  获取类对象有以下三种方法: //用户类 package com.demo.springbootdemo; /** * @ClassName: ...

    不对的地方,希望大佬指正。

    什么是反射?

             每个类都有对应的类对象,该类对象包含该类的属性方法等信息,这个类对象就是这个类的反射。

            获取类对象有以下三种方法:

    //用户类
    package com.demo.springbootdemo;
    
    /**
     * @ClassName: User
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:03
     * @Version: 1.0
     */
    public class User {
        public String username;
        public String password;
    
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        public void say() {
            System.out.println("我的用户名:" + username + ",我的密码:" + password);
        }
    
        public void setUsername(String username){
            this.username = username;
        }
    }
    
    //获取类对象
    package com.demo.springbootdemo;
    
    /**
     * @ClassName: Test08
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:02
     * @Version: 1.0
     */
    public class Test08 {
        public static void main(String[] args) throws Exception {
            //第一种
            Class a = Class.forName("com.demo.springbootdemo.User");
            //第二种
            Class b = User.class;
            //第三种
            Class c = new User().getClass();
            //类对象有且只有一个,因此a,b,c三个是相等的,还有一个注意的点是,如果类中包含静态代码块,那么除了User.class这种方法外的另外两种方法,都会造成静态代码块的执行,且只执行一次
        }
    }

    反射的作用?

             1、用来创建对象

    package com.demo.springbootdemo;
    
    import java.lang.reflect.Constructor;
    
    /**
     * @ClassName: Test08
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:02
     * @Version: 1.0
     */
    public class Test08 {
        public static void main(String[] args) throws Exception {
            Class a = Class.forName("com.demo.springbootdemo.User");
            //参数是构造器中的参数类型
            Constructor constructor = a.getConstructor(String.class, String.class);
            //参数类型和数量要与构造器一致
            User user = (User) constructor.newInstance("admin", "123");
            user.say();
        }
    }

             2、用来访问属性

    package com.demo.springbootdemo;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    
    /**
     * @ClassName: Test08
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:02
     * @Version: 1.0
     */
    public class Test08 {
        public static void main(String[] args) throws Exception {
            Class a = Class.forName("com.demo.springbootdemo.User");
            Constructor constructor = a.getConstructor(String.class, String.class);
            User user = (User) constructor.newInstance("admin", "123");
            user.say();
            Field field = user.getClass().getField("username");
            field.set(user, "sysadmin");
            user.say();
        }
    }
    

             3、用来访问方法

    package com.demo.springbootdemo;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    
    /**
     * @ClassName: Test08
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:02
     * @Version: 1.0
     */
    public class Test08 {
        public static void main(String[] args) throws Exception {
            Class a = Class.forName("com.demo.springbootdemo.User");
            Constructor constructor = a.getConstructor(String.class, String.class);
            User user = (User) constructor.newInstance("admin", "123");
            Method method = user.getClass().getMethod("say");
            method.invoke(user);
            user.getClass().getMethod("setUsername", String.class).invoke(user,"test");
            method.invoke(user);
        }
    }

    实际应用

            前面的例子看着好像反射没什么用,实际反射是下面这么用的,通过修改配置文件,可以在不修改原程序的情况下,分别对不同的类进行访问处理

    //我有两个服务类
    //第一个
    package com.demo.springbootdemo;
    
    /**
     * @ClassName: Service1
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:31
     * @Version: 1.0
     */
    public class Service1 {
        public void say(){
            System.out.println("i am service1");
        }
    }
    
    //第二个
    package com.demo.springbootdemo;
    
    /**
     * @ClassName: Service2
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 17:31
     * @Version: 1.0
     */
    public class Service2 {
        public void doSomething(){
            System.out.println("i am service2,i will doSomething");
        }
    }
    
    
    //然后通过反射写个main方法,这个方法中没有出现这两个服务类的任何信息,只出现了一个配置文件
    package com.demo.springbootdemo;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Method;
    import java.util.Properties;
    
    /**
     * @ClassName: Test07
     * @Author: zhanghongkai
     * @Date: Create in 2019/2/15 14:38
     * @Version: 1.0
     */
    public class Test07 {
        public static void main(String[] args) throws Exception {
            File file = new File("F:/prop.txt");
            Properties properties = new Properties();
            properties.load(new FileInputStream(file));
            String classKey = properties.getProperty("class");
            String methodKey = properties.getProperty("method");
            Class<?> c = Class.forName(classKey);
            Constructor<?> constructor = c.getConstructor();
            Object object = constructor.newInstance();
            Method method = c.getMethod(methodKey);
            method.invoke(object);
        }
    }
    
    //配置文件如下
    class = com.demo.springbootdemo.Service2
    method = doSomething

     

    展开全文
  • 定义 反射机制是Java语言中一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许其对内部成员进行操作。由于反射机制能够实现在运行时对类进行装载,因此能够增加程序...反射机制的作用: 1,反编译:.c...

    定义
    反射机制是Java语言中一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许其对内部成员进行操作。由于反射机制能够实现在运行时对类进行装载,因此能够增加程序的灵活性,但是不恰当地使用反射机制,也会严重影响系统的性能。
    具体而言,反射机制的主要功能主要有:①得到一个对象所属的类,②获取一个类的所有成员变量和方法,③在运行时创建对象,调用对象的方法。

    反射机制的作用:
    1,反编译:.class–>.java
    2,通过反射机制访问java对象的属性,方法,构造方法等;

    先看一下sun为我们提供了那些反射机制中的类:
    java.lang.Class;
    java.lang.reflect.Constructor; java.lang.reflect.Field;
    java.lang.reflect.Method;
    java.lang.reflect.Modifier;

    很多反射中的方法,属性等操作我们可以从这四个类中查询。还是哪句话要学着不断的查询API,那才是我们最好的老师。

    Class c=Class.forName(“Employee”);
    Object o=c.newInstance(); 调用了Employee的无参数构造方法

    方法关键字
    getDeclareMethods() 获得所有的方法
    getReturnType() 获得方法的返回类型
    getParameterTypes() 获得属性的传入参数类型

    构造方法关键字
    getDeclaredConstructors() 获得所有的构造方法
    getDeclaredConstructor(参数类型.class,……) 获得特定的构造方法

    父类和父接口
    getSuperclass() 获取某类的父类
    getInterfaces() 获取某类实现的接口
    这样我们就可以获得类的各种内容,从而进行反编译
    反射机制获取类的方法有三种,我们分别展示如何获取Reflection包下的Student类

    Class.forName(“类的路径”)
    Class Student = Class.forName(“Reflection.Student”); //包名+类名
    类名.class
    Class Student = Reflection.Student.class;
    类实例.getClass()
    Student student = new Student(); Class Student =student.getClass();

    Class类中的6个重要方法
    1.getName()方法,返回一个String字符串,显示该类的名称。
    1.System.out.println(Student.getName()); //输出: Reflection.Student
    2.newInstance()方法, 由类调用该方法,根据该类的默认构造函数创建类的实例
    Object o = Student.newInstance();
    3.getClassLoader()方法,返回该类对象的对应的加载器。

    4.getComponentType()方法,返回类的组件类型的数组,如果这个类并不代表一个数组类,此方法返回null。
    5.getSuperClass()方法,返回某子类所对应的直接父类所对应的Class对象。
    6.isArray()方法,判定此Class对象所对应的是否是一个数组对象。

    反射机制获取类的方法
    获取类的构造方法
    getDeclaredConstructors() //获取类的所有构造方法
    getDeclaredConstructor(参数类型.class,……) //获取特定的构造方法

    获取类的普通方法
    getDeclaredMethods() //获取所有普通方法
    getDeclaredMethod(“方法名”,参数类型.class,……) //获取指定名称的方法
    getReturnType() //获取方法的返回类型
    getParameterTypes() //获得方法的传入参数类型

    new 创建对象,是静态加载类,在编译时刻就需要加载所有可能使用到的类

    通过动态加载类可以解决该问题。通过类类型创建该类的对象
    1、静态加载类,是编译时刻加载;动态加载类,是运行时刻加载
    2、new创建对象:是静态加载类,在编译时刻就需要加载所有的【可能使用到的类】。有一个类有问题(如不存在),都不能通过编译,会报错。
    3、Class.forName()通过动态加载类,可以用到一个类时,才进行加载。

    展开全文
  • JAVA反射机制作用什么

    万次阅读 多人点赞 2015-10-30 21:10:39
    那么什么是Java的反射呢?  大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了

    转自这里

    Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。

    那么什么是Java的反射呢?

           大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。

    Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射。

    那么Java反射有什么作用呢?

    假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。

    Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。

    Class类

           要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。

    反射API

           u反射API用于反应在当前Java虚拟机中的类、接口或者对象信息

    u功能
    —获取一个对象的类信息.

           —获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息.

           —检获属于一个接口的常量和方法声明.

           —创建一个直到程序运行期间才知道名字的类的实例.

           —获取并设置一个对象的成员,甚至这个成员的名字是
       在程序运行期间才知道.

           —检测一个在运行期间才知道名字的对象的方法

           利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信息进行检测。当然这种检测在对运行的性能上会有些减弱,所以什么时候使用反射,就要靠业务的需求、大小,以及经验的积累来决定。

           那么如何利用反射API在运行的时候知道一个类的信息呢?

    代码示例:

    [java]  view plain copy
    1. <span style="font-size:16px;">import java.lang.reflect.Field;  
    2. import java.lang.reflect.Method;  
    3. import javax.swing.JOptionPane;  
    4. /** 
    5.   *本类用于测试反射API,利用用户输入类的全路径, 
    6. *找到该类所有的成员方法和成员属性 
    7.   */  
    8. public class MyTest {  
    9.      /** 
    10.      *构造方法 
    11.      */  
    12.     public MyTest(){  
    13.        String classInfo=JOptionPane.showInputDialog(null,"输入类全路径");//要求用户输入类的全路径  
    14.        try {  
    15.            Class cla=Class.forName(classInfo);//根据类的全路径进行类加载,返回该类的Class对象  
    16.             
    17.            Method[] method=cla.getDeclaredMethods();//利用得到的Class对象的自审,返回方法对象集合  
    18.             
    19.            for(Method me:method){//遍历该类方法的集合  
    20.               System.out.println(me.toString());//打印方法信息  
    21.            }  
    22.             
    23.            System.out.println("********");  
    24.             
    25.            Field[] field=cla.getDeclaredFields();//利用得到的Class对象的自审,返回属性对象集合  
    26.            for(Field me:field){ //遍历该类属性的集合  
    27.               System.out.println(me.toString());//打印属性信息  
    28.            }  
    29.        } catch (ClassNotFoundException e) {  
    30.            e.printStackTrace();  
    31.        }  
    32.     }  
    33.     public static void main(String[] args) {  
    34.        new MyTest();  
    35.     }  
    36. }</span>  

    运行的时候,我们输入javax.swing.JFrame,那么运行结果如下:

    public void javax.swing.JFrame.remove(java.awt.Component)

    public void javax.swing.JFrame.update(java.awt.Graphics)

    …………

    ********

    public static final int javax.swing.JFrame.EXIT_ON_CLOSE

    private int javax.swing.JFrame.defaultCloseOperation

    …………

        大家可以发现,类的全路径是在程序运行的时候,由用户输入的。所以虚拟机事先并不知道所要加载类的信息,这就是利用反射机制来对用户输入的类全路径来对类自身的一个自审。从而探知该类所拥有的方法和属性。

    通过上面代码,大家可以知道编译工具为什么能够一按点就能列出用户当前对象的属性和方法了。它是先获得用户输入对象的字符串,然后利用反射原理来对这样的类进行自审,从而列出该类的方法和属性。

    使用反射机制的步骤:

    u导入java.lang.relfect 包

    u遵循三个步骤
    第一步是获得你想操作的类的 java.lang.Class 对象
    第二步是调用诸如 getDeclaredMethods 的方法
    第三步使用 反射API 来操作这些信息

    获得Class对象的方法

    u如果一个类的实例已经得到,你可以使用

           【Class c = 对象名.getClass(); 

          例: TextField t = new TextField();

                  Class c = t.getClass();

                  Class s = c.getSuperclass();

    u如果你在编译期知道类的名字,你可以使用如下的方法

    Class c = java.awt.Button.class; 
    或者

             Class c = Integer.TYPE;

    u如果类名在编译期不知道, 但是在运行期可以获得, 你可以使用下面的方法

              Class c = Class.forName(strg);

       这样获得Class类对象的方法,其实是利用反射API把指定字符串的类加载到内存中,所以也叫类加载器加载方法。这样的话,它会把该类的静态方法和静态属性,以及静态代码全部加载到内存中。但这时候,对象还没有产生。所以为什么静态方法不能访问非静态属性和方法。因为静态方法和属性产生的时机在非静态属性和方法之前。

    代码示例:

    [java]  view plain copy
    1. <span style="font-size:16px;">package  com;  
    2.    
    3. public class MyTest {  
    4.     public static void main(String[] args) {  
    5.        TestOne  one=null;  
    6.        try{  
    7.        Class  cla=Class.forName("com.TestOne");//进行com.TestOne类加载,返回一个Class对象  
    8.        System.out.println("********");  
    9.        one=(TestOne)cla.newInstance();//产生这个Class类对象的一个实例,调用该类无参的构造方法,作用等同于new TestOne()  
    10.        }catch(Exception e){  
    11.            e.printStackTrace();  
    12.        }  
    13.        TestOne two=new TestOne();  
    14.   System.out.println(one.getClass() == two.getClass());//比较两个TestOne对象的Class对象是否是同一个对象,在这里结果是true。说明如果两个对象的类型相同,那么它们会有相同的Class对象  
    15.     }  
    16. }  
    17.    
    18. class TestOne{  
    19.     static{  
    20.        System.out.println("静态代码块运行");  
    21.     }  
    22.     TestOne(){  
    23.        System.out.println("构造方法");  
    24.     }  
    25. }</span>  

      以上代码过行的结果是:

    静态代码块运行

    ***********

    构造方法

    构造方法


    代码分析:

    在进行Class.forName("com.TestOne")的时候,实际上是对com.TestOne进行类加载,这时候,会把静态属性、方法以及静态代码块都加载到内存中。所以这时候会打印出"静态代码块运行"。但这时候,对象却还没有产生。所以"构造方法"这几个字不会打印。当执行cla.newInstance()的时候,就是利用反射机制将Class对象生成一个该类的一个实例。这时候对象就产生了。所以打印"构造方法"。当执行到TestOne two=new TestOne()语句时,又生成了一个对象。但这时候类已经加载完毕,静态的东西已经加载到内存中,而静态代码块只执行一次,所以不用再去加载类,所以只会打印"构造方法",而"静态代码块运行"不会打印。

    反射机制不但可以例出该类对象所拥有的方法和属性,还可以获得该类的构造方法及通过构造方法获得实例。也可以动态的调用这个实例的成员方法。

    代码示例:

    [java]  view plain copy
    1. <span style="font-size:16px;">package reflect;  
    2.    
    3. import java.lang.reflect.Constructor;  
    4.    
    5.    
    6. /** 
    7.  * 
    8.  * 本类测试反射获得类的构造器对象, 
    9.  * 并通过类构造器对象生成该类的实例 
    10.  * 
    11.  */  
    12. public class ConstructorTest {  
    13.    
    14.     public static void main(String[] args) {  
    15.        try {  
    16.            //获得指定字符串类对象  
    17.            Class cla=Class.forName("reflect.Tests");  
    18.            //设置Class对象数组,用于指定构造方法类型  
    19.            Class[] cl=new Class[]{int.class,int.class};  
    20.             
    21.            //获得Constructor构造器对象。并指定构造方法类型  
    22.            Constructor con=cla.getConstructor(cl);  
    23.             
    24.            //给传入参数赋初值  
    25.            Object[] x={new Integer(33),new Integer(67)};  
    26.             
    27.            //得到实例  
    28.            Object obj=con.newInstance(x);  
    29.        } catch (Exception e) {  
    30.            e.printStackTrace();  
    31.        }  
    32.     }  
    33.    
    34. }  
    35.    
    36. class Tests{  
    37.     public Tests(int x,int y){  
    38.        System.out.println(x+"    "+y);  
    39.     }  
    40. }</span>  

    运行的结果是” 33    67。说明我们已经生成了Tests这个类的一个对象。 


    三、Java类反射中所必须的类:
    Java的类反射所需要的类并不多,它们分别是:Field、Constructor、Method、Class、Object,下面我将对这些类做一个简单的说明。
    Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。
    Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。
    Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
    Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
    Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

    四、Java的反射类能做什么:
    看完上面的这么多我想你已经不耐烦了,你以为我在浪费你的时间,那么好吧!下面我们就用一些简单的小例子来说明它。
    首先我们来看一下通过Java的反射机制我们能得到些什么。
    首先我们来写一个类:

    java 代码
     
    1. import  java.awt.event.ActionListener;  
    2. import  java.awt.event.ActionEvent;  
    3. class  A  extends  Object  implements  ActionListener{  
    4. private   int  a =  3 ;  
    5. public  Integer b =  new  Integer( 4 );  
    6. public  A(){}  
    7. public  A( int  id,String name){}  
    8. public   int  abc( int  id,String name){ return   0 ;}  
    9. public   void  actionPerformed(ActionEvent e){}  
    10. }  


    你可能被我这个类弄糊涂了,你看不出我要做什么,那就不要看这个类了,这个类是用来测试的,你知道知道它继承了Object类,有一个接口是ActionListener,两个属性int和Integer,两个构造方法和两个方法,这就足够了。
    下面我们把A这个类作为一个反射类,来过去A类中的一些信息,首先我们先来过去一下反射类中的属性和属性值。

    java 代码
     
    1. import  java.lang.reflect.*;  
    2. class  B{  
    3. public   static   void  main(String args[]){  
    4. A r = new  A();  
    5. Class temp = r.getClass();  
    6. try {  
    7. System.out.println("反射类中所有公有的属性" );  
    8. Field[] fb =temp.getFields();  
    9. for ( int  j= 0 ;j<fb.length;j++){  
    10. Class cl = fb[j].getType();  
    11. System.out.println("fb:" +cl);  
    12. }  
    13.   
    14. System.out.println("反射类中所有的属性" );  
    15. Field[] fa = temp.getDeclaredFields();  
    16. for ( int  j= 0 ;j<fa.length;j++){  
    17. Class cl = fa[j].getType();  
    18. System.out.println("fa:" +cl);  
    19. }  
    20. System.out.println("反射类中私有属性的值" );  
    21. Field f = temp.getDeclaredField("a" );  
    22. f.setAccessible(true );  
    23. Integer i = (Integer)f.get(r);  
    24. System.out.println(i);  
    25. }catch (Exception e){  
    26. e.printStackTrace();  
    27. }  
    28. }  
    29.   
    30. }   


    这里用到了两个方法,getFields()、getDeclaredFields(),它们分别是用来获取反射类中所有公有属性和反射类中所有的属性的方法。另外还有getField(String)和getDeclaredField(String)方法都是用来过去反射类中指定的属性的方法,要注意的是getField方法只能取到反射类中公有的属性,而getDeclaredField方法都能取到。
    这里还用到了Field 类的setAccessible方法,它是用来设置是否有权限访问反射类中的私有属性的,只有设置为true时才可以访问,默认为false。另外 Field类还有set(Object AttributeName,Object value)方法,可以改变指定属性的值。

    下面我们来看一下如何获取反射类中的构造方法

    java 代码
     
    1. import  java.lang.reflect.*;  
    2. public   class  SampleConstructor {  
    3. public   static   void  main(String[] args) {  
    4. A r = new  A();  
    5. printConstructors(r);  
    6. }  
    7.   
    8. public   static   void  printConstructors(A r) {  
    9. Class c = r.getClass();  
    10. //获取指定类的类名   
    11. String className = c.getName();  
    12. try  {  
    13. //获取指定类的构造方法   
    14. Constructor[] theConstructors = c.getConstructors();  
    15. for ( int  i= 0 ; i<theConstructors.length; i++) {  
    16. //获取指定构造方法的参数的集合   
    17. Class[] parameterTypes = theConstructors[i].getParameterTypes();  
    18.   
    19. System.out.print(className + "(" );  
    20.   
    21. for ( int  j= 0 ; j<parameterTypes.length; j++)  
    22. System.out.print(parameterTypes[j].getName() + " " );  
    23.   
    24. System.out.println(")" );  
    25.   
    26. }  
    27. }catch (Exception e) {  
    28. e.printStackTrace();  
    29. }  
    30. }  
    31. }  

    这个例子很简单,只是用getConstructors()方法获取了反射类的构造方法的集合,并用Constructor类的getParameterTypes()获取该构造方法的参数。

    下面我们再来获取一下反射类的父类(超类)和接口

    java 代码
     
    1. import  java.io.*;  
    2. import  java.lang.reflect.*;  
    3.   
    4. public   class  SampleInterface {  
    5. public   static   void  main(String[] args)  throws  Exception {  
    6. A raf = new  A();  
    7. printInterfaceNames(raf);  
    8. }  
    9.   
    10. public   static   void  printInterfaceNames(Object o) {  
    11. Class c = o.getClass();  
    12. //获取反射类的接口   
    13. Class[] theInterfaces = c.getInterfaces();  
    14. for ( int  i= 0 ; i<theInterfaces.length; i++)  
    15. System.out.println(theInterfaces[i].getName());  
    16. //获取反射类的父类(超类)   
    17. Class theSuperclass = c.getSuperclass();  
    18. System.out.println(theSuperclass.getName());  
    19. }  
    20. }  


    这个例子也很简单,只是用Class类的getInterfaces()方法获取反射类的所有接口,由于接口可以有多个,所以它返回一个 Class数组。用getSuperclass()方法来获取反射类的父类(超类),由于一个类只能继承自一个类,所以它返回一个Class对象。

    下面我们来获取一下反射类的方法

    java 代码
     
    1. import  java.lang.reflect.*;  
    2. public   class  SampleMethod {  
    3.   
    4. public   static   void  main(String[] args) {  
    5. A p = new  A();  
    6. printMethods(p);  
    7. }  
    8.   
    9. public   static   void  printMethods(Object o) {  
    10. Class c = o.getClass();  
    11. String className = c.getName();  
    12. Method[] m = c.getMethods();  
    13. for ( int  i= 0 ; i<m.length; i++) {  
    14. //输出方法的返回类型   
    15. System.out.print(m[i].getReturnType().getName());  
    16. //输出方法名   
    17. System.out.print(" " +m[i].getName()+ "(" );  
    18. //获取方法的参数   
    19. Class[] parameterTypes = m[i].getParameterTypes();  
    20. for ( int  j= 0 ; j<parameterTypes.length; j++){  
    21. System.out.print(parameterTypes[j].getName());  
    22. if (parameterTypes.length>j+ 1 ){  
    23. System.out.print("," );  
    24. }  
    25. }  
    26.   
    27. System.out.println(")" );  
    28. }  
    29.   
    30. }  
    31.   
    32. }  


    这个例子并不难,它只是获得了反射类的所有方法,包括继承自它父类的方法。然后获取方法的返回类型、方法名和方法参数。

    接下来让我们回过头来想一想,我们获取了反射类的属性、构造方法、父类、接口和方法,可这些东西能帮我们做些什么呢!!
    下面我写一个比较完整的小例子,来说明Java的反射类能做些什么吧!!

    java 代码
     
    1. import  java.lang.reflect.Constructor;  
    2. import  java.lang.reflect.Method;  
    3.   
    4. public   class  LoadMethod {  
    5. public  Object Load(String cName,String MethodName,String[] type,String[] param){  
    6. Object retobj = null ;  
    7. try  {  
    8. //加载指定的Java类   
    9. Class cls = Class.forName(cName);  
    10.   
    11. //获取指定对象的实例   
    12. Constructor ct = cls.getConstructor(null );  
    13. Object obj = ct.newInstance(null );  
    14.   
    15. //构建方法参数的数据类型   
    16. Class partypes[] = this .getMethodClass(type);  
    17.   
    18. //在指定类中获取指定的方法   
    19. Method meth = cls.getMethod(MethodName, partypes);  
    20.   
    21. //构建方法的参数值   
    22. Object arglist[] = this .getMethodObject(type,param);  
    23.   
    24. //调用指定的方法并获取返回值为Object类型   
    25. retobj= meth.invoke(obj, arglist);  
    26.   
    27. }  
    28. catch  (Throwable e) {  
    29. System.err.println(e);  
    30. }  
    31. return  retobj;  
    32. }  
    33.   
    34. //获取参数类型Class[]的方法   
    35. public  Class[] getMethodClass(String[] type){  
    36. Class[] cs = new  Class[type.length];  
    37. for  ( int  i =  0 ; i < cs.length; i++) {  
    38. if (!type[i].trim().equals( "" )||type[i]!= null ){  
    39. if (type[i].equals( "int" )||type[i].equals( "Integer" )){  
    40. cs[i]=Integer.TYPE;  
    41. }else   if (type[i].equals( "float" )||type[i].equals( "Float" )){  
    42. cs[i]=Float.TYPE;  
    43. }else   if (type[i].equals( "double" )||type[i].equals( "Double" )){  
    44. cs[i]=Double.TYPE;  
    45. }else   if (type[i].equals( "boolean" )||type[i].equals( "Boolean" )){  
    46. cs[i]=Boolean.TYPE;  
    47. }else {  
    48. cs[i]=String.class ;  
    49. }  
    50. }  
    51. }  
    52. return  cs;  
    53. }  
    54.   
    55. //获取参数Object[]的方法   
    56. public  Object[] getMethodObject(String[] type,String[] param){  
    57. Object[] obj = new  Object[param.length];  
    58. for  ( int  i =  0 ; i < obj.length; i++) {  
    59. if (!param[i].trim().equals( "" )||param[i]!= null ){  
    60. if (type[i].equals( "int" )||type[i].equals( "Integer" )){  
    61. obj[i]= new  Integer(param[i]);  
    62. }else   if (type[i].equals( "float" )||type[i].equals( "Float" )){  
    63. obj[i]= new  Float(param[i]);  
    64. }else   if (type[i].equals( "double" )||type[i].equals( "Double" )){  
    65. obj[i]= new  Double(param[i]);  
    66. }else   if (type[i].equals( "boolean" )||type[i].equals( "Boolean" )){  
    67. obj[i]=new  Boolean(param[i]);  
    68. }else {  
    69. obj[i] = param[i];  
    70. }  
    71. }  
    72. }  
    73. return  obj;  
    74. }  
    75. }  


    这是我在工作中写的一个实现Java在运行时加载指定的类,并调用指定方法的一个小例子。这里没有main方法,你可以自己写一个。
    Load方法接收的五个参数分别是,Java的类名,方法名,参数的类型和参数的值。


          Java中反射机制使用的还是比较广泛的,系统的灵活性、可扩展性大都都是通过反射等方式来加载外部插件,使得系统与插件解耦的同时,增加了功能。但是很多人都只是会用,却是不知道它的实现机制,今天就由我来带大家揭开反射机制的神秘面纱。

           Java中是用Class.forName(classname)来反射类。


    1. package com.java.reflecttest;  
    2.   
    3. import com.java.dbtest.DBTest;  
    4.   
    5.   
    6. /** 
    7.  * Java反射机制测试 
    8.  * @author Longxuan 
    9.  * 
    10.  */  
    11. public class ReflectTest {  
    12.   
    13.     /** 
    14.      * 测试反射类 
    15.      */  
    16.     public static void refTest(){  
    17.         String className = "com.java.dbtest.TestConnection";  
    18.         DBTest dbTest = null;  
    19.         try {  
    20.               
    21.             //通过反射机制,使用类装载器,装载该类  
    22.             Class tc = Class.forName(className);  
    23.               
    24.             //输出反射得到的类  
    25.             System.out.println(tc);  
    26.               
    27.             //创建该类的实例,转化为接口  
    28.             dbTest =(DBTest)tc.newInstance();  
    29.               
    30.             //通过接口,调用该类的方法  
    31.             dbTest.SelectUser();  
    32.               
    33.         } catch (ClassNotFoundException e) {  
    34.             e.printStackTrace();  
    35.         } catch (InstantiationException e) {  
    36.             e.printStackTrace();  
    37.         } catch (IllegalAccessException e) {  
    38.             e.printStackTrace();  
    39.         }  
    40.           
    41.     }  
    42.       
    43.     public static void main(String[] args){  
    44.         refTest();  
    45.     }  
    46. }  


           通过main函数的调试,已经通过,结果如图:

           

           经过调试,查资料,结合自己的推测和理解,似乎是明白了一些。现与大家分享讨论。

           先说执行过程:

           Class.forName(classname)方法,实际上是调用了Class类中的 Class.forName(classname, true, currentLoader)方法。参数:name - 所需类的完全限定名;initialize - 是否必须初始化类;loader - 用于加载类的类加载器。currentLoader则是通过调用ClassLoader.getCallerClassLoader()获取当前类加载器的。类要想使用,必须用类加载器加载,所以需要加载器。反射机制,不是每次都去重新反射,而是提供了cache,每次都会需要类加载器去自己的cache中查找,如果可以查到,则直接返回该类。


           有意思的是java的类加载器也有些门道。它分为BootStrap Class Loader(引导类加载器),Extensions Class Loader (扩展类加载器),App ClassLoader(或System Class Loader),当然少不了Custom ClassLoader(用户自定义类加载器)。其加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。类加载器的详细介绍会在接下来的博文中较深入的分析,欢迎期待。


           forName方法中,调用了ClassLoader.loadClass方法来完成类的反射。根据类加载器的特殊性,结合我的调试过程,画了一个简单的流程图,



           我的这幅图简单的说明了类加载器的类加载过程。先检查自己是否已经加载过该类,如果加载过,则直接返回该类,若没有则调用父类的loadClass方法,如果父类中没有,则执行findClass方法去尝试加载此类,也就是我们通常所理解的片面的"反射"了。这个过程主要通过ClassLoader.defineClass方法来完成。defineClass 方法将一个字节数组转换为 Class 类的实例(任何类的对象都是Class类的对象)。这种新定义的类的实例需要使用 Class.newInstance 来创建,而不能使用new来实例化。

     

          为什么说“任何类的对象都是Class类的对象”呢?在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类(.java文件),编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。


           其实说的简单通俗一点,就是在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。


           以上内容是我经过调试、查java Api和网上资料,结合自己的理解,与大家分享讨论的,如果有错,欢迎大家指正,我们共同进步。


    展开全文
  • 什么是反射机制,有什么作用

    千次阅读 2017-08-06 22:27:32
    1. 反射机制定义反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。在Java环境中,反射机制允许程序在...2. 反射机制的作用Java反射机制主要用于实现以下功能。(1

    1. 反射机制定义

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。

    在Java环境中,反射机制允许程序在执行时获取某个类自身的定义信息,例如熟悉和方法等也可以实现动态创建类的对象、变更属性的内容或执行特定的方法的功能。从而使Java具有动态语言的特性,增强了程序的灵活性和可移植性。

    2. 反射机制的作用

    Java反射机制主要用于实现以下功能。

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

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

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

    (4)在运行时调用任意一个对象的方法,甚至可以调用private方法。

    注意:上述功能都是在运行时环境中,而不是在编译时环境中。

    3. Java反射机制API

    实现Java反射机制的API在Java.lang.reflect包下,具有以下几点。

    (1)Class类:代表一个类。

    (2)Filed类:代表类的成员变量。

    (3)Method类:代表类的方法。

    (4)Constructor类:代表类的构造方法。

    (5)Array类:提供了动态创建数组及访问数组元素的静态方法。该类中的所有方法都是静态的。

    4. 应用示例

    (1)根据类名获取类中定义的所有属性和方法,实例代码如下:

    package day0105;  
    
    import java.lang.reflect.Array;  
    import java.lang.reflect.Field;  
    import java.lang.reflect.Method;  
    
    
    public class Reflect {  
        /** 
         *  
         *打印出String类所有的属性和方法 
         */  
        public void test1(){  
            Class c = String.class;  
            Method[] methods = c.getMethods();  
            for(int i = 0;i<methods.length;i++){  
                System.out.println(methods[i].getName());  
            }  
            Field[] fields = c.getFields();  
            for(Field f : fields){  
                System.out.println(f.getType()+":"+f.getName());  
            }  
        }  
    
        /** 
         * 根据类名动态创建类的对象 
         * @throws Exception 
         */  
        public void test2() throws Exception{  
            Class c = Class.forName("day0105.Student");  
            Student student = (Student)c.newInstance();  
            student.setName("java");  
            student.setId("1001");  
            student.show();  
        }  
    
        /** 
         * 根据类名和方法名,执行对象的方法 
         * @param student 
         * @param method 
         * @param value 
         * @throws Exception 
         */  
        public void test3(Student student,String method,String value) throws Exception{  
            String s1 = method.substring(0,1).toUpperCase();  
            String s2 = method.substring(1);  
            String m = "set"+s1+s2;  
            System.out.println(m);  
            Class c = student.getClass();  
            Method set = c.getMethod(m,new Class[]{String.class});  
            set.invoke(student,new Object[]{value});  
        }  
    
        /** 
         * 动态创建数组对象,对数组元素复制和取值 
         */  
        public void test4(){  
            try{  
                Class cls = Class.forName("java.lang.String");  
                //创建一个String类型的数组,大小为10  
                Object arr = Array.newInstance(cls, 10);  
                //在数组5索引的位置赋值  
                Array.set(arr, 5, "this is a test");  
                //获取数组5索引位置的值  
                String s = (String)Array.get(arr, 5);  
                System.out.println(s);  
            }catch(Throwable e){  
                System.out.println(e);  
            }  
        }  
    } 

    Student类的定义如下

    package day0105;  
    
    public class Student {  
        private String id;  
    
        private String name;  
    
        public String getId() {  
            return id;  
        }  
    
        public void setId(String id) {  
            this.id = id;  
        }  
    
        public String getName() {  
            return name;  
        }  
    
        public void setName(String name) {  
            this.name = name;  
        }  
    
        public void show(){  
            System.out.println(id+":"+name);  
        }  
    }  

    Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象,
    无需提前硬编码目标类。这些特性使得反射特别适用于创建以普通方式与对象协作的库。
    反射在性能方面会有一定的损耗,用于字段和方法接入时反射要远慢于直接写代码。如果它作为程序
    运行中相对很少涉及的部分将不会造成影响,因为即使测试最坏情况下的计时图显示的反射操作也只耗用几微秒。

    展开全文
  • 反射

    千次阅读 多人点赞 2019-07-14 20:30:55
    什么是反射反射的优点反射的缺点2. 类类3.一切反射相关的代码都从获得java.lang.Class类对象开始4. 反射三大作用(java.lang.reflect.*)4.1获取类对象的三种方式4.2反射实例化对象4.3 反射动态调用方法4.4 反射读写...
  • 最近在学java反射以及动态代理,好多博客都写的十分官方。就自己整合些资料。加深java反射机制的理解。 在说反射之前,我们要先了解动态语言和静态语言的概念: 动态类型语言 所谓动态类型语言,就是类型的检查是在...
  • 请说明一下JAVA中反射的实现过程和作用分别是什么? Java语言编译后形成.class文件,反射就是通过字节码文件找到一个类,类中的方法及属性等。反射的实现主要通过四个类 Class 类的对象 Constructor 类的构造方法 ...
  • 反射作用及意义

    2020-11-05 08:51:28
    1.反射的定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为java语言的反射...
  • JAVA语言编译之后会生成一个.class文件,反射就是通过字节码文件找到某一个类...作用反射机制指的是程序在运行时能够获取自身的信息。在JAVA中,只要给定类的名字,那么就可以通过反射机制来获取类的所有信息。 ...
  • ava Java 基础这部分一些简单的问题就直接没有放上来。 需要资料的朋友麻烦一键三连之后点此免费获取! 基础: Java 反射?...什么是类加载? 何时类加载? java的类加载流程? 知道哪些类加载器。类
  • 什么是反射?什么Java反射

    万次阅读 2018-06-11 22:16:31
    什么是反射(Reflection )?主要是指程序可以访问、检测和修改它本身状态或行为的一种能力Java反射?在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一...
  • 简述什么是反射以及反射的使用

    千次阅读 2020-08-09 14:24:36
    什么是反射 在了解反射之前我们需要先简单来了解一下类加载的过程 在类加载的过程中,第一步JVM(JAVA虚拟机)将A.class文件读入内存方法区,第二步JVM为A.class创建唯一的Class类的对象,而Class对象是后面访问...
  • 反射什么?有什么用?

    千次阅读 2020-02-06 11:04:47
    今天想来总结一下反射什么?以及如何使用? 概念:  在Java里面一个类有两种状态,它们分别是编译和运行状态,通常我们需要获取这个类的信息都是在编译阶段获得的,也就是直接点出来或者new出来,可是如果需要...
  • 在本篇文章里小编给大家整理的是关于java反射作用知识点总结,需要的朋友们可以学习下。
  • 大佬,到底什么是Java的反射

    万次阅读 多人点赞 2020-08-06 23:23:05
    什么是反射 JAVA反射机制是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法;对于任何一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射...
  • java反射的原理,作用

    万次阅读 多人点赞 2018-10-17 14:31:44
    什么是反射反射原理 Java反射的原理:java类的执行需要经历以下过程, 编译:.java文件编译后生成.class字节码文件 加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时...
  • java反射作用与意义

    万次阅读 2018-08-23 13:38:08
    2、反射作用:通过反射可以使程序代码访问装载到JVM 中的类的内部信息 获取已装载类的成员变量信息 获取已装载类的方法 获取已装载类的构造方法信息     常用方法: getName()获得类的完整名字 get...
  • 什么是Java的反射机制

    千次阅读 2018-05-24 20:37:58
    Java反射机制是Java的特点,是框架实现的基础,百度结果:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的...
  • 反射什么,以及作用

    千次阅读 2016-03-20 22:29:19
    能做什么反射(Reflection)是.NET中的重要机制,通过放射,可以在运行时获 得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称...
  • C# 反射机制和作用

    千次阅读 2018-06-21 23:41:49
    作用&lt;1&gt; Json或XML解析,用于实例化一个class类,当然需要该class类和jsondata或XML data的内容相匹配。评价:很鸡肋的用法——如果你很懒,不想写反射机制的相关代码,完全可以用JsonMa...
  • 我疑问的地方就是,已经创建了类还有属性,为什么还要用复杂的反射去调用,直接创建 不好吗?
  • 文章目录反射的定义什么是“正射”反射作用 反射的定义 计算机科学中的反射(reflection) 指计算机程序在运行时(runtime) 可以访问、检测和修改它本身状态或行为的一种能力。通俗说,反射就是程序在运行的时候...
  • Java反射作用用途

    万次阅读 多人点赞 2019-02-26 17:16:45
    反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息...
  • 反射作用与原理

    千次阅读 2018-03-12 13:42:44
    (1)概念反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射...
  • Java反射机制--是什么,为什么,怎么用

    千次阅读 多人点赞 2018-04-27 16:09:40
    1.反射什么 首先看书要理解反射,很难完全理解,这关系到Java的语言特性,jvm的内存细节,当初我看反射,就像高票答案那样,照着写一遍,结果是你并没有理解,你只是照猫画虎,要想真正理解,我建议题主,不断...
  • 反射的使用场景、作用及优缺点?

    千次阅读 2019-11-19 09:24:00
    作用 通过反射可以使程序代码访问装载到 JVM 中的类的内部信息,获取已装载类的属性信息、方法信息 优点 提高了 Java 程序的灵活性和扩展性,降低耦合性,提高自适应能力。 允许程序创建和控制任何类的对象,...
  • 什么是反射?一般用来做什么?

    万次阅读 2018-05-08 11:12:40
    反射机制指的是程序在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。 2、作用 a) 获取一个Class对象 1) .getClass()方法,这是一个Object类定义的方法,涉及到强转,用通配符表示泛型可以避免...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 194,069
精华内容 77,627
关键字:

反射作用是什么