类的反射机制

一,什么是反射机制??

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

2,   简单的说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。包括其访问修饰符、父类、实现的接口、属性和方法的所有信息,并可在运行时创建对象、修改属性(包括私有的)、调用方法(包括私有的)。

二,   为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态和静态的概念

a)         静态编译:在编译时确定类型,绑定对象,即通过 Student stu=new Student(“zhangsan”,20);

b)         动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,用以降低类之间的耦合性。

            Class.forName(“com.mysql.jdbc.Driver.class”).newlnstance();

c)         反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是J2EE的开发中。

d)         它的缺点是对性能有影响,使用反射基本上是一种解释操作,这类操作总是慢于直接执行的相同操作。

三,生成对象的两种方式

1,通过new对象的方式

   

2,通过反射

  

         注意:forName("包名.类名"),且该方法仅支持默认构造一个对象。

       若想调用类的带有参数的构造函数,则采用下面方式:

     

       此方法可以通过调用类的任何构造函数来生成类的对象,用传入的参数来匹配构造函数。(注意:传入的是类型的Class对象)

      小提示:当一个类的构造函数被定义成私有的,说明该类不能在类外new对象了。

四,获得类的类对象的三种方式

 1,Class   c = Student .class;

      该方法仅能将Student类的Class对象加载到内存,不会进行初始化。

 

    注意:要用类名.class,因为此时没有生成对象

 2,Class  c2=Class.forName(" 包名.要加载的类的类名");

     将类加载进来,并进行内存分配和初始化赋值

     此时借助的使Class对象的方法,并将包名.要加载的类的类名赋给该方法

   

  3.Student student =new Student("张三“,20,‘男’,”西安工业大学“);

     Class  c3=student.getClass();

    将类加载进来,并进行内存分配和初始化赋值,此时也会生成类的实例.

    注意:此时是通过生成对象的getClass()来进行类的加载。

 

五,通过反射获取类的构造函数/变量/方法

1,方法

 2,变量

3.构造函数(同上)

六,通过反射访问类的私有成员(必须要有对象)

    当一个类的的属性或方法被定义成私有的,此时通过new对象的方式是无法访问的,但是通过反射的方法,却可以访问到。

1,通过反射调用方法。

      第一步:获取类的Class对象和生成对象:

                    Student student=new Student("张三",20,'男',"西安工业大学");

                    Class c=student.getClass();

             还可以采用下面两种方法:

              ******************************************

            

              ******************************************

            

              注意:当构造函数为私有的,要通过反射调用构造函数生成对象       

       

     第二步:获取变量/方法:

            方法:Method method=c.getDeclaredMethod("sing"); //将要获取的方法的名字传入

           变量:Field field=c.getDeclaredField("age"); //将要获取的变量的名字传入

     第三步:设置访问的变量或方法的访问权限

                    field.setAccessible(true);

      第四步:进行操作 ( 访问相应的成员,注意在使用这方法时,先要把对象传入,在传参数)

                     newInstance - 构造对象
                       invoke - 成员方法调用
                       set - 成员变量设置     
get - 得到成员变量值

                       getName - 得到变量/方法/构造函数   的名字

 

 七,应用举例

     对于程序的开发模式之前一直强调:尽量减少耦合,而减少耦合的最好做法是使用接口,但是就算使用了接口也逃不出关键字new,所以实际上new是造成耦合的关键元凶。

范例1:工厂设计模式

 1 package Factory_demo;
 2 
 3 interface Fruit {
 4     public void eat() ;
 5 }
 6 class Apple implements Fruit {
 7     public void eat() {
 8         System.out.println("吃苹果。");
 9     };
10 }
11 class Factory {
12     public static Fruit getInstance(String className) {
13         if("apple".equals(className)){
14             return new Apple() ;
15         }
16         return null;
17     }
18 }
19 public class Demo {
20     public static void main(String[] args) {
21         Fruit f = Factory.getInstance("apple") ;
22         f.eat() ;
23     }
24 }

以上为之前所编写最简单的工厂设计模式,但是在这个工厂设计模式之中有一个最大的问题:如果现在接口的子类增加了,那么工厂类肯定需要修改,这是它所面临的最大问题,而这个最大问题造成的关键性的病因是new,那么如果说现在不使用关键字new了,变为了反射机制呢?

反射机制实例化对象的时候实际上只需要“包.类”就可以,于是根据此操作,修改工厂设计模式。

 1 package reflection_demo1;
 2 
 3 interface Fruit {
 4     public void eat() ;
 5 }
 6 class Apple implements Fruit {
 7     public void eat() {
 8         System.out.println("吃苹果。");
 9     };
10 }
11 class Orange implements Fruit {
12     public void eat() {
13         System.out.println("吃橘子。");
14     };
15 }
16 
17 class Factory {
18     public static Fruit getInstance(String className) {
19         Fruit f = null;
20         try{
21             f = (Fruit) Class.forName(className).newInstance() ;
22         } catch(Exception e) {
23             e.printStackTrace();
24         }
25         return f ;
26     }
27 }
28 
29 public class Demo {
30     public static void main(String[] args) {
31         Fruit f = Factory.getInstance("reflection_demo1.Orange") ;   //传参数 包名.类名
32         f.eat() ;
33     }
34 }

 发现,这个时候即使增加了接口的子类,工厂类照样可以完成对象的实例化操作,这个才是真正的工厂类,可以应对于所有的变化。如果单独从开发角度而言,与开发者关系不大,但是对于日后学习的一些框架技术这个就是它实现的命脉,在日后的程序开发上,如果发现操作的过程之中需要传递了一个完整的“包.类”名称的时候几乎都是反射机制作用。

原文地址:https://www.cnblogs.com/ljl150/p/11786077.html