`
中南大宝
  • 浏览: 33760 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

反射(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日凌晨写于刘洋寝室

 

  • 描述: 写好的几个类
  • 大小: 85.6 KB
  • 描述: 编译Selecter.java
  • 大小: 68 KB
  • 描述: 没有编译Dell前的窗体
  • 大小: 29.9 KB
  • 描述: 编译Dell后再次点击查询
  • 大小: 42.3 KB
  • 描述: 编译Dell和Apple类
  • 大小: 50.4 KB
  • 描述: 编译后Apple也可以被查询了
  • 大小: 40.4 KB
分享到:
评论
1 楼 ronaldoLY 2013-01-25  

相关推荐

Global site tag (gtag.js) - Google Analytics