Java知识总结:Java反射机制(用实例理解)

简介: 概念理解:          反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

概念理解:

         反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

         Java中的反射是一个强大的工具,他能够创建灵活的代码,这些 代码可以在运行时装配,无需在组件之间进行链接,发射允许在编写和执行时,使程序代码能够接入装载到 JVM 中的类的内部信息 。而不是源代码中选定的类协作的代码。这使发射成为构建灵活运用的主要工具。值得注意是,如果使用不当,发射的成本会更高。

         Java中的类的反射Refection是Java程序开发语言的特征之一,它允许运行中的Java程度对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java的这一能力在实际应用中也许用的不是很多,但是在其他的程序设计语言中,根本就不存在这样的特性,例如:Pascal、C或者C++中就没有办法在程序中获得与函数定义相关的信息。

案例理解 Java 反射机制:

【案例 1 】 通过一个对象获得完整的包名和类名

package com.guan.goodboy;

public class Demo {

    public Demo(){

    }

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Demo demo = new Demo();

        System. out .println(demo.getClass().getName());

    }

}

【运行结果】 : com.guan.goodboy.Demo

注解:所有类的对象其实都是 Class 的实例。

【案例 2 】 实例化 Class 类对象(三种方法)

方法一 :   Class. forName ( "com.guan.goodboy.Demo" );

方法二 :   new Demo().getClass();

方法三 :   new Demo().getClass();

package com.guan.goodboy;

public class Demo {

    public Demo(){

    }

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo1= null ;

           Class<?> demo2= null ;

           Class<?> demo3= null ;

        try {

            // 一般尽量采用这种形式

          // 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中

            demo1=Class. forName ( "com.guan.goodboy.Demo" );

        } catch (Exception e){

            e.printStackTrace();

        }

        demo2= new Demo().getClass();

        demo3=Demo. class ;

        System. out .println( " 类名称    " +demo1.getName());

        System. out .println( " 类名称    " +demo2.getName());

        System. out .println( " 类名称    " +demo3.getName());

    }

}

【运行结果】 

类名称   com.guan.goodboy.Demo

类名称   com.guan.goodboy.Demo

类名称   com.guan.goodboy.Demo

【案例 3 】 : 通过 Class 实例化其他类的对象

package com.guan.goodboy;

public class Person {

      public String getName() {

            return name ;

        }

        public void setName(Stringname) {

            this . name = name;

        }

        public int getAge() {

            return age ;

        }

        public void setAge( int age) {

            this . age = age;

        }

        @Override

        public String toString(){

            return "[" + this . name + "  " + this . age + "]" ;

        }

        private String name ;

        private int age ;

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo= null ;

        try {

          // 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        Person per= null ;

        try {

          // 通过反射,实例化对象,创建一个无参数的构造器(反射机制)

            per=(Person)demo.newInstance();

        } catch (InstantiationException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        } catch (IllegalAccessException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        per.setName( "Rollen" );

        per.setAge(20);

        System. out .println(per);

    }

}

【运行结果】 : [Rollen  20]

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

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

    public Person(String name, int age) {

        this . age =age;

        this . name =name;

    }

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

java.lang.InstantiationException : com.guan.goodboy.Person

    at java.lang.Class.newInstance0( Class.java:357 )

    at java.lang.Class.newInstance( Class.java:325 )

    at com.guan.goodboy.FiveHead.main( FiveHead.java:15 )

Exception inthread "main" java.lang.NullPointerException

    at com.guan.goodboy.FiveHead.main( FiveHead.java:23 )

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

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

package com.guan.goodboy;

public class Person {

    private String name ;

      private int age ;

    public Person() {

    }

    public Person(String name){

        this . name =name;

    }

    public Person( int age ){

        this . age = age ;

    }

    public Person(String name, int age) {

        this . age =age;

        this . name =name;

    }

    public String getName() {

        return name ;

    }

    public int getAge() {

        return age ;

    }

    @Override

