快速了解java中的反射概念是由什么样的方法构成的

    作者:课课家教育更新于: 2016-02-29 20:02:57

    大神带你学编程,欢迎选课

      java介绍了新的“反射”概念,并利用这个概念查询一个特定类的方法——要么是由所有方法构成的一个完整列表,要么是这个列表的一个子集(名字与我们指定的关键字相符)。那个例子最大的好处就是能自动显示出所有方法,不强迫我们在继承结构中遍历,检查每一级的基础类。所以,它实际是我们节省编程时间的一个有效工具:因为大多数Java方法的名字都规定得非常全面和详尽,所以能有效地找出那些包含了一个特殊关键字的方法名。若找到符合标准的一个名字,便可根据它直接查阅联机帮助文档。

    快速了解java中的反射概念是由什么样的方法构成的_java特定类_java继承_课课家

      但第11的那个例子也有缺陷,它没有使用AWT,仅是一个纯命令行的应用。在这儿,我们准备制作一个改进的GUI版本,能在我们键入字符的时候自动刷新输出,也允许我们在输出结果中进行剪切和粘贴操作:

      //: DisplayMethods.java

      // Display the methods of any class inside

      // a window. Dynamically narrows your search.

      import java.awt.*;

      import java.awt.event.*;

      import java.applet.*;

      import java.lang.reflect.*;

      import java.io.*;

      public class DisplayMethods extends Applet {

      Class cl;

      Method[] m;

      Constructor[] ctor;

      String[] n = new String[0];

      TextField

      name = new TextField(40),

      searchFor = new TextField(30);

      Checkbox strip =

      new Checkbox("Strip Qualifiers");

      TextArea results = new TextArea(40, 65);

      public void init() {

      strip.setState(true);

      name.addTextListener(new NameL());

      searchFor.addTextListener(new SearchForL());

      strip.addItemListener(new StripL());

      Panel

      top = new Panel(),

      lower = new Panel(),

      p = new Panel();

      top.add(new Label("Qualified class name:"));

      top.add(name);

      lower.add(

      new Label("String to search for:"));

      lower.add(searchFor);

      lower.add(strip);

      p.sETLayout(new BorderLayout());

      p.add(top, BorderLayout.NORTH);

      p.add(lower, BorderLayout.SOUTH);

      setLayout(new BorderLayout());

      add(p, BorderLayout.NORTH);

      add(results, BorderLayout.CENTER);

      }

      class NameL implements TextListener {

      public void textValueChanged(TextEvent e) {

      String nm = name.getText().trim();

      if(nm.length() == 0) {

      results.setText("No match");

      n = new String[0];

      return;

      }

      try {

      cl = Class.forName(nm);

      } catch (ClassNotFoundException ex) {

      results.setText("No match");

      return;

      }

      m = cl.getMethods();

      ctor = cl.getConstructors();

      // Convert to an array of Strings:

      n = new String[m.length + ctor.length];

      for(int i = 0; i < m.length; i++)

      n[i] = m[i].toString();

      for(int i = 0; i < ctor.length; i++)

      n[i + m.length] = ctor[i].toString();

      Redisplay();

      }

      }

      void reDisplay() {

      // Create the result set:

      String[] rs = new String[n.length];

      String find = searchFor.getText();

      int j = 0;

      // Select from the list if find exists:

      for (int i = 0; i < n.length; i++) {

      if(find == null)

      rs[j++] = n[i];

      else if(n[i].indexOf(find) != -1)

      rs[j++] = n[i];

      }

      results.setText("");

      if(strip.getState() == true)

      for (int i = 0; i < j; i++)

      results.append(

      StripQualifiers.strip(rs[i]) + "\\\\n");

      else // Leave qualifiers on

      for (int i = 0; i < j; i++)

      results.append(rs[i] + "\\\\n");

      }

      class StripL implements ItemListener {

      public void itemStateChanged(ItemEvent e) {

      reDisplay();

      }

      }

      class SearchForL implements TextListener {

      public void textValueChanged(TextEvent e) {

      reDisplay();

      }

      }

      public static void main(String[] args) {

      DisplayMethods applet = new DisplayMethods();

      Frame aFrame = new Frame("Display Methods");

      aFrame.addWindowListener(

      new WindowAdapter() {

      public void windowClosing(WindowEvent e) {

      System.exit(0);

      }

      });

      aFrame.add(applet, BorderLayout.CENTER);

      aFrame.setSize(500,750);

      applet.init();

      applet.start();

      aFrame.setVisible(true);

      }

      }

      class StripQualifiers {

      private StreamTokenizer st;

      public StripQualifiers(String qualified) {

      st = new StreamTokenizer(

      new StringReader(qualified));

      st.ordinaryChar(' ');

      }

      public String getNext() {

      String s = null;

      try {

      if(st.nextToken() !=

      StreamTokenizer.TT_EOF) {

      switch(st.ttype) {

      case StreamTokenizer.TT_EOL:

      s = null;

      break;

      case StreamTokenizer.TT_NUMBER:

      s = Double.toString(st.nval);

      break;

      case StreamTokenizer.TT_WORD:

      s = new String(st.sval);

      break;

      default: // single character in ttype

      s = String.valueOf((char)st.ttype);

      }

      }

      } catch(IOException e) {

      System.out.println(e);

      }

      return s;

      }

      public static String strip(String qualified) {

      StripQualifiers sq =

      new StripQualifiers(qualified);

      String s = "", si;

      while((si = sq.getNext()) != null) {

      int lastDot = si.lastIndexOf('.');

      if(lastDot != -1)

      si = si.substring(lastDot + 1);

      s += si;

      }

      return s;

      }

      } ///:~

      程序中的有些东西已在以前见识过了。和本书的许多GUI程序一样,这既可作为一个独立的应用程序使用,亦可作为一个程序片(Applet)使用。此外,StripQualifiers类与它在第11章的表现是完全一样的。

      GUI包含了一个名为name的“文本字段”(TextField),或在其中输入想查找的类名;还包含了另一个文本字段,名为searchFor,可选择性地在其中输入一定的文字,希望在方法列表中查找那些文字。Checkbox(复选框)允许我们指出最终希望在输出中使用完整的名字,还是将前面的各种限定信息删去。最后,结果显示于一个“文本区域”(TextArea)中。

      大家会注意到这个程序未使用任何按钮或其他组件,不能用它们开始一次搜索。这是由于无论文本字段还是复选框都会受到它们的“侦听者(Listener)对象的监视。只要作出一项改变,结果列表便会立即更新。若改变了name字段中的文字,新的文字就会在NameL类中捕获。若文字不为空,则在Class.forName()中用于尝试查找类。当然,在文字键入期间,名字可能会变得不完整,而Class.forName()会失败,这意味着它会“掷”出一个违例。该违例会被捕获,TextArea会随之设为“Nomatch”(没有相符)。但只要键入了一个正确的名字(大小写也算在内),Class.forName()就会成功,而getMethods()和getConstructors()会分别返回由Method和Constructor对象构成的一个数组。这些数组中的每个对象都会通过toString()转变成一个字串(这样便产生了完整的方法或构建器签名),而且两个列表都会合并到n中——一个独立的字串数组。数组n属于DisplayMethods类的一名成员,并在调用reDisplay()时用于显示的更新。

      若改变了Checkbox或searchFor组件,它们的“侦听者”会简单地调用reDisplay()。reDisplay()会创建一个临时数组,其中包含了名为rs的字串(rs代表“结果集”——Result Set)。结果集要么直接从n复制(没有find关键字),要么选择性地从包含了find关键字的n中的字串复制。最后会检查strip Checkbox,看看用户是不是希望将名字中多余的部分删除(默认为“是”)。若答案是肯定的,则用StripQualifiers.strip()做这件事情;反之,就将列表简单地显示出来。

      在init()中,大家也许认为在设置布局时需要进行大量繁重的工作。事实上,组件的布置完全可能只需要极少的工作。但象这样使用BorderLayout的好处是它允许用户改变窗口的大小,并特别能使TextArea(文本区域)更大一些,这意味着我们可以改变大小,以便毋需滚动即可看到更长的名字。

      编程时,大家会发现特别有必要让这个工具处于运行状态,因为在试图判断要调用什么方法的时候,它提供了最好的方法之一。

课课家教育

未登录