反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
反射的原理在于class对象。
加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
原理
Student s1=new Student();
Student s2=new Student();
当我们new Student时,JVM会去我们本地磁盘去找Student.class文件并加载到JVM内存中,
new Student会在JVM中产生s1,s2的对象空间,JVM通过得到Student对象信息使得s1或s2可以通过 点来获取Student类的信息。
查看Class类在java中的api详
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)Class 没有公共构造方法。
==Class ==对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。
反射的使用
一、工厂模式
工厂模式(Factory Pattern)即在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。工厂模式是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
目的 ->定义一个创建对象的接口,让其子类自己决定实例化那一个工厂类,工厂模式使其创建过程推迟到子类进行。
优点 | 缺点 |
---|---|
调用者想创建一个对象,只要知道其名称就可以了 | 每增加一个就需要增加一个具体类和实现工厂 ,增加了复杂度 |
扩展性高 | 耦合度变高 |
举例说明
简单工厂反射实现
利用反射Class.forName(clz.getName()).newInstance()实现的简单工厂:
编写实体类Student
import java.util.Date;
public class Student {
int id;
String name;
String email;
Date date;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
测试类
import java.lang.reflect.Field;
public class StudentTest {
public static void main(String[] args) throws ClassNotFoundException {
//调用forName 类加载器
Class clzz=Class.forName("main.Student");
System.out.println(clzz.getName());
//返回 Field 对象的一个数组
Field field[]=clzz.getDeclaredFields();
for (int i=0; i<field.length;i++){
System.out.println(field[i].toString());
}
}
}
结果输出
创建简单(静态)工厂
1.创建
抽象基类,或接口,这是产品的抽象类或接口
我创建的是Ibook接口
package main.Impl;
public interface Ibook {
public void Read();
}
2.编写具体产品类
在这里简单的写了三个
历史书A类,历史书B类,历史书C类,都实现Ibook接口并重写Read()方法
import main.Impl.Ibook;
public class HistoryA implements Ibook {
@Override
public void Read() {
System.out.println("历史书A");
}
}
import main.Impl.Ibook;
public class HistoryB implements Ibook {
@Override
public void Read() {
System.out.println("历史书B");
}
}
import main.Impl.Ibook;
public class HistoryC implements Ibook {
@Override
public void Read() {
System.out.println("历史书C");
}
}
3.创建简单工厂类
- 创建simpleBookFactory
- 设置静态常量:public static final int TYPE_LB=1; 通过编号设置对应A B C类书
- 编写静态方法creatBooks参数为int类型编号,返回值为基类或接口
import main.Impl.Ibook;
public class simpleBookFactory {
public static final int TYPE_A =1;
public static final int TYPE_B =2;
public static final int TYPE_C =3;
public static Ibook creatBooks(int type){
switch (type){
case TYPE_A:
return new HistoryA();
case TYPE_B:
return new HistoryB();
case TYPE_C:
return new HistoryC();
default:
return null;
}
}
}
4.编写测试类
- 通过图书工厂的创建图书方法,选择图书相应的参数进行创建
import main.Impl.Ibook;
import main.simpleBookFactory;
public class MyTest {
public static void main(String[] args) {
Ibook ibook=simpleBookFactory.creatBooks(simpleBookFactory.TYPE_B);
ibook.Read();
}
}
输出结果为