    public String toString(){

        return "[" + this . name + "  " + this . age + "]" ;

    }

}

package com.guan.goodboy;

import java.lang.reflect.Constructor;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo= null ;

        try {

          // 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        Person per1= null ;

        Person per2= null ;

        Person per3= null ;

        Person per4= null ;

        // 取得全部的构造函数

        Constructor<?>cons[]=demo.getConstructors();

        // 检测一个奇怪的现象,就是构造器的生成时从后面算起的

        System. out .println(cons[0]);

        System. out .println(cons[1]);

        System. out .println(cons[2]);

        System. out .println(cons[3]);

        System. out .println();

        try {

          // 获得的构造器,在进行参数赋值的时候,要与生成的构造器参数类型一直,不然会包如下错误

          //java.lang.IllegalArgumentException: wrong number ofarguments

            per1=(Person)cons[0].newInstance( "Rollen" ,20);

            per2=(Person)cons[1].newInstance(20);

            per3=(Person)cons[2].newInstance( "Rollen" );

            per4=(Person)cons[3].newInstance();

        } catch (Exception e){

            e.printStackTrace();

        }

        System. out .println(per1);

        System. out .println(per2);

        System. out .println(per3);

        System. out .println(per4);

    }

}

【运行结果】:

publiccom.guan.goodboy.Person(java.lang.String,int)

publiccom.guan.goodboy.Person(int)

publiccom.guan.goodboy.Person(java.lang.String)

publiccom.guan.goodboy.Person()

[Rollen  20]

[null  20]

[Rollen  0]

[null 0]

【案例 5 】 通过Class调用其他类中的构造函数 (为了避免案例4中的顺序问题,可以通过构造器中的参数,指定相应的构成函数,如本例所示)

package com.guan.goodboy;

public class Person {

    private String name ;

      private Integer age ;

    public Person() {

    }

    public Person(String name){

        this . name =name;

    }

    public Person(Integer age){

        this . age =age;

    }

    public Person(String name, Integer age) {

        this . age =age;

        this . name =name;

    }

    public String getName() {

        return name ;

    }

    public int getAge() {

        return age ;

    }

    @ Override

    public String toString(){

        return "[" + this . name + "  " + this . age + "]" ;

    }

}

package com.guan.goodboy;

import java.lang.reflect.Constructor;

public class FiveHead {

    public static void main(String[] args) throws NoSuchMethodException, SecurityException {

        Class<?> demo= null ;

        try {

          // 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        Person per1= null ;

        Person per2= null ;

        Person per3= null ;

        Person per4= null ;

        Constructor<?> con1 =demo.getConstructor( new Class[]{});

        Constructor<?> con2 =demo.getConstructor( new Class[]{Integer. class });

        Constructor<?> con3 = demo.getConstructor( new Class[]{String. class ,Integer.class });

        Constructor<?> con4 =demo.getConstructor( new Class[]{String. class });

        // 检测一个奇怪的现象,就是构造器的生成时从后面算起的

        System. out .println(con1);

        System. out .println(con2);

        System. out .println(con3);

        System. out .println(con4);

        System. out .println();

        try {

          per1= (Person)con1.newInstance();

          per2 = (Person)con2.newInstance( new Object[]{20});

          per3= (Person)con3.newInstance( new Object[]{ "xiaoguan" ,20});

          per4= (Person)con4.newInstance( new Object[]{ "xiaoguan" });

         

        } catch (Exception e){

            e.printStackTrace();

        }

        System. out .println(per1);

        System. out .println(per2);

        System. out .println(per3);

        System. out .println(per4);  

    }

}

【运行结果】:

publiccom.guan.goodboy.Person()

publiccom.guan.goodboy.Person(java.lang.Integer)

publiccom.guan.goodboy.Person(java.lang.String,java.lang.Integer)

publiccom.guan.goodboy.Person(java.lang.String)

[null  null]

[null  20]

[xiaoguan  20]

[xiaoguan  null]

【案例 6 】 返回一个类实现的接口

package com.guan.goodboy;

interface   China {

