Java反射机制及IoC原理

Posted Eason-S

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射机制及IoC原理相关的知识,希望对你有一定的参考价值。

一. 反射机制概念

  主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。

  反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

  类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字。

二. 反射机制的作用

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时获取类的对象;
  3. 在运行时访问java对象的属性,方法,构造方法等。

三. 反射机制的优点与缺点

首先要搞清楚为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。 
静态编译:在编译时确定类型,绑定对象,即通过。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。 

反射机制的优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

  比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。 

反射机制的缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。

四. 反射机制的示例

1.通过一个对象获得完整的包名和类名

添加一句:所有类的对象其实都是Class的实例。

 1 package Reflect;
 2 
 3 class Demo{
 4     //other codes...
 5 }
 6 
 7 class hello{
 8     public static void main(String[] args) {
 9         Demo demo=new Demo();
10         System.out.println(demo.getClass().getName());
11     }
12 }
13 //【运行结果】:Reflect.Demo

2.实例化Class类对象

 1 package Reflect;
 2 
 3 class Demo{
 4     //other codes...
 5 }
 6 
 7 class hello{
 8     public static void main(String[] args) {
 9         Class<?> demo1=null;
10         Class<?> demo2=null;
11         Class<?> demo3=null;
12         try{
13             //一般尽量采用这种形式
14             demo1=Class.forName("Reflect.Demo");
15         }catch(Exception e){
16             e.printStackTrace();
17         }
18         demo2=new Demo().getClass();
19         demo3=Demo.class;
20 
21         System.out.println("类名称   "+demo1.getName());
22         System.out.println("类名称   "+demo2.getName());
23         System.out.println("类名称   "+demo3.getName());
24     }
25 }
26 //【运行结果】:
27 //类名称   Reflect.Demo
28 //类名称   Reflect.Demo
29 //类名称   Reflect.Demo

3.通过Class实例化其他类的对象

 1 package Reflect;
 2 
 3 class Person{
 4     public String getName() {
 5         return name;
 6     }
 7     public void setName(String name) {
 8         this.name = name;
 9     }
10     public int getAge() {
11         return age;
12     }
13     public void setAge(int age) {
14         this.age = age;
15     }
16     @Override
17     public String toString(){
18         return "["+this.name+"  "+this.age+"]";
19     }
20     private String name;
21     private int age;
22 }
23 
24 class hello{
25     public static void main(String[] args) {
26         Class<?> demo=null;
27         try{
28             demo=Class.forName("Reflect.Person");
29         }catch (Exception e) {
30             e.printStackTrace();
31         }
32         Person per=null;
33         try {
34             per=(Person)demo.newInstance();
35         } catch (InstantiationException e) {
36             // TODO Auto-generated catch block
37             e.printStackTrace();
38         } catch (IllegalAccessException e) {
39             // TODO Auto-generated catch block
40             e.printStackTrace();
41         }
42         per.setName("Rollen");
43         per.setAge(20);
44         System.out.println(per);
45     }
46 }
47 //【运行结果】:
48 //[Rollen  20]

但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:

比如定义了一个构造函数:

1 public Person(String name, int age) {
2         this.age=age;
3         this.name=name;
4     }

然后继续运行上面的程序,会出现:

java.lang.InstantiationException: Reflect.Person
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at Reflect.hello.main(hello.java:39)
Exception in thread "main" java.lang.NullPointerException
at Reflect.hello.main(hello.java:47)

所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数。

