Java反射机制及IoC原理
Posted Eason-S
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反射机制及IoC原理相关的知识,希望对你有一定的参考价值。
一. 反射机制概念
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
类中有什么信息,利用反射机制就能可以获得什么信息,不过前提是得知道类的名字。
二. 反射机制的作用
- 在运行时判断任意一个对象所属的类;
- 在运行时获取类的对象;
- 在运行时访问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]
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
(以下几个例子,都会用到这个例子的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
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)
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){}
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;
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
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原理的主要内容,如果未能解决你的问题,请参考以下文章