    public static final String name = "Rollen" ;

    public static   int age =20;

    public void sayChina();

    public void sayHello(String name, int age);

}

package com.guan.goodboy;

public class Person implements China{

    public Person() {

    }

    public Person(String sex){

        this . sex =sex;

    }

    public String getSex() {

        return sex ;

    }

    public void setSex(String sex) {

        this . sex = sex;

    }

    public void sayChina(){

        System. out .println( "hello ,china" );

    }

    public void sayHello(String name, int age){

        System. out .println(name+ "  " +age);

    }

    private String sex ;

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo= null ;

        try {

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        // 保存所有的接口

        Class<?>intes[]=demo.getInterfaces();

         for int i = 0; i <intes. length ; i++) {

            System. out .println( " 实现的接口    " +intes[i].getName());

        } 

    }

}

【运行结果】:

实现的接口   com.guan.goodboy.China

【案例 7 】取得其他类中的父类(下面几个案例,重用案例 6 的 Person 类和 China类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo= null ;

        try {

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        // 取得父类

        Class<?>temp=demo.getSuperclass();

        System. out .println( " 继承的父类为:    " +temp.getName());

    }

}

【运行结果】:

继承的父类为:   java.lang.Object

【案例 8 】获得其他类中的全部构造函数(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Constructor;

public class FiveHead {

    public static void main(String[] args) {

          Class<?> demo= null ;

            try {

                demo=Class. forName ( "com.guan.goodboy.Person" );

            } catch ( Exception e) {

               e.printStackTrace();

            }

           Constructor<?>cons[]=demo.getConstructors();

            for int i = 0; i <cons. length ; i++) {

                System. out .println( " 构造方法:   " +cons[i]);

            }

    }

}

【运行结果】:

构造方法:  public com.guan.goodboy.Person()

构造方法:  publiccom.guan.goodboy.Person(java.lang.String)

【案例 9 】获取构造函数中 public  或者 private 等这一类的修饰符(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Constructor;

import java.lang.reflect.Modifier;

public class FiveHead {

    public static void main(String[] args) {

          Class<?> demo= null ;

            try {

                demo=Class. forName ( "com.guan.goodboy.Person" );

            } catch (Exception e) {

               e.printStackTrace();

            }

           Constructor<?>cons[]=demo.getConstructors();

            for int i = 0; i <cons. length ; i++) {

                Class<?>p[]=cons[i].getParameterTypes();

                System. out .print( " 构造方法:   " );

                int mo=cons[i]. getModifiers ();

                System. out .print(Modifier. toString (mo)+ " " );

                System. out .print(cons[i]. getName ());

                System. out .print( "(" );

                for int j=0;j<p. length ;++j){

                    System. out .print(p[j].getName()+ " arg" +i);

                    if (j<p. length -1){

                        System. out .print( "," );

                    }

                }

                System. out .println( "){}" );

            }

    }

}

【运行结果】:

构造方法:  public com.guan.goodboy.Person(){}

构造方法: public com.guan.goodboy.Person(java.lang.String arg1){}

【案例 10 】获得类中所有方法及方法后的异常信息(本案例,重用案例 6 的Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo= null ;

        try {

            demo=Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        Method method[]=demo.getMethods();

        for int i=0;i<method. length ;++i){

            Class<?>returnType=method[i].getReturnType();

            Class<?>para[]=method[i].getParameterTypes();

            int temp=method[i].getModifiers();

            System. out .print(Modifier. toString (temp)+ " " );

            System. out .print(returnType.getName()+ "  " );

            System. out .print(method[i].getName()+ " " );

            System. out .print( "(" );

            for int j=0;j<para. length ;++j){

                System. out .print(para[j].getName()+ " " + "arg" +j);

                if (j<para. length -1){

                    System. out .print( "," );

                }

            }

            Class<?> exce []=method[i].getExceptionTypes();

            if ( exce . length >0){

                System. out .print( ") throws " );

                for int k=0;k< exce . length ;++k){

                    System. out .print( exce [k].getName()+ " " );

                    if (k< exce . length -1){

                        System. out .print( "," );

                    }

                }

            } else {

                System. out .print( ")" );

            }

            System. out .println();

        }

    }

}

