反射(Reflaction)初探
昨天,在蓝杰很多同学一起讨论了反射的东西。大家你一言我一语就把我给整蒙了,一个简简单单的反射,弄得我稀里糊涂的,回寝后就在网上搜了两篇文章,看了别人写的文章,总算是有点头绪了。于是就自己写了一个小程序,测试了一下动态装载的东西。先来解释一下反射的概念,然后贴代码,看结果。
Java 反射机制是指Java程序可以在执行期载入,探知,使用编译期间完全未知的classes.这句话可能有点难以理解,我们可以通过一个例子来看。在 Java程序中我们经常会用到这样一条语句来创建一个对象。Date date = new Date();在这条语句中date的类型(Java.util.Date)在编译时已经确定。那么,有没有办法使我们把对象类型的确定时间由编译转到运行,答案是肯定的。这就是Java反射机制所提供的便利。而且它不单单可以生成对象还可以获取Field,对Field设值,及调用方法等。
谈及Java反射机制就一定要知道一个名为“Class”的类,它是Java反射机制的基础。“Class”和其它类一样继承于Object类,它的实例对象用来描述Java运行时的一种类型,接口,或者原始类型(比如 int).“Class”的实例要由JVM创建,它没有公用的构造方法。下面我们来看一下如何获得"Class"类实例。
主要有三种方法。
一,通过Class类的静态方法forName获取。Class cla = Class.forName("java.lang.String");
二,通过.Type或.class属性获得。Class cla = String.class;Class cla1 = int.Type;
三,通过实例变量的getClass方法获得。String s = ""; Class cla = s.getClass();
如上所示实例对象cla就是对String类型的描述,通过它我们就可以创建一个String实例,并调用其中的方法。
上面的某几段来自百度文库上的一片文章,写的很棒!地址点这里
下面是我写的一个例子,代码的意图是:
Computer接口:含一个方法,测试是否能开机
Dell类:继承了Computer接口,并加入了一些Dell电脑的信息
Lenove类:继承了Computer接口,并加入了一些Lenove电脑的信息
Apple类:继承了Computer接口,并加入了一些Apple电脑的信息
Selecter类:用窗口实现了一些东东
public interface Computer { //在这个接口中定义方法 public String startScreen();//开机的方法 }
public class Dell implements Computer { private String operatingSystem = "Windows7"; private int prize = 4500; private int hardMemory = 320; private int Memory = 2; public String startScreen() { return "Dell is OK!"; } }
public class Apple implements Computer{ private String operatingSystem = "IOS"; private int prize = 7000; private int hardMemory = 500; private int Memory = 4; @Override public String startScreen() { return "Apple is OK!"; } }
public class Lenove implements Computer { private String operatingSystem = "Windows XP"; private int prize = 5000; private int hardMemory = 500; private int Memory = 2; @Override public String startScreen() { return "Lenove is OK!"; } }
import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Field; import java.lang.reflect.Method; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.UIManager; public class Selecter extends JFrame { JTextArea area; private void initFrame() { this.setName("电脑信息查询"); this.setLayout(new FlowLayout()); this.setSize(new Dimension(340, 400)); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(3); JLabel lable = new JLabel("查询的电脑:"); final JTextField text = new JTextField(13); JButton button1 = new JButton("查询"); JButton button2 = new JButton("测试"); area = new JTextArea(); JScrollPane scrollpane = new JScrollPane(area); scrollpane.setPreferredSize(new Dimension(290, 290)); this.add(lable); this.add(text); this.add(button1); this.add(button2); this.add(scrollpane); this.setVisible(true);// 设置窗体可见 // 给按钮1添加监听器 button1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String text1 = text.getText(); getDescription(text1); } }); // 给按钮2添加监听器 button2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String text2 = text.getText(); Computer com = (Computer) getComputer(text2); testComputer(com, "startScreen"); } }); } // 得到所查询电脑的详细信息 public void getDescription(String type) { try { Class cla = Class.forName(type); // 生成一个实例对象,在编译时我们并不知道obj是什么类型 Object obj = cla.newInstance(); // 获得type类型所有已定义类变量及方法。 Field[] fileds = cla.getDeclaredFields(); area.append(cla.getSimpleName()+"电脑的详细信息是:\n"); for (int i = 0; i < fileds.length; i++) { fileds[i].setAccessible(true); // 输出类变量的定义及obj实例中对应的值 area.append(fileds[i].getName() + ":" + fileds[i].get(obj) + "\n"); } area.append("\n"); } catch (Exception e) { area.append("对不起,没有这种电脑的信息!\n\n"); } } // 使用电脑的某个功能 public void testComputer(Object obj, String function) { try { Class cla = obj.getClass(); // 获得cla类中定义的无参方法。 Method m = cla.getMethod(function, null); // 调用obj中名为function的无参方法。 String aa= (String)m.invoke(obj, null); area.append(aa+"\n\n"); } catch (Exception e) {} } // 拿电脑给顾客 public Object getComputer(String type) { try { Class cla = Class.forName(type); Object obj = cla.newInstance(); return obj; } catch (Exception e) { area.append("对不起,没有这种电脑的信息!\n\n"); return null; } } public static void main(String[] args) { /*************** 以下几句是优化窗体界面的方法 ***************************/ JFrame.setDefaultLookAndFeelDecorated(true); // 加上此语句连同窗体外框也改变 JDialog.setDefaultLookAndFeelDecorated(true); // 加上此语句会使弹出的对话框也改变 try { UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (Exception e) { e.printStackTrace(); } /*************** 以上几句是优化窗体界面的方法 ***************************/ Selecter selecter = new Selecter(); selecter.initFrame(); } }
当我输入使用控制台编译Selecter后,三个电脑类还没有被编译。
弹出的窗体如下,当我输入Dell时,因为Dell类此时未被编译,所以没有.class文件,显示没有此电脑信息。
当我编译后,再次点击查询的时候就可以了,这个时候主程序是没有退出的,也就是说,这个类是被动态加载到程序中的,这是使用反射实现的。
大概的就是这些吧,要休息了,如有不完善赶明儿个再补充!
—2013年1月25日凌晨写于刘洋寝室
下一篇: 常用关键字