Java反射机制
1、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法。所以先要获取到每一个字节码文件对应的Class类型的对象。
使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)
2、反射机制的相关类在哪个包
java.lang.reflect.*;
3、反射能做什么?
我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合。
先获取Class才能获取Method、Constructor、Field
反射就是把java类中的各种成分映射成一个个的Java对象
一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
类加载:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
![](https://i-blog.csdnimg.cn/blog_migrate/1e583f59d5a9d8744ddc6fe09002e142.png)
4、反射的具体实现
package com.chen.service;
public interface BookService {
public void add();
public void fun();
}
BookServiceImpl 类 实现BookService 接口:
package com.chen.service.impl;
import com.chen.dao.BookDao;
import com.chen.dao.impl.BookDaoImpl;
import com.chen.service.BookService;
public class BookServiceImpl implements BookService {
//类的属性--存储数据
//公有属性
public String name;
int age;
//受保护属性
protected String sex;
//私有属性
private String address;
//类的构造方法--用来构造对象
public BookServiceImpl() {
}
public BookServiceImpl(String name){
}
public 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();
}
@Override
public void fun() {
System.out.println("BookServiceImpl..fun");
}
}
spring.properties 外部配置:
key=value
更改java程序需要
修改代码--编译--打包--部署--重启
反射在外修改外部配置 不用重新编译重启
className=com.chen.service.impl.BookServiceImpl
methodName=add
1>获取Class的三种方式
![](https://i-blog.csdnimg.cn/blog_migrate/c622d585a3f985878bc6418b7658e2d3.png)
注:以上三种方式返回值都是Class类型。
//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object类型的对象,而我不知道你具体是什么类,用这种方法
Person p1 = new Person(); Class c1 = p1.getClass();
//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高这说明任何一个类都有一个隐含的静态成员变量 class
Class c2 = Person.class; //3、通过 Class 对象的 forName() 静态方法来获取,用的最多,但可能抛ClassNotFoundException 异常
Class c3 = Class.forName("com.ys.reflex.Person");
注意:在运行期间,一个类,只有一个Class对象产生。
2>通过 Class 类获取成员变量、成员方法、接口、超类、构造方法等
查阅 API 可以看到 Class 有很多方法:
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
测试类:
package com.chen.servlet;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* 反射的应用
*/
public class Test01 {
public static void main(String[] args) throws Exception {
//通过全类名加载类的Class对象
Class cla = Class.forName("com.chen.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();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("-----------------");
Constructor[] constructors1 = cla.getDeclaredConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor);
}
}
}
package com.chen.servlet;
import com.chen.service.BookService;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.Properties;
/**
* 微型框架
*/
/*
* 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
*
* 1.获取构造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
* 2).获取单个的方法,并调用:
* public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
*
* 调用构造方法:
* Constructor-->newInstance(Object... initargs)
*/
public class Test02 {
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 = Test02.class.getClassLoader().getResourceAsStream("spring.properties");
Properties p=new Properties();
p.load(stream);
String className=p.getProperty("className");
//1.通过全类名获取类的Class对象
Class cla = Class.forName(className);
//2.通过Class对象获取类的无参构造器
Constructor constructor = cla.getDeclaredConstructor();
//3.使用构造器创建对象
BookService bookService = (BookService) constructor.newInstance();
//4.使用对象调用方法
bookService.add();
}
}
package com.chen.servlet;
import com.chen.service.BookService;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
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 = Test02.class.getClassLoader().getResourceAsStream("spring.properties");
Properties p=new Properties();
p.load(stream);
String className=p.getProperty("className");
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);
}
}
反射是Java中的一种重要机制,它使得Java更灵活
常用的JavaEE框架——Spring全家桶底层都利用了反射机制
Spring中spring.properties就是反射的一种利用