【运行结果】:

publicjava.lang.String  getSex ()

publicvoid  setSex (java.lang.String arg0)

publicvoid  sayChina ()

publicvoid  sayHello (java.lang.String arg0,intarg1)

public finalvoid  wait () throws java.lang.InterruptedException

public finalvoid  wait (long arg0,int arg1) throws java.lang.InterruptedException

public finalnative void  wait (long arg0) throws java.lang.InterruptedException

publicboolean  equals (java.lang.Object arg0)

publicjava.lang.String  toString ()

publicnative int  hashCode ()

public finalnative java.lang.Class  getClass ()

public finalnative void  notify ()

public finalnative void  notifyAll ()

【案例 11 】接下来让我们取得其他类的全部属性吧,最后将这些整理在一起,也就是通过 class 取得一个类的全部框架(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Field;

import java.lang.reflect.Modifier;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo = null ;

        try {

            demo = Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

        System. out .println( "=============== 本类属性========================" );

        // 取得本类的全部属性

        Field[] field = demo. getDeclaredFields ();

        for int i = 0; i < field. length ; i++) {

            // 权限修饰符

            int mo = field[i].getModifiers();

            String priv = Modifier. toString (mo);

            // 属性类型

            Class<?> type =field[i].getType();

            System. out .println(priv + " " + type.getName() + " "

                    + field[i].getName() + ";" );

        }

        System. out .println( "=============== 实现的接口或者父类的属性========================" );

        // 取得实现的接口或者父类的属性

        Field[] filed1 = demo.getFields();

        for int j = 0; j < filed1. length ; j++) {

            // 权限修饰符

            int mo = filed1[j].getModifiers();

            String priv = Modifier. toString (mo);

            // 属性类型

            Class<?> type =filed1[j].getType();

            System. out .println(priv + " " + type.getName() + " "

                    + filed1[j].getName() + ";" );

        }

    }

}

【运行结果】:

===============本类属性========================

privatejava.lang.String sex;

===============实现的接口或者父类的属性========================

publicstatic final java.lang.String name;

publicstatic final int age;

