zoukankan      html  css  js  c++  java
  • java反射

    Java Reflection
         Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
    反射相关的主要API:
    java.lang.Class:代表一个类
    java.lang.reflect.Method:代表类的方法
    java.lang.reflect.Field:代表类的成员变量
    java.lang.reflect.Constructor:代表类的构造方
    Class 类:
           在Object类中定义了以下的方法,此方法将被所有子类继承: public final Class getClass()
    Class 类的常用方法:
    实例:
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    public class TestReflection {
        //有了反射,可以通过反射创建一个类的对象,并调用其中的属性、方法
        
        public void test3(){
            Person p=new Person();
            Class cla=p.getClass();//通过运行时类的对象,调用其getClass方法,返回其运行时类
            System.out.println(cla);
        }
          
        public void test2() throws Exception{
         Class cla=Person.class;
         
         //1.创建cla对应的运行时类Person类的对象
         Person p=(Person)cla.newInstance();
         System.out.println(p);
         
         //2.通过反射调用运行时类的指定的属性
         //2.1
         Field f1=cla.getField("name");
         f1.set(p, "LiMing");
         System.out.println(p);
         //2.2
         Field f2=cla.getDeclaredField("age");
         f2.setAccessible(true);
         f2.set(p, 20);
         System.out.println(p);
         
         //3.通过反射调用运行时类的指定的方法
         Method m1=cla.getMethod("show");
         m1.invoke(p);
         
         Method m2=cla.getMethod("display", String.class);
         m2.invoke(p, "China");
        }    
        
        //不使用反射的情况下,创建一个对象,并调用其中的属性、方法    
        public void test1(){
           Person person=new Person();
           person.setName("LiMing");
           person.setAge(20);
           person.show();
           person.display("HK");
        }
    }
    public class Person {
         private String name;
         private int age;
         public Person(){
             super();
         }
         public Person(String name){
             super();
             this.name=name;
         }
         public Person(String name,int age){
             super();
             this.name=name;
             this.age=age;
         }
         
         public void setName(String name){
             this.name=name;
         }
         public String getName(){
             return name;
         }
         public void setAge(int age){
             this.age=age;
         }
         public int getAge(){
             return age;
         }
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
        public void show(){
            System.out.println("我是一个人!");
        }
        public void display(String nation){
            System.out.println("我的国籍是:"+nation);
        }
    }
    java.lang.Class:是反射的源头
    我们创建了一个类,通过编译(javac.exe)生成相应的.class文件。之后我们使用java.exe加载(JVM的类加载器)此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在缓冲区,那么这个运行时类本身就是一个Class实例。
        1.一个运行时类只加载一次。
        2.有了Class类的实例以后,我们才可以进行如下的操作:
            1)创建对应的运行时类的对象
            2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解...)
            3)调用对应的运行时类的指定的结构(属性、方法、构造器)
            4)反射的应用:动态代理
     
    实例化Class类对象(四种方法):
        1.若已知具体的类,通过类的class属性获取,该方法 最为安全可靠,程序性能最高
                    实例:Class clazz = String.class;
           2.已知某个类的实例,调用该实例的getClass()方法获取Class对象
                    实例:Class clazz = “www.atguigu.com”.getClass();
           3.已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException
                    实例:Class clazz = Class.forName(“java.lang.String”);
           4.通过类的加载器(类加载器是用来把类(class)装载进内存的)(了解)
                    ClassLoader cl = this.getClass().getClassLoader();
                    Class clazz4 = cl.loadClass(“类的全类名”);
    public void test4() throws ClassNotFoundException{
            //调用运行时类本身的.class属性
            Class cla1=Person.class;
            System.out.println(cla1.getName());//返回com.atguigu.java.Person
            Class cla2=String.class;
            System.out.println(cla2.getName());//返回java.lang.String
            
            //通过运行时类的对象获取
            Person p=new Person();
            Class cla3=p.getClass();
            System.out.println(cla3.getName());//返回com.atguigu.java.Person
            
            //通过运行时类的静态方法forName获取
            Class cla4=Class.forName("com.atguigu.java.Person");
            System.out.println(cla4.getName());//返回com.atguigu.java.Person
        } 
    创建类对象并获取类的完整结构:
             创建类的对象:调用Class对象的newInstance()方法
                       要求:1)类必须有一个无参数的构造器。
                         2)类的构造器的访问权限需要足够。
           //1.根据全类名获取对应的Class对象
           String name = “atguigu.java.Person";
           Class clazz = Class.forName(name);
           //2.调用指定参数结构的构造器,生成Constructor的实例
           Constructor con = clazz.getConstructor(String.class,Integer.class);
           //3.通过Constructor的实例创建对应类的对象,并初始化类属性
           Person p2 = (Person) con.newInstance("Peter",20);
           System.out.println(p2);
     
     
    通过反射调用类中的指定方法、指定属性:
    1.调用指定属性
    先获取属性
    public Field getField(String name) 返回此Class对象表示的类或接口的指定的public的Field。
    public Field getDeclaredField(String name)返回此Class对象表示的类或接口的指定的Field。
    在Field中:
    public Object get(Object obj) 取得指定对象obj上此Field的属性内容
    public void set(Object obj,Object value) 设置指定对象obj上此Field的属性内容
    注:在类中属性都设置为private的前提下,在使用set()和get()方法时,首先要使用Field类中的setAccessible(true)方法将需要操作的属性设置为可以被外部访问。
    public void setAccessible(true)访问私有属性时,让这个属性可见。
    2.调用指定方法
    通过反射,调用类中的方法,通过Method类完成。步骤:
        1).通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
        2).之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。
        //调用运行时类中指定的属性
        public void test5() throws Exception{
            Class cla=Person.class;
            //1.获取指定的属性
            Field name=cla.getField("name");
            //2.创建运行时类的对象
            Person p=(Person)cla.newInstance();
            //3.将运行时类的指定的属性赋值
            name.set(p, "LiMing");
            System.out.println(p);
            
            Field age=cla.getDeclaredField("age");
            age.setAccessible(true);
            age.set(p, 20);
            System.out.println(p);
        }
        //调用运行时类中指定的方法
        public void test6() throws Exception{
            Class cla=Person.class;
            //获取运行时类中声明为public的指定的方法
            Method m1=cla.getMethod("show");
            Person p=(Person)cla.newInstance();
            //调用指定的方法
            Object returnVal=m1.invoke(p);
            
            //对于运行时类中静态方法的调用,无需创建运行时类的对象,直接使用类调用对象
            Method m2=cla.getMethod("info");
            m2.invoke(Person.class);
        }  
  • 相关阅读:
    (十)安装YAML
    (十四)日志
    Android自动化测试------monkeyrunner(六)
    Android自动化测试------monkey日志管理(五)
    如何学好一门编程语言
    linux vi hjkl由来
    .net 微服务CICD 好文章
    APPCMD 精心整理 有点赞的吗
    APPCMD 命令合集
    APPCMD 使用手册
  • 原文地址:https://www.cnblogs.com/xujiming/p/5374189.html
Copyright © 2011-2022 走看看