反射
1.反射定义:在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过某种机制来实现对自己行为的描述和监测,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
2.java类反射中的类
java类反射所需要的类,分别是:Field、Constructor、Method、Class、Object
Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。
Constructor类: 提供关于类的单个构造方法的信息,以及对它的访问权限,此类封装了反射类的构造方法。
Method类:提供关于类或者接口上单独某个方法的信息。此类封装反射类方法的一个类。
Class类:类的实例表示正在运行的java应用程序中的类和接口。
获得反射类的三种方法
//获取反射类的三种方法
Class c = null;
//方法一,调用运行时类本身的.class属性
c = String.class;
//方法二 ,通过运行时类的实例获取
c = new String("").getClass();//方法三 Class.forname全包名
c = Class.forName("java.lang.String");
Field类
getFields()访问的是 获取可访问类型 的字段
getField()返回指定字段
getDeclaredFields()访问的是所有的字段
getDeclaredField()访问的是某一个已声明的指定字段
建立实体类
package cn.edu.xatu.entity;
public class Student {
private int id;
private String name;
private char M;
@Override
public String toString() {
// TODO Auto-generated method stub
return "name: " + name +" id:"+id+ "M: " +M;
}
public Student(String name){
this.name = name;
}
public Student(){
System.out.println("student: 默认构造");
}
public Student(int id, String name, char m) {
super();
this.id = id;
this.name = name;
M = m;
}
public String speak(String k){
System.out.println(this.name +k);
return k;
}
private 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 char getM() {
return M;
}
public void setM(char m) {
M = m;
}}
Field类测试
//获取学生的反射类
Class student = null;
try {
student = Class.forName("cn.edu.xatu.entity.Student");
} catch (Exception e) {
e.printStackTrace();
}
// getFields只能获取到public 类型的
// Field[] fiedls = student.getFields();
for (Field field : fiedls) {
System.out.println("getFields方法获取字段名字"+field.getName());
System.out.println("getFields方法获取字段类型"+field.getType().getName());
}
//获得所有声明的字段,破坏封装
Field[] f = student.getDeclaredFields();
for (Field field : f) {
//遍历每个字段获取每个字段的名字
System.out.println("getDeclaredFields获取字段:"+field.getName());
//获取字段的类型并输出名字
System.out.println("getDeclaredFields获取字段类型"+field.getType().getName());
}
//获取单个字段对象
Field f =student.getDeclaredField("name");
f.setAccessible(true);
System.out.println(f.getName());
//获取反射类字段的类型的名字
System.out.println(f.getType().getName());
//新建对象
Student s = new Student("张三");
//通过反射获取某个实例的某个字段
String name = (String) f.get(s);
System.out.println("name:"+name);
// System.out.println("通过get方法获取name:"+ s.getName());
Construceor类
public void test3(){
Class c = null;
try {
c = Class.forName("cn.edu.xatu.entity.Student");
//直接通过反射实例得到的是无参构造函数
Object o = c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
try {
Constructor f = c.getConstructor(int.class,String.class,char.class);
//实例化构造,调用带参构造
Object o =f.newInstance(21,"张三",'m');
System.out.println(o);
} catch (Exception e) {
e.printStackTrace();
}
}
运行结果:
Method类
public void test4(){
Class c = cn.edu.xatu.entity.Student.class;
try {
//通过反射构造实例
Constructor f = c.getConstructor(int.class,String.class,char.class);
Object o =f.newInstance(21,"张三",'m');
//获取指定参数的方法
Method m =c.getMethod("speak", String.class);
//方法调用
m.invoke(o, "在学习");
} catch (Exception e) {
e.printStackTrace();
}
}
运行结果:
反射的一个例子:
创建自己的属性 文件 键、值形式
package cn.edu.xatu.view;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class MyFrame extends JFrame {
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu("功能模块");
public MyFrame(){
bar.add(menu);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setJMenuBar(bar);
setSize(800,600);
setVisible(true);
//获取资源文件
ResourceBundle bundle = ResourceBundle.getBundle("function");
Enumeration<String> keys = bundle.getKeys();
//获取资源文件的键
while(keys.hasMoreElements()){
String key = keys.nextElement();
System.out.println(key);
String name = bundle.getString(key);
System.out.println(name);
try {
//获取该类的反射类
Class c = Class.forName(name);
//对实现execute接口的类进行组装
Class[] in = c.getInterfaces();
for (Class class1 : in) {
while("cn.edu.xatu.view.Function".equals(class1.getName())){
final Function o = (Function) c.newInstance();
JMenuItem m = new JMenuItem(o.getName());
menu.add(m);
m.addActionListener(
new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
o.execute(o.getName());
}
}
);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new MyFrame();
}}
接口函数
package cn.edu.xatu.view;
public interface Function {
/**
* 返回模块名
* @return
*/
public String getName();
/**
* 获取资源的功能
*/
public void execute(String name);}
package cn.edu.xatu.view;
import javax.swing.JOptionPane;
public class WorkPlan implements Function {
@Override
public String getName() {
return "工作管理计划";
}@Override
public void execute(String name) {
this.getName();
JOptionPane.showMessageDialog(null,"工作管理计划");
}}
package cn.edu.xatu.view;
import javax.swing.JOptionPane;
public class CET implements Function {
@Override
public String getName() {
return "CET管理";
}@Override
public void execute(String name) {
this.getName();
JOptionPane.showMessageDialog(null,"CET管理计划");
}}
运行结果:
在自己的Frame类里面,读取资源文件,获取配置的全包名,通过发射new出实例,搭建自己所需要的一个功能平台,创建一个接口,根据需求扩展自己的需求,后期可以通过实现接口来增加不同的需求。本来功能的实现需要各个模块子功能的实现,主模块功能才能用,但是通过反射先将主模块功能建立,子功能基于接口实现不同的功能,可以先完成主功能在完成子功能,各自完成各自的,实现了依赖倒置。降低了模块与模块之间的耦合性。