zoukankan      html  css  js  c++  java
  • Java知识总结:Java反射机制(用实例理解)

    概念理解:

             反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( 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  用来进行扩展类的加载,一般对应的是 jrelibext目录中的类

    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

  • 相关阅读:
    [JSOI2007][BZOJ1030] 文本生成器|AC自动机|动态规划
    [NOI2014][BZOJ3670] 动物园|KMP
    [HAOI2010][BZOJ2427] 软件安装|tarjan|树型dp
    [JSOI2008][BZOJ1017] 魔兽地图DotR|树型dp
    [JLOI2014][BZOJ3631] 松鼠的新家|树上倍增LCA|差分
    [SDOI2010][BZOJ1975] 魔法猪学院|A*|K短路
    [BZOJ1251] 序列终结者|Splay
    hdu 2141 Can you find it?
    hdu 3152 Obstacle Course
    hdu 2680 Choose the best route
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4069890.html
Copyright © 2011-2022 走看看