Java反射基础

Reflection(反射)是Java被视为动态语言(动态语言:程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。

一句话概括:反射就是把Java类中的各种成分映射成一个个的Java对象

简单画了个图,凑合看吧,自己的理解,如有大神希望多多指教

首先创建一个Student类,为了后面操作方便,在类里面分别创建了四种不同访问权限的构造函数,成员变量以及成员方法

package com.example.testdemo.classforname;

public class Student {
    //构造方法
    public Student() {
        System.out.println("(公有)的构造器被执行了---------");
    }

    public Student(String name, int age) {
        this.age = age;
        this.name = name;
        System.out.println("(公有带参)的构造器被执行了---------");
    }

    Student(String name) {
        this.name = name;
        System.out.println("(默认)的构造器被执行了---------");
    }

    private Student(int age) {
        this.age = age;
        System.out.println("(私有)的构造器被执行了---------");
    }

    protected Student(double grade) {
        this.grade = grade;
        System.out.println("(受保护)的构造器被执行了---------");
    }

    //成员变量
    String name;
    private int age;
    public double grade;
    public int classNumber;
    protected String sex;

    //成员函数
    void method1(String name) {
        System.out.println("(默认)的方法被执行了---------");
    }

    public void method2() {
        System.out.println("(公有)的方法被执行了---------");
    }

    private void method3(double grade) {
        System.out.println("(私有)的方法被执行了---------");
    }

    protected void method4(String sex) {
        System.out.println("(受保护)的方法被执行了---------");
    }

    @Override
    public String toString() {
        return "[name:" + name + ",age:" + age + ",grade:" + grade + ",sex:" + sex + ",classNumber:" + classNumber + "]";
    }

    public static void main(String[] args) {
        System.out.println("main方法被执行" + args.toString());
    }

}

反射的使用在这里大致分为四个部分:

获取class对象

获取class对象有三种方式

package com.example.testdemo.classforname;

/**
 * 获取class对象
 */
public class Test {

    public static void main(String[] args) throws Exception {
        //获取class文件的三种方法:
        //1,根据对象获取class(无意义)已经有对象
        Student student = new Student();
        Class clazz = student.getClass();
        //2,根据对象.class(无意义)一般需要导入类的相关包
        clazz = Student.class;
        //3,根据类名获取class(推荐使用)
        clazz = Class.forName("com.example.testdemo.classforname.Student");
        System.out.println(clazz);
        //class对象获取实例对象
        Object object= clazz.newInstance();
        System.out.println(object);

    }
}

获取构造函数

package com.example.testdemo.classforname;

import java.lang.reflect.Constructor;

/**
 * 获取class对象的构造函数
 */
public class Test1 {
    public static void main(String[] args) throws Exception {
        //获取class对象
        Class clazz = Class.forName("com.example.testdemo.classforname.Student");
        //分为两组
        //第一组:1,获取单个(公有)构造函数
        System.out.println("获取单个(公有)构造函数---------");
        Constructor constructor = clazz.getConstructor();
        System.out.println(constructor);
        constructor = clazz.getConstructor(String.class, int.class);//获取有参构造需要传入参数类型
        System.out.println(constructor);
        //第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)构造函数
        System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)构造函数---------");
        constructor = clazz.getDeclaredConstructor(String.class);//获取有参构造需要传入参数类型
        System.out.println(constructor);

        //根据不同构造器创建实例对象
        Object obj = constructor.newInstance("张三");
        System.out.println(obj);

        //第二组:1,获取多个(公有)构造函数
        System.out.println("获取多个(公有)构造函数---------");
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }
        //第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)构造函数
        System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)构造函数---------");
        constructors = clazz.getDeclaredConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }

    }
}

 

获取成员变量

package com.example.testdemo.classforname;

import java.lang.reflect.Field;

/**
 * 获取class对象的成员变量
 */
public class Test2 {
    public static void main(String[] args) throws Exception {
        //获取class对象
        Class clazz = Class.forName("com.example.testdemo.classforname.Student");
        //分为两组
        //第一组:1,获取单个(公有)成员变量
        System.out.println("获取单个(公有)成员变量---------");
        Field field = clazz.getField("grade");//需要传入成员变量名称
        System.out.println(field);

        //第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量
        System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
        field = clazz.getDeclaredField("age");//需要传入成员变量名称
        System.out.println(field);

        //获取私有属性并赋值
        Object obj = clazz.newInstance();
        //age是私有属性,需要暴力设置
        field.setAccessible(true);
        field.set(obj,15);
        System.out.println(obj);

        //第二组:1,获取多个(公有)成员变量
        System.out.println("获取多个(公有)成员变量---------");
        Field[] fields = clazz.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        //第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)成员变量
        System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
        fields = clazz.getDeclaredFields();
        for (Field f : fields) {
            System.out.println(f);
        }
    }
}

 

获取成员方法

package com.example.testdemo.classforname;

import java.lang.reflect.Method;

/**
 * 获取成员方法
 */
public class Test3 {
    public static void main(String[] args) throws Exception {
        //获取class对象
        Class clazz = Class.forName("com.example.testdemo.classforname.Student");

        //分为两组
        //第一组:1,获取单个(公有)成员方法
        System.out.println("获取单个(公有)成员方法---------");
        Method m = clazz.getMethod("method2");//需要传入成员方法名称,有参数需要传入参数
        System.out.println(m);

        //第一组:2,获取单个(所有包括公有的,私有的,默认的,受保护的)成员方法
        System.out.println("获取单个(所有包括公有的,私有的,默认的,受保护的)成员变量---------");
        m = clazz.getDeclaredMethod("method3",double.class);//需要传入成员方法名称
        System.out.println(m);

        //获取方法后执行
        Object obj = clazz.newInstance();
        //method3是私有方法需要暴力设置
        m.setAccessible(true);
        m.invoke(obj,89.50);//传入方法需要的参数


        //第二组:1,获取多个(公有)成员方法
        System.out.println("获取多个(公有)成员方法--------");
        Method[] methods = clazz.getMethods();
        for (Method m1 : methods) {
            System.out.println(m1);
        }
        //第二组:2,获取多个(所有包括公有的,私有的,默认的,受保护的)成员方法
        System.out.println("获取多个(所有包括公有的,私有的,默认的,受保护的)成员方法---------");
        methods = clazz.getDeclaredMethods();
        for (Method m1 : methods) {
            System.out.println(m1);
        }
    }
}

突发奇想能不能获取类中的main方法?不说了,直接上代码测试

package com.example.testdemo.classforname;

import java.lang.reflect.Method;

/**
 * 获取class中的main方法
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        //获取class对象
        Class clazz = Class.forName("com.example.testdemo.classforname.Student");
        //main方法是公有方法
        Method method = clazz.getMethod("main",String[].class);
        //main方法没有对象(静态方法),需要注意invoke传入的参数是object类型必须强转,不然出现异常
        method.invoke(null,(Object) new String[]{"aaaaa"});
    }
}

依然是可以拿到的,以前觉得反射没有什么用,除了在jdbc的时候使用,最近看了一些框架,基本都是反射,编程的路漫漫,我们一起走吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值