JAVA 基础 - 反射

1.Java类加载机制

1.1 概要

class文件有类加载器加载后,在JVM中形成一份描述Class结构的元信息对象,通过该元信息对象Class可以获知class文件的结构信息,如构造函数,属性和方法等。
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制。

1.2工作机制

类加载器就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件,在JAVA中,类加载器把一个类装入JVM中,要经过以下几个步骤:
1.加载,查找和导入Class文件
2.连接,把类的二进制数据合并到JRE中。
a校验:检查载入Class文件数据的正确性。
b准备:给类的静态变量分配存储空间。
c解析:将符号引用转成直接引用。
3.初始化:对类的静态变量,静态代码块执行初始化操作。

1.3类初始化的时机

下列四种情况能够出发类的初始化

new出来的对象。
需要调用父类的方法
制定的主类,main()
java.lang.reflect反射的方法。

1.4反射概述

JAVA反射机制是对运行状态中,对指定的类,任意的方法或者字段进行操作,这种动态获取的信息以及动态调用对象方法的功能成为反射。
主要组成:

Class类
COnstructor类
Method方法
Field字段
instance实例
invoke执行

1.5创建数据,JavaBean
//用于数据的封装
/*
 * JavaBean 规范:
 *      1.必须提供私有字段。
 *      2.必须提供getter和setter方法。
 *      3.提供无参构造方法。
 *      4.必须实现序列化接口
 *          java.io.Serializable
 * 
 * 
 * */
public class JavaBean implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String className;
    private String id;
    public String getClassName() {
        return className;
    }
    public void setClassName(String className) {
        this.className = className;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public JavaBean(String className, String id) {
        super();
        this.className = className;
        this.id = id;
    }
    public JavaBean() {
        super();
        // TODO Auto-generated constructor stub
    }

}

1.6 获取Class的三种方法和应用场景

/*
 * 三种方式获得Class对象
 *      1.不同应用场景,需要不同的方式
 * 方式:
 *      1.通过字符串(全限定类名)获取。
 *      2.通过JAVA类型获得。
 *      3.通过实例对象(变量名)来获得。
 * 
 * 应用:
 *  方式一:从配置文件中来获得类的全限定类名,并通过反射进行所有操作。
 *  方式二:确定构造方法、普通方法形参列表时,需要通过类型获得。
 *  public void init(String s,Integer i);
 *  内存需要通过类型对应的Class进行标识。
 *  init(Stirng.class,Integer.class)
 *  方式三:方法内部通过变量名获得
 * */   

    @Test
    public void demo01() throws ClassNotFoundException{
//      通过字符串获得
        Class clazz  =  Class.forName("MyReflect.JavaBean");
        System.out.println(clazz);
    }

    @Test
    public void demo02() throws ClassNotFoundException{
//      通过JAVA类型获得
        Class clazz = JavaBean.class;

        System.out.println(clazz);
    }

    @Test
    public void demo03() throws ClassNotFoundException{
//      通过实例对象获得

        JavaBean javaBean = new JavaBean();
        Class clazz = javaBean.getClass();
        System.out.println(clazz);
    }
}

1.7反射获取构造方法

1.7.1 反射获取无参构造。
public class Contructor {
    @Test
    public void demo01(){
//      1.触发无参构造方法。
        JavaBean javaBean = new JavaBean();

    }

    @Test
    public void demo02() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//      1.通过反射获得无参构造方法,在获得实例对象。
        /*
         * 1.获得Class对象。
         * 2.通过Class获得无参构造。
         * 3.通过构造对象获得实例化对象。
         * */
//      获得class
        Class clazz = Class.forName("MyReflect.JavaBean");
//      获得构造对象,相当于JavaBean()
        Constructor constructor = clazz.getConstructor();
//      获得实例,相当于:new JavaBean();
//      newInstance() 创建制定实参的实例对象
        Object object = constructor.newInstance();

    }

    @Test
    public void demo03() throws Exception, SecurityException{
        Class clazz = JavaBean.class;

        Constructor constructor = clazz.getConstructor(String.class,String.class);

        Object object = constructor.newInstance("0001","Tommy");

        System.out.println(object);

    }

    @Test
//  无参构造快速获得实例对象
    public void demo04() throws Exception, SecurityException{
//      1.获得Class
        Class clazz = JavaBean.class;
//      2.通过CLazz直接获得对象
        Object object = clazz.newInstance();

    }
}

    @Test
