JAVA反射机制

来源:互联网 发布:0基础php自学要多久 编辑:程序博客网 时间:2024/06/10 12:34

假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,
但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?
这是不能通过编译的。
那怎么办呢?
为了解决这个问题,就出现了反射,利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。
什么是反射?
概念:
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
个人感觉看概念很晕的,也许本来懂一丢丢的,基本看完定义就晕了。。。

讲简单点:
java通常是先有类再有对象,有对象我就可以调用方法或者属性。反射其实是通过Class对象来调用类里面的方法。通过反射可以动态的获取对象中的方法,变量,使用这些方法和变量。大部分框架都是运用反射原理

============================================
要是打算做J2EE的朋友们,反射这里可是个重点,基本做J2EE项目都是用框架的,而这些框架中到处充斥着反射机制。

1.反射机制获取类对象有三种方式:

1.//java语言中任何一个java对象都有getClass 方法  类名 e = new 类名();  Class c3 = e.getClass(); //c3是运行时类 类型为类名类型
2.//java中每个类型都有class 属性.  Class c2 = 类名.class;  
3.Class c1 = Class.forName(类的全类名);  

2.创建对象:获取类以后我们来创建它的对象,利用newInstance()方法

Class c1 = Class.forName(类的全类名); //通常用这个Object o = c1.newInstance(); //调用了这个类的无参数构造方法.  

3.获取属性
已经获得对象了,那就可以获得类中的属性了

    // 获取所有的属性    Field[] fs = c.getDeclaredFields();    //获取id属性  (获取特定属性)    Field idF = c.getDeclaredField("id");  

4.获取方法,和构造方法

方法关键字
含义
getDeclaredMethods()
获取所有的方法
getReturnType()
获得方法的放回类型
getParameterTypes()
获得方法的传入参数类型
getDeclaredMethod(“方法名”,参数类型.class,……)
获得特定的方法

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

父类和父接口
含义
getSuperclass()
获取某类的父类
getInterfaces()
获取某类实现的接口

这样利用反射机制,我们就获取了这个类中的所有东西,可以说实现了反编译!对java来说,反射将java的面向对象编程展现的淋漓尽致!
(看到这,啥叫反射?还不懂?举个例子,你在杀猪,反射就是那把杀猪刀,这利用反射这把刀就把猪的内部结构全给你展现在眼前!=-= 恶心到大家,可别打小编奥~)

想必大家了解过配置文件吧,反射加配置文件,简直可以说将程序的扩展性提高了不只一点点!

举个例子:
在工程根目录下新建一个init.properties文件
添加字段ClassName=cn.pack_03.Demo
新建类Demo.java

package cn.pack_03;public class Demo {    public void run() {        System.out.println("welcome to heima!");    }}

新建类Test,java

package cn.pack_03;import java.io.FileReader;import java.lang.reflect.Method;import java.net.InetAddress;import java.util.Properties;public class Test {    public static void main(String[] args) throws Exception, Exception {        //获得properties对象        Properties properties = new Properties();        //加载文件        properties.load(new FileReader("info.properties"));        //根据key获取字段值        String className = properties.getProperty("ClassName");        //直接设置        Class<?> clazz = Class.forName(className);        Object newInstance = clazz.newInstance();        Method method = clazz.getMethod("run", null);        Object invoke = method.invoke(newInstance, null);    }}

有人看完之后会说,本来直接写上ClassName不就好了,这么麻烦,但是,假如我们有一天要改变获取的类对象,那我们就必须进来修改代码,但是这样做,我们只要去修改下配置文件里的内容就好,源代码无序更改,扩展性是不是一下就大了!
在后边我们做数据库时,方便就会彻底展现出来,我们就可以通过配置文件随时更换数据库,例如我们将系统的数据库从SQL Server升级到Oracle,那么我们写两份D层,在配置文件的内容改一下,或者加条件选择一下即可。

注意:弊端
有好处就会有坏处对吧,任何事物都是有相对性的
1.性能:
反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。
2.安全性
使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。
3.类本身内部的安全性
由于反射允许代码执行一些在正常情况下不被允许的操作(比如暴力访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。
总结:
通过反射读取里边的内容,这样代码是固定的,但是配置文件的内容我们可以改,这样使我们的代码灵活了很多,扩展性提高!但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加,具体看开发者是否正确的,灵活的利用反射!

特点:
java的反射机制在很大程度上增加了程序的灵活性,避免将程序写死到代码里。
例如:我们在自己的程序源代码中实例化了一个类对象,但是假如某一天需要将实例化的这个类换成别的类,那么我们只能回到源代码中修改,有基础的朋友,应该很清楚,修改源代码是最不推荐的!但是因为反射机制的出现,我们就可以通过配置*.xml文件来灵活的修改。