4.通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

 1 package Reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 
 5 class Person{
 6     public Person() {   
 7 
 8     }
 9     public Person(String name){
10         this.name=name;
11     }
12     public Person(int age){
13         this.age=age;
14     }
15     public Person(String name, int age) {
16         this.age=age;
17         this.name=name;
18     }
19     public String getName() {
20         return name;
21     }
22     public int getAge() {
23         return age;
24     }
25     @Override
26     public String toString(){
27         return "["+this.name+"  "+this.age+"]";
28     }
29     private String name;
30     private int age;
31 }
32 
33 class hello{
34     public static void main(String[] args) {
35         Class<?> demo=null;
36         try{
37             demo=Class.forName("Reflect.Person");
38         }catch (Exception e) {
39             e.printStackTrace();
40         }
41         Person per1=null;
42         Person per2=null;
43         Person per3=null;
44         Person per4=null;
45         //取得全部的构造函数
46         Constructor<?> cons[]=demo.getConstructors();
47         try{
48             per1=(Person)cons[0].newInstance();
49             per2=(Person)cons[1].newInstance("Rollen");
50             per3=(Person)cons[2].newInstance(20);
51             per4=(Person)cons[3].newInstance("Rollen",20);
52         }catch(Exception e){
53             e.printStackTrace();
54         }
55         System.out.println(per1);
56         System.out.println(per2);
57         System.out.println(per3);
58         System.out.println(per4);
59     }
60 }
61 //【运行结果】:
62 //[null  0]
63 //[Rollen  0]
64 //[null  20]
65 //[Rollen  20]
View Code

5.返回一个类实现的接口

 1 package Reflect;
 2 
 3 interface China{
 4     public static final String name="Rollen";
 5     public static  int age=20;
 6     public void sayChina();
 7     public void sayHello(String name, int age);
 8 }
 9 
10 class Person implements China{
11     public Person() {
12 
13     }
14     public Person(String sex){
15         this.sex=sex;
16     }
17     public String getSex() {
18         return sex;
19     }
20     public void setSex(String sex) {
21         this.sex = sex;
22     }
23     @Override
24     public void sayChina(){
25         System.out.println("hello ,china");
26     }
27     @Override
28     public void sayHello(String name, int age){
29         System.out.println(name+"  "+age);
30     }
31     private String sex;
32 }
33 
34 class hello{
35     public static void main(String[] args) {
36         Class<?> demo=null;
37         try{
38             demo=Class.forName("Reflect.Person");
39         }catch (Exception e) {
40             e.printStackTrace();
41         }
42         //保存所有的接口
43         Class<?> intes[]=demo.getInterfaces();
44         for (int i = 0; i < intes.length; i++) {
45             System.out.println("实现的接口   "+intes[i].getName());
46         }
47     }
48 }
49 //【运行结果】:
50 //实现的接口   Reflect.China
View Code

(以下几个例子,都会用到这个例子的Person类,所以为节省篇幅,此处不再粘贴Person的代码部分,只粘贴主类hello的代码)

6.取得其他类中的父类

 1 class hello{
 2     public static void main(String[] args) {
 3         Class<?> demo=null;
 4         try{
 5             demo=Class.forName("Reflect.Person");
 6         }catch (Exception e) {
 7             e.printStackTrace();
 8         }
 9         //取得父类
10         Class<?> temp=demo.getSuperclass();
11         System.out.println("继承的父类为:   "+temp.getName());
12     }
13 }
14 //【运行结果】
15 //继承的父类为:   java.lang.Object
View Code

7.获得其他类中的全部构造函数

 1 //这个例子需要在程序开头添加import java.lang.reflect.*;
 2 class hello{
 3     public static void main(String[] args) {
 4         Class<?> demo=null;
 5         try{
 6             demo=Class.forName("Reflect.Person");
 7         }catch (Exception e) {
 8             e.printStackTrace();
 9         }
10         Constructor<?>cons[]=demo.getConstructors();
11         for (int i = 0; i < cons.length; i++) {
12             System.out.println("构造方法:  "+cons[i]);
13         }
14     }
15 }
16 //【运行结果】:
17 //构造方法:  public Reflect.Person()
18 //构造方法:  public Reflect.Person(java.lang.String)
View Code
 1 class hello{
 2     public static void main(String[] args) {
 3         Class<?> demo=null;
 4         try{
 5             demo=Class.forName("Reflect.Person");
 6         }catch (Exception e) {
 7             e.printStackTrace();
 8         }
 9         Constructor<?>cons[]=demo.getConstructors();
10         for (int i = 0; i < cons.length; i++) {
11             Class<?> p[]=cons[i].getParameterTypes();
12             System.out.print("构造方法:  ");
13             int mo=cons[i].getModifiers();
14             System.out.print(Modifier.toString(mo)+" ");
15             System.out.print(cons[i].getName());
16             System.out.print("(");
17             for(int j=0;j<p.length;++j){
18                 System.out.print(p[j].getName()+" arg"+i);
19                 if(j<p.length-1){
20                     System.out.print(",");
21                 }
22             }
23             System.out.println("){}");
24         }
25     }
26 }
27 //【运行结果】:
28 //构造方法:  public Reflect.Person(){}
29 //构造方法:  public Reflect.Person(java.lang.String arg1){}
View Code