【案例 12 】通过反射调用其他类中的方法(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Method;

public class FiveHead {

    public static void main(String[] args) {

         Class<?> demo = null ;

            try {

                demo = Class. forName ( "com.guan.goodboy.Person" );

            } catch (Exception e) {

               e.printStackTrace();

            }

             try {

                // 调用 Person 类中的 sayChina 方法

                Methodmethod=demo.getMethod( "sayChina" );

                System. out .println(method);    // 输出结果如下

                //public void com.guan.goodboy.Person.sayChina()

               method.invoke(demo.newInstance());

               

                // 调用 Person 的 sayHello 方法

               method=demo.getMethod( "sayHello" , String. class int class );

               method.invoke(demo.newInstance(), "Rollen" ,20);

                

            } catch (Exception e) {

                e.printStackTrace();

            }

    }

}

【运行结果】:

public voidcom.guan.goodboy.Person.sayChina()

hello ,china

Rollen  20

【 案例 13 】调用其它类的 get 与 set 方法(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Method;

public class FiveHead {

    public static void main(String[] args) {

        Class<?> demo = null ;

        Object obj= null ;

        try {

            demo = Class. forName ( "com.guan.goodboy.Person" );

        } catch (Exception e) {

            e.printStackTrace();

        }

         try {

         obj=demo.newInstance();

        } catch (Exception e) {

            e.printStackTrace();

        }

        setter (obj, "Sex" , " 男 " ,String. class );

        getter (obj, "Sex" );

    }

    /**

     * @param obj

     *            操作的对象

     * @param att

     *            操作的属性

     * */

    public static void getter(Object obj , String att) {

        try {

            Method method = obj .getClass().getMethod( "get" + att);

            System. out .println(method.invoke( obj ));

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

    /**

     * @param obj

     *            操作的对象

     * @param att

     *            操作的属性

     * @param value

     *            设置的值

     * @param type

     *            参数的属性

     * */

    public static void setter(Object obj, String att, Object value,

            Class<?> type) {

        try {

            Method method =obj.getClass().getMethod( "set" + att, type);

            method.invoke(obj, value);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

【运行结果】:

【案例 14 】通过反射操作属性(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)

package com.guan.goodboy;

import java.lang.reflect.Field;

public class FiveHead {

    public static void main(String[] args) throwsClassNotFoundException,InstantiationException, IllegalAccessException, NoSuchFieldException,SecurityException {

        Class<?> demo = null ;

        Object obj = null ;

        demo = Class. forName ( "com.guan.goodboy.Person" );

        obj = demo.newInstance();

        Field field = demo.getDeclaredField( "sex" );

        field.setAccessible( true );

        field.set(obj, " 男 " );

        System. out .println(field.get(obj));

    }

}

【运行结果】:

【案例 15 】通过反射取得并修改数组的信息

package com.guan.goodboy;

import java.lang.reflect.Array ;

public class FiveHead {

    public static void main(String[] args) {

        int [] temp={1,2,3,4,5};

       Class<?>demo=temp.getClass().getComponentType();

        System. out .println( " 数组类型: " +demo.getName());

        System. out .println( " 数组长度   " + Array . getLength (temp));

        System. out .println( " 数组的第一个元素 : " + Array . get (temp, 0));

        Array . set (temp, 0, 100);

        System. out .println( " 修改之后数组第一个元素为: " + Array . get (temp, 0));

    }

}

【运行结果】:

数组类型: int

数组长度  5

数组的第一个元素: 1

修改之后数组第一个元素为: 100

【案例 16 】通过反射修改数组大小

package com.guan.goodboy;

import java.lang.reflect.Array;

public class FiveHead {

    public static void main(String[] args) {

        int [] temp={1,2,3,4,5,6,7,8,9};

        int [] newTemp=( int []) arrayInc (temp,15);

        print (newTemp);

        System. out .println();

        System. out .println( "=====================" );

        String[] atr={ "a" , "b" , "c" };

        String[] str1=(String[]) arrayInc (atr,8);

        print (str1);

    }

    /**

     * 修改数组大小

     * */

    public static Object arrayInc(Object obj, int len){

        Class<?>arr=obj.getClass().getComponentType();

        Object newArr=Array. newInstance (arr,len);

        int co=Array. getLength (obj);

        System. arraycopy (obj, 0, newArr,0, co);

        return newArr;

    }

    /**

     * 打印

     * */

    public static void print(Object obj){

        Class<?>c=obj.getClass();

        if (!c.isArray()){

            return ;

        }

        System. out .println( " 数组长度为: " +Array. getLength (obj));

        for int i = 0; i < Array. getLength (obj);i++) {

            System. out .print(Array. get (obj, i)+ " " );

        }

    }

}

【运行结果】:

数组长度为: 15

1 2 3 4 5 6 7 8 9 0 0 0 0 0 0

=====================

数组长度为: 8

a b c null null null null null

 

 

反射机制之动态代理:

【案例 17 】首先来看看如何获得类加载器:

package com.guan.goodboy;

public class Test {

}

 

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Test t= new Test();

        System. out . println (t.getClass());

        System. out . println (t.getClass().getClassLoader());

        System. out println (t.getClass().getClassLoader().getClass());

        System. out .println( " 类加载器   "+t.getClass().getClassLoader().getClass().getName());

    }

}

【运行结果】:

class com.guan.goodboy.Test

sun.misc.Launcher$AppClassLoader@2760e8a2

classsun.misc.Launcher$AppClassLoader

类加载器  sun.misc.Launcher$AppClassLoader

 

其实在 java 中有三种类类加载器。

1 )、 BootstrapClassLoader  此加载器采用 c++ 编写,一般开发中很少见。

2 )、 ExtensionClassLoader  用来进行扩展类的加载,一般对应的是 jre\lib\ext目录中的类

3 )、 AppClassLoader  加载 classpath 指定的类,是最常用的加载器。同时也是java 中默认的加载器。

【案例 18 】如果想要完成动态代理,首先需要定义一个 InvocationHandler 接口的子类,已完成代理的具体操作

package com.guan.goodboy;

/**

 * 定义项目接口

 */

interface Subject {

    public String say(String name, int age);

}

package com.guan.goodboy;

/**

 * 定义真实项目

 */

class RealSubject implements Subject {

    public String say(String name, int age) {

        return name + "  " + age;

    }

}

package com.guan.goodboy;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

class MyInvocationHandler implements InvocationHandler {

    private Object obj = null ;

    public Object bind(Object obj) {

        this . obj = obj;

        return Proxy. newProxyInstance (obj. getClass ().getClassLoader(),obj

                . getClass ().getInterfaces(), this );

    }

    public Object invoke(Object proxy, Method method,Object[] args)

            throws Throwable {

        Object temp = method.invoke( this . obj , args);

        return temp;

    }

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        MyInvocationHandler demo = new MyInvocationHandler();

        Subject sub = (Subject) demo.bind( new RealSubject());

        String info = sub.say( "Rollen" , 20);

        System. out .println(info);

    }

}

