一、反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
2.获取Class的三方式
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?
方式 | 备注 |
---|---|
Class.forName(“完整类名带包名”) | 静态方法 |
对象.getClass() | |
任何类型.class |
public class Demo{
public static void main(String[] args) throws Exception {
//获取Class对象的第一种方式:
Student student = new Student();
Class c1 = Class.forName("Day01.test01.Student");
System.out.println("第一种方式:"+c1.getMethods());
//第二种方式:
Class c2 = Student.class;
System.out.println("第二种方式:"+c2.getMethods());
//第三种方式:
Class c3 = student.getClass();
System.out.println("第三种方式:"+c3.getMethods());
}
}
3.反射
Class<?> cla = null;
//获取Class对象的引用
cla = Class.forName("Day01.test01.Student");
//第一种方法,实例化默认构造方法,Student必须无参构造函数,否则将抛异常
Student student = (Student) cla.newInstance();
student.setAge(20);
student.setName("java");
System.out.println(user);
两段代码执行效果一样,但是实现的过程还是有很大的差别的:
第一段代码在未运行前就已经知道了要运行的类是 Student ;
第二段代码则是到整个程序运行的时候,从字符串 “Day01.test01.Student”,才知道要操作的类是 Student 。
所以反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
4.反射的应用
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.w.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、在src目录下新建一个properties文件
2、其中数据和值采用键值对(key = value)的形式进行赋值
className=com.chen.service.impl.BookServiceVip
methodName=add
3、在测试类中完成框架内容
InputStream stream=Test01.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);
}
}