Java反射

一,反射的概述

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

二,反射的功能

Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

有时候我们说某个语言具有很强的动态性,有时候我们会区分动态和静态的不同技术与作法。动态绑定(dynamic binding)、动态链接(dynamic linking)、动态加载(dynamic loading)等。然而“动态”一词其实没有绝对而普遍适用的严格定义,有时候甚至像面向对象当初被导入编程领域一样,一人一把号,各吹各的调。

一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。

尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

Java如何能够做出上述的动态特性呢?这是一个深远话题,本文对此只简单介绍一些概念。整个篇幅最主要还是介绍Reflection APIs,也就是让读者知道如何探索class的结构、如何对某个“运行时才获知名称的class”生成一份实体、为其fields设值、调用其methods。本文将谈到java.lang.Class,以及java.lang.reflect中的Method、Field、Constructor等等classes。

三、反射的原理

Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了

如图是类的正常加载过程:反射的原理在与class对象

四,反射的使用

1、获取Class对象的三种方式:

1、new之后使用getClass()获取Class对象

    Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
    Class stuClass = stu1.getClass();//获取Class对象

2、使用静态的class属性获取

Class stuClass2 = Student.class;
  1. 通过Class类的forName()方法获取常用

Class stuClass3 = Class.forName("com.bean.Student");//括号中是类的全类名(即包名+类名)

2、反射的应用

1、Class对象中一些方法的使用,先写一个接口和两个接口的实现

BookService 接口
 
public interface BookService {
    public void add();
 
    public void fun();
}
BookServiceImpl实现类
public class BookServiceImpl implements BookService {
    //类的属性---存储数据
    public String name;
    int age;
    protected String sex;
    private String address;
 
    //类的构造方法---用来构造对象
    public BookServiceImpl() {
    }
 
    public BookServiceImpl(String name) {
        this.name = name;
    }
 
    private BookServiceImpl(String name, int age, String sex, String address) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.address = address;
    }
 
 
    BookDao bookDao=new BookDaoImpl();
 
    //功能方法---完成一些程序或者功能
    @Override
    public void add() {
        System.out.println("BookServiceImpl...add");
        bookDao.add();
    }
 
    public void fun(){
        System.out.println("BookServiceImpl...fun");
    }
}
BookServiceVip实现类
public class BookServiceVip implements BookService {
    BookDao bookDao=new BookDaoImpl();
    @Override
    public void add() {
        System.out.println("BooKServiceVip...add");
        bookDao.add();
    }
 
    public void fun(){
        System.out.println("BookServiceImpl...fun");
    }
}

五,在测试类Class中的一些常用的方法

public class Test01 {
    public static void main(String[] args) throws Exception {
        //通过全类名加载类的Class对象
        Class cla = Class.forName("com.service.impl.BookServiceImpl");
        //Class对象可以认为是类的手术刀,可以解刨类里面的东西--属性、构造器、方法
        Field[] fields = cla.getFields(); //只能获取public修饰的属性
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-------------");
        Field[] fields1 = cla.getDeclaredFields(); //获取所有属性
        for (Field field : fields1) {
            System.out.println(field);
        }
 
        System.out.println("======================");
 
        Constructor[] constructors = cla.getConstructors();//获取构造该方法(public修饰的方法)
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("-------------");
        Constructor[] constructors1 = cla.getDeclaredConstructors();//获取所有的构造方法
        for (Constructor constructor : constructors1) {
            System.out.println(constructor);
        }
 
        System.out.println("======================");
        Method[] methods = cla.getMethods();//获取所有public修饰的方法
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("-------------");
        Method[] methods1 = cla.getDeclaredMethods();//获得类的所有方法。包括private 声明的和继承类
        for (Method method : methods1) {
            System.out.println(method);
        }
    }
}
  1. 使用外部配置和反射机制完成一个微型框架

1、在src目录下新建一个properties文件
  1. 其中数据和值采用键值对(key = value)的形式进行赋值
className=com.chen.service.impl.BookServiceVip
methodName=add
  1. 在测试类中完成框架内容

public class Test03 {
    public static void main(String[] args) throws Exception {
        //读取配置文件,获取内容   
//File file=new 
    //File("D:\\code\\IdeaProjects\\spring2105\\spring01\\src\\info.properties");
//        InputStream stream=new FileInputStream(file);
//简便写法
   InputStream stream = Test03.class.getClassLoader().getResourceAsStream("info.properties");
        //声明一个properties对象
        Properties p=new Properties();
        p.load(stream);
        String className=p.getProperty("className");//想要获取的值的key
        String methodName=p.getProperty("methodName");
 
        //1.通过全类名获取类的Class对象
        Class cla = Class.forName(className);
        //2.通过Class对象获取类的无参构造器
        Constructor constructor = cla.getDeclaredConstructor();
        //3.使用构造器创建对象
        BookService bookService = (BookService) constructor.newInstance();
        //4.获取方法名
        Method method = cla.getDeclaredMethod(methodName);
        //5.执行方法
        method.invoke(bookService);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值