【运行结果】:

Rollen 20

类的生命周期

在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开 JVM 。在程序执行中 JVM 通过 装载 , 链接 , 初始化 这 3 个步骤完成。

类的 装载 是通过类加载器完成的,加载器将 .class 文件的二进制文件装入 JVM 的方法区,并且在堆区创建描述这个类的 java.lang.Class 对象。用来封装数据。但是同一个类只会被类装载器装载,以前 链接 就是把二进制数据组装为可以运行的状态。

 

链接 分为校验,准备,解析这 3 个阶段

校验 一般用来确认此二进制文件是否适合当前的 JVM (版本),

准备 就是为静态成员分配内存空间,。并设置默认值

解析 指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)

完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。

当没有任何引用指向 Class 对象时就会被卸载,结束类的生命周期

将反射用于工厂模式

先来看看,如果不用反射的时候,就用工厂模式吧:

http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html

【案例 19 】现在来看看工厂模式

工厂模式特点: 当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。 【案例 20 】 用反射机制设置,请看 【案例 20】 .

package com.guan.goodboy;

/**

 * 工厂模式设计

 */

interface Fruit{

    public abstract void eat();

}

package com.guan.goodboy;

/**

 * Apple 实现接口 Fruit

 */

class Apple implements Fruit{

    public void eat(){

        System. out .println( "Apple" );

    }

}

package com.guan.goodboy;

/**

 * Orange 实现接口 Fruit

 */

class Orange implements Fruit {

    public void eat (){

        System. out .println( "Orange" );

    }

}

package com.guan.goodboy;

/**

 * 构造工厂类

 * 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了

 */

class Factory{

  public static Fruit getInstance(String fruitName ){

     Fruit f= null ;

     if ( "Apple" .equals( fruitName )){

         f= new Apple();

     }

     if ( "Orange" .equals( fruitName )){

         f= new Orange();

     }

     return f;

 }

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Fruit f=Factory. getInstance ( "Orange" );

        f.eat();

    }

}

【运行结果】:

Orange

【案例 20 】用反射模式,实现 【案例 19 】 中同样的功能,请查看各自的区别(注解:其中主要的不同在 Factory 类与 main 函数类的不同)

package com.guan.goodboy;

/**

 * Fruit 接口

 */

