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

目录
相关文章
|
23天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
60 2
|
27天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
26天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
|
1月前
|
安全 IDE Java
Java反射Reflect机制详解
Java反射(Reflection)机制是Java语言的重要特性之一,允许程序在运行时动态地获取类的信息,并对类进行操作,如创建实例、调用方法、访问字段等。反射机制极大地提高了Java程序的灵活性和动态性,但也带来了性能和安全方面的挑战。本文将详细介绍Java反射机制的基本概念、常用操作、应用场景以及其优缺点。 ## 基本概念 ### 什么是反射 反射是一种在程序运行时动态获取类的信息,并对类进行操作的机制。通过反射,程序可以在运行时获得类的字段、方法、构造函数等信息,并可以动态调用方法、创建实例和访问字段。 ### 反射的核心类 Java反射机制主要由以下几个类和接口组成,这些类
60 2
|
1月前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
29 3
|
1月前
|
Java 开发者
深入理解Java异常处理机制
【10月更文挑战第29天】在Java的世界中,异常处理如同生活的调味品,不可或缺。它确保了程序在遇到错误时不会崩溃,而是优雅地继续运行或者给出提示。本文将带你领略异常处理的奥秘,从基础的try-catch语句到高级的自定义异常,让你在面对程序中的各种“意外”时,能够从容应对。
|
1月前
|
SQL Java
探索Java中的异常处理机制
【10月更文挑战第26天】 在本文中,我们将深入探讨Java编程语言的异常处理机制。通过分析不同类型的异常、异常的捕获与抛出方式,以及如何自定义异常类,读者将能够更好地理解并应用Java中的异常处理机制来提高代码的健壮性和可读性。
24 0
|
20天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
11天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
6天前
|
监控 Java 开发者
深入理解Java中的线程池实现原理及其性能优化####
本文旨在揭示Java中线程池的核心工作机制,通过剖析其背后的设计思想与实现细节,为读者提供一份详尽的线程池性能优化指南。不同于传统的技术教程,本文将采用一种互动式探索的方式,带领大家从理论到实践,逐步揭开线程池高效管理线程资源的奥秘。无论你是Java并发编程的初学者,还是寻求性能调优技巧的资深开发者,都能在本文中找到有价值的内容。 ####