//  获取私有构造方法,创建实例对象
    public void demo05() throws Exception, SecurityException{
//      1.获得Class对象
        Class clazz = JavaBean.class;
//      2.获得制定形参的私有构造
        /*
         * clazz.getConstructor(parameterTypes); 获得指定对象的public构造方法。
         * 
         * clazz.getDeclaredConstructor(parameterTypes);
         * 获得指定对象的所有构造方法。
         * */
        Constructor constructor = clazz.getDeclaredConstructor(String.class,String.class);
//      3.通知JVM允许实例化私有构造
        constructor.setAccessible(true);
//      4.创建实例,并设置实参
        Object object = constructor.newInstance("kooo1","Tommy&hans");
        System.out.println(object);

    }
1.8反射私有方法
public class Method {

    @Test
    public void demo01(){
        JavaBean javaBean = new JavaBean();
        javaBean.setId("000001");
        javaBean.setClassName("Tommys");
        String idString = javaBean.getId();
        System.out.println(idString);
    }

    @Test
    public void demo02() throws Exception, Exception{

//      1.获得实例
        Class clazz = JavaBean.class;
        Object object = clazz.newInstance();

//      2.通过色图ID方法,设置参数
//      2.1获得方法,setID
        java.lang.reflect.Method method = clazz.getMethod("setId", String.class);
//      2.2执行方法,javaBean.setID()
//      2.3确定实例对象,并执行确定方法,具体实际参数
        method.invoke(object, "b00093");
        System.out.println(object);
    }

    @Test
    public void demo03() throws Exception, Exception{

//      1.获得实例
        Class clazz = JavaBean.class;
        Object object = clazz.newInstance();

//      2.通过色图ID方法,设置参数
//      2.1获得方法,setID
        java.lang.reflect.Method method = clazz.getMethod("setId", String.class);
//      2.2执行方法,javaBean.setID()
//      2.3确定实例对象,并执行确定方法,具体实际参数
        method.invoke(object, "b00093");
        System.out.println(object);
//      3.通过getId方法,获得数据
        java.lang.reflect.Method getMethod = clazz.getMethod("getId");
        String idString = (String) getMethod.invoke(object);
        System.out.println(idString);
    }

}
1.9 反射main函数
@Test
    public void testMian() throws Exception, Exception{
//      执行静态main方法
//      获得实例
//      执行方法,必须Class对象

//      1.获Class对象

        Class clazz = JavaBean.class;

//      2.获得main方法
        Method method = clazz.getMethod("main", String[].class);

        System.out.println(method);
//3.执行main方法
//      3.1参数一:为实例对象,Static方法不需要
//      3.2参数二:main方法执行的实际参数。
//      可变参数在执行时,JVM内部将传递的实参数组打散,变成了多个参数。
//      可变参数这里,method.invoke(null, args);
//      等效method.invoke(null, "","","');
        String[] args = {"abc","123","xxx"};

//      method.invoke(null, args);错误的写法。
//      数组参数需要特殊处理
//      1.将String[] 转换成Object,可变参数将不处理数组。   
        method.invoke(null, (Object)args);
//      2.将提供二维数组,args将作为二维数组的第一个数。
        method.invoke(null, new Object[] {args});

    }
2.0反射字段
public class Reflect_field {
    @Test
    public void demo01() throws Exception, Exception{
//      1.获取实例对象
        Class clazz = BeanDemo1.class;
        Object object = clazz.newInstance();

//      2.给字段赋值
        Field filed = clazz.getField("description");
        filed.set(object, "descriptions");

//      3.获取字段值
        String string = (String)filed.get(object);
        System.out.println(string);
    }

    @Test
    public void demo02() throws Exception, Exception{
//      私有字段
//      1.获得实例
        Class clazz = BeanDemo1.class;
        Object object = clazz.newInstance();
//      2.获得声明的字段
//      ***clazz.getField(arg0) 公共字段
//      ***clazz.getDeclaredField(arg0); 声明字段,私有
        Field field = clazz.getDeclaredField("className");
//      3.设置运行访问的私有
        field.setAccessible(true);
        field.set(object, "i am className");
//      4.设置数据
        String classname = (String)field.get(object);
//      5.获得数据
        System.out.println(classname);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值