8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架

 1 class hello {
 2     public static void main(String[] args) {
 3         Class<?> demo = null;
 4         try {
 5             demo = Class.forName("Reflect.Person");
 6         } catch (Exception e) {
 7             e.printStackTrace();
 8         }
 9         System.out.println("===============本类属性========================");
10         // 取得本类的全部属性
11         Field[] field = demo.getDeclaredFields();
12         for (int i = 0; i < field.length; i++) {
13             // 权限修饰符
14             int mo = field[i].getModifiers();
15             String priv = Modifier.toString(mo);
16             // 属性类型
17             Class<?> type = field[i].getType();
18             System.out.println(priv + " " + type.getName() + " "
19                     + field[i].getName() + ";");
20         }
21         System.out.println("===============实现的接口或者父类的属性========================");
22         // 取得实现的接口或者父类的属性
23         Field[] filed1 = demo.getFields();
24         for (int j = 0; j < filed1.length; j++) {
25             // 权限修饰符
26             int mo = filed1[j].getModifiers();
27             String priv = Modifier.toString(mo);
28             // 属性类型
29             Class<?> type = filed1[j].getType();
30             System.out.println(priv + " " + type.getName() + " "
31                     + filed1[j].getName() + ";");
32         }
33     }
34 }
35 //【运行结果】:
36 //===============本类属性========================
37 //private java.lang.String sex;
38 //===============实现的接口或者父类的属性========================
39 //public static final java.lang.String name;
40 //public static final int age;
View Code

9.通过反射调用其他类中的方法

 1 class hello {
 2     public static void main(String[] args) {
 3         Class<?> demo = null;
 4         try {
 5             demo = Class.forName("Reflect.Person");
 6         } catch (Exception e) {
 7             e.printStackTrace();
 8         }
 9         try{
10             //调用Person类中的sayChina方法
11             Method method=demo.getMethod("sayChina");
12             method.invoke(demo.newInstance());
13             //调用Person的sayHello方法
14             method=demo.getMethod("sayHello", String.class,int.class);
15             method.invoke(demo.newInstance(),"Rollen",20);
16         }catch (Exception e) {
17             e.printStackTrace();
18         }
19     }
20 }
21 //【运行结果】:
22 //hello ,china
23 //Rollen  20
View Code

10.调用其他类的set和get方法

 1 class hello {
 2     public static void main(String[] args) {
 3         Class<?> demo = null;
 4         Object obj=null;
 5         try {
 6             demo = Class.forName("Reflect.Person");
 7         } catch (Exception e) {
 8             e.printStackTrace();
 9         }
10         try{
11          obj=demo.newInstance();
12         }catch (Exception e) {
13             e.printStackTrace();
14         }
15         setter(obj,"Sex","男",String.class);
16         getter(obj,"Sex");
17     }
18 
19     /**
20      * @param obj   操作的对象
21      * @param att   操作的属性
22      * */
23     public static void getter(Object obj, String att) {
24         try {
以上是关于Java反射机制及IoC原理的主要内容,如果未能解决你的问题,请参考以下文章

Java反射及 IoC原理内省机制

java:反射机制

java的反射

Java--反射机制原理几种Class获取方式及应用场景

Spring————java的反射机制,Spring的IOC和DI

Java反射机制的原理及在Android下的简单应用