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

    反射

    反射被称为框架设计的灵魂

    1568517281277
    JAVA运行的三个阶段:

    1568517527821

    1. .java文件通过javac编译为.class字节码文件,这些都是存放在硬盘中的,这个阶段称为源代码阶段
    2. ClassLoader将字节码文件加载到内存
    3. class是一个用来描述字节码文件的类。其的成员变量、构造方法和成员方法分别被封装为Field[]、Constructor[]、Method[]对象(因为可能有多个,所以用数组进行描述)。--这就是一个反射的过程

    例如,当我们在IDE中定义了一个对象后,IDE会将这个对象对应的类的字节码文件加载到内存中,对应的class对象将其所有的成员方法封装为Method[],这样只需要将Method[]中的元素变量显示出来,就达到了代码提示的效果

    反射的好处:

    1568518178168

    获取字节码文件Class对象

    1568519847034
    第一种方式:字节码文件未加载进内存时

    第二种:字节码文件已加载到内存中

    第三种:已经在运行、有对象了

    1568519762769
    举一个例子:

    Demo1.java

    import domain.Person;
    
    /*
    *@author JiaDing
    */
    public class Demo1 {
    /*
     * 获取Class的三种方式
     */
    	public static void main(String[]args) throws Exception {
    		//1.Claa.forName("全类名")
    		Class cls1=Class.forName("domain.Person");
    		System.out.println(cls1);
    		//2.类名.class
    		Class cls2=Person.class;
    		System.out.println(cls2);
    		//3.对象.getClass()
    		Person p=new Person();
    		Class cls3=p.getClass();
    		System.out.println(cls3);
    	}
    }
    
    

    Person.java

    package domain;
    /*
    *@author JiaDing
    */
    public class Person {
    	private String name;
    	private int age;
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	public Person() {
    		
    	}
    	public Person(String name,int age) {
    		this.name=name;
    		this.age=age;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + "]";
    	}
    	
    }
    
    

    1568519931458

    使用Class对象

    1568520486913

    1. 获取成员变量

    getFields()获取的所有public成员变量!,而getDeclaredFields()获取的才是所有的成员变量(输出时会输出权限修饰符)!

    getDeclaredFields()可以突破private限制对私有变量进行读写!

    1568530697598
    在使用前需要忽略访问权限修饰符的安全检查:暴力反射!

    对成员变量能做的两个操作:设置值void set(Object obj,Object value)、获取值get(Object obj)

    1568530107861
    2. 获取构造方法

    获取时要给出不同参数类型的类

    1568530993796
    有了构造方法获得的构造器,就可以用来创建对象了

    1568531120435
    如果构造使用空参数构造方法创建对象,则可以简化为用class对象中专用的newInstance方法

    1568531281541
    要访问私有构造方法时:

    constructor1.setAccessible(true)

    关于setAccessible()方法,可以看这篇文章:https://www.cnblogs.com/ixenos/p/5699420.html

    这里抽取原博客的一个例子,很好地体现了这个方法的作用:

    class Employee{
        private int id;
        private String name;
        private int age;
        
        public Employee(){
        
        }
        public Employee(int id, String name, int age){
            this.id = id;
            this.name = name;
            this.age = age;
        }
    
        private void setId(int id){
           this.id = id;
        }
        private int judge(int id){
            return this.id - id;
        }
        private String sayHalo(String name){
            return "Halo" + name;
        }
    }
    
    public class PrivateTest{
         public static void main(String[] args){
             Employee em = new Employee(1, "Alex", 22);
            //获取Class对象
             Class<?> emClass =  em.getClass();
     
             //获取特定的声明了的方法
             Method judgeMethod = emClass.getDeclaredMethod("judge", new Class[]{Integer.TYPE});
             //setAccessible(boolean flag)使所有成员可以访问,访问之前设置
             judgeMethod.setAccessible(true);
     
             //获取所有声明的方法
             Method[] allMethods = emClass.getDeclaredMethods();
             //AccessibleObject.setAccessible(AccessibleObject[] array,
                                      boolean flag)批量给访问权限
             AccessibleObject.setAccessible(allMethods, true);
     
             //下面就可以通过反射访问了
             judgeMethod.invoke(em, new Object[]{3});
     
             //or...
             for(Method method : allMethods){
              ...
             }
         }
    }
    
    1. 获取成员方法

    Method对象调用对应的方法:invoke(Object obj,Object ··· args)//传入一个对象和执行该参数需要的参数

    通过getMethods()获取的方法不仅有该类我们定义的方法,还有继承自Object类的方法

    开启暴力反射:method.setAccessible(true);

    获取该方法的名称:String getName();

    String name=method.getName();

    1. 获取类名

    1568531876181
    这样获取的类名是全类名

    反射案例

    1568532864248
    前提:不能改变该类的任何代码,即创建一种通用的方法

    1568533707867
    配置文件类型:.properties,在其中使用全类名(换句话说,如果我们看到一个配置文件中使用的是全类名,我们也可以猜测它使用了反射原理)

    1568534174160
    1568533943763
    利用类加载器的方法获取配置文件资源

    1568534011047
    1568534055038
    这样每次只需要修改配置文件就好了。相比于修改代码,修改配置文件不需要重新编译、测试、上线,也提高了程序的拓展性。

  • 相关阅读:
    重新想象 Windows 8 Store Apps (15) 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager
    重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
    返璞归真 asp.net mvc (10) asp.net mvc 4.0 新特性之 Web API
    与众不同 windows phone (29) Communication(通信)之与 OData 服务通信
    与众不同 windows phone (33) Communication(通信)之源特定组播 SSM(Source Specific Multicast)
    与众不同 windows phone (27) Feature(特性)之搜索的可扩展性, 程序的生命周期和页面的生命周期, 页面导航, 系统状态栏
    与众不同 windows phone (30) Communication(通信)之基于 Socket TCP 开发一个多人聊天室
    返璞归真 asp.net mvc (12) asp.net mvc 4.0 新特性之移动特性
    重新想象 Windows 8 Store Apps (2) 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch
    重新想象 Windows 8 Store Apps (10) 控件之 ScrollViewer 特性: Chaining, Rail, Inertia, Snap, Zoom
  • 原文地址:https://www.cnblogs.com/jiading/p/12357886.html
Copyright © 2011-2022 走看看