interface Fruit{

    public abstract void eat();

}

package com.guan.goodboy;

/**

 * Apple 实现接口 Fruit

 */

class Apple implements Fruit{

    public void eat(){

        System. out .println( "Apple" );

    }

}

package com.guan.goodboy;

/**

 * Orange 实现接口 Fruit

 */

class Orange implements Fruit{

    public void eat(){

        System. out .println( "Orange" );

    }

}

package com.guan.goodboy;

/**

 * 构造工厂类

 * 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了

 */

class Factory{

    public static Fruit getInstance(String ClassName ){

        Fruit f= null ;

        try {

            f=(Fruit)Class. forName ( ClassName ).newInstance();

        } catch (Exception e) {

            e.printStackTrace();

        }

        return f;

    }

}

package com.guan.goodboy;

public class FiveHead {

    public static void main(String[] args) {

        Fruit f=Factory. getInstance ( "com.guan.goodboy.Apple" );

        if (f!= null ){

            f.eat();

        }

    }

}

【运行结果】:

Apple

参考文献:

编译工具Myeclipse8.6

JDK1.7

《Java编程思想》

《Java面试宝典》

http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html

http://blog.csdn.net/justinavril/article/details/2873664

http://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B

目录
相关文章
|
2天前
|
XML 安全 Java
Java反射机制:解锁代码的无限可能
Java 反射(Reflection)是Java 的特征之一,它允许程序在运行时动态地访问和操作类的信息,包括类的属性、方法和构造函数。 反射机制能够使程序具备更大的灵活性和扩展性
15 5
Java反射机制:解锁代码的无限可能
|
1天前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
9 3
|
1天前
|
安全 Java UED
深入理解Java中的异常处理机制
【10月更文挑战第25天】在编程世界中,错误和意外是不可避免的。Java作为一种广泛使用的编程语言,其异常处理机制是确保程序健壮性和可靠性的关键。本文通过浅显易懂的语言和实际示例,引导读者了解Java异常处理的基本概念、分类以及如何有效地使用try-catch-finally语句来处理异常情况。我们将从一个简单的例子开始,逐步深入到异常处理的最佳实践,旨在帮助初学者和有经验的开发者更好地掌握这一重要技能。
7 2
|
3天前
|
Java 数据库连接 开发者
Java中的异常处理机制####
本文深入探讨了Java语言中异常处理的核心概念,通过实例解析了try-catch语句的工作原理,并讨论了finally块和throws关键字的使用场景。我们将了解如何在Java程序中有效地管理错误,提高代码的健壮性和可维护性。 ####
|
4天前
|
Java
Java中的反射机制与应用实例
【10月更文挑战第22天】Java作为一门面向对象的编程语言,提供了丰富的特性来支持对象的创建、操作和交互。其中,反射机制是Java的一项核心特性,它允许程序在运行时动态地获取类的信息、创建对象、调用方法、访问属性等。本文将从三个部分探讨Java中的反射机制及其应用实例:一是反射机制的基本概念和原理;二是反射机制在Java中的应用场景;三是通过实例深入理解反射机制的使用方法和技巧。
10 4
|
5天前
|
安全 Java 程序员
深入浅出Java中的异常处理机制
【10月更文挑战第20天】本文将带你一探Java的异常处理世界,通过浅显易懂的语言和生动的比喻,让你在轻松阅读中掌握Java异常处理的核心概念。我们将一起学习如何优雅地处理代码中不可预见的错误,确保程序的健壮性和稳定性。准备好了吗?让我们一起踏上这段旅程吧!
20 6
|
3天前
|
存储 运维 Java
💻Java零基础:深入了解Java内存机制
【10月更文挑战第18天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
15 1
|
6月前
|
Java API 开发者
解密Java反射机制与动态代理
解密Java反射机制与动态代理
48 0
|
XML Java 数据库连接
JAVA反射机制与动态代理
JAVA反射机制与动态代理
132 0