当前位置:天才代写 > tutorial > JAVA 教程 > 目次列表器

目次列表器

2017-11-13 08:00 星期一 所属: JAVA 教程 浏览:287

此刻假设我们想寓目一个目次列表。可用两种方法列出File工具。若在不含自变量(参数)的环境下挪用list(),会得到File工具包括的一个完整列表。然而,若想对这个列表举办某些限制,就需要利用一个“目次过滤器”,该类的浸染是指出应如何选择File工具来完成显示。
下面是用于这个例子的代码(或在执行该措施时碰着坚苦,请参考第3章3.1.2小节“赋值”):
 

//: DirList.java
// Displays directory listing
package c10;
import java.io.*;

public class DirList {
  public static void main(String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else 
        list = path.list(new DirFilter(args[0]));
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

class DirFilter implements FilenameFilter {
  String afn;
  DirFilter(String afn) { this.afn = afn; }
  public boolean accept(File dir, String name) {
    // Strip path information:
    String f = new File(name).getName();
    return f.indexOf(afn) != -1;
  }
} ///:~

DirFilter类“实现”了interface FilenameFilter(关于接口的问题,已在第7章举办了详述)。下面让我们看看FilenameFilter接口有何等简朴:

public interface FilenameFilter {
boolean accept(文件目次, 字串名);
}

它指出这种范例的所有工具都提供了一个名为accept()的要领。之所以要建设这样的一个类,背后的全部原因就是把accept()要领提供应list()要领,使list()可以或许“回调”accept(),从而判定应将哪些文件名包罗到列表中。因此,凡是将这种技能称为“回调”,有时也称为“算子”(也就是说,DirFilter是一个算子,因为它独一的浸染就是容纳一个要领)。由于list()回收一个FilenameFilter工具作为本身的自变量利用,所以我们能通报实现了FilenameFilter的任何类的一个工具,用它抉择(甚至在运行期)list()要领的行为方法。回调的目标是在代码的行为上提供更大的机动性。
通过DirFilter,我们看出尽量一个“接口”只包括了一系列要领,但并不范围于只能写那些要领(可是,至少必需提供一个接口内所有要领的界说。在这种环境下,DirFilter构建器也会建设)。
accept()要领必需采取一个File工具,用它指示用于寻找一个特定文件的目次;并采取一个String,个中包括了要寻找之文件的名字。可抉择利用或忽略这两个参数之一,但有时至少要利用文件名。记着list()要领筹备为目次工具中的每个文件名挪用accept(),核实哪个应包括在内——详细由accept()返回的“布尔”功效抉择。
为确定我们操纵的只是文件名,个中没有包括路径信息,必需回收String工具,并在它的外部建设一个File工具。然后挪用getName(),它的浸染是去除所有路径信息(回收与平台无关的方法)。随后,accept()用String类的indexOf()要领查抄文件名内部是否存在搜索字串"afn"。若在字串内找到afn,那么返回值就是afn的起点索引;但如果没有找到,返回值就是-1。留意这只是一个简朴的字串搜索例子,未利用常见的表达式“通配符”方案,好比"fo?.b?r*";这种方案更难实现。
list()要领返回的是一个数组。可查询这个数组的长度,然后在个中遍历,选定命组元素。与C和C++的雷同行为对比,这种于要领表里利便游历数组的行为无疑是一个显著的进步。

1. 匿名内部类
下例用一个匿名内部类(已在第7章报告)来重写显得很是抱负。首先建设了一个filter()要领,它返回指向FilenameFilter的一个句柄:
 

//: DirList2.java
// Uses Java 1.1 anonymous inner classes
import java.io.*;

public class DirList2 {
  public static FilenameFilter 
  filter(final String afn) {
    // Creation of anonymous inner class:
    return new FilenameFilter() {
      String fn = afn;
      public boolean accept(File dir, String n) {
        // Strip path information:
        String f = new File(n).getName();
        return f.indexOf(fn) != -1;
      }
    }; // End of anonymous inner class
  }
  public static void main(String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else 
        list = path.list(filter(args[0]));
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~

#p#分页标题#e#

留意filter()的自变量必需是final。这一点是匿名内部类要求的,使其能利用来自自己浸染域以外的一个工具。
之所以认为这样做更好,是由于FilenameFilter类此刻同DirList2细密地团结在一起。然而,我们可采纳进一步的操纵,将匿名内部类界说成list()的一个参数,使其显得越发精简。如下所示:
 

//: DirList3.java
// Building the anonymous inner class "in-place"
import java.io.*;

public class DirList3 {
  public static void main(final String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else 
        list = path.list(
          new FilenameFilter() {
            public boolean 
            accept(File dir, String n) {
              String f = new File(n).getName();
              return f.indexOf(args[0]) != -1;
            }
          });
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~

main()此刻的自变量是final,因为匿名内部类直接利用args[0]。
这展示了如何操作匿名内部类快速建设精简的类,以便办理一些巨大的问题。由于Java中的所有对象都与类有关,所以它无疑是一种相当有用的编码技能。它的一个长处是将特定的问题断绝在一个处所统一办理。但在另一方面,这样生成的代码不是十分容易阅读,所以利用时必需慎重。

2. 顺序目次列表
常常都需要文件名以排好序的方法提供。由于Java 1.0和Java 1.1都没有提供对排序的支持(从Java 1.2开始提供),所以必需用第8章建设的SortVector将这一本领直接插手本身的措施。就象下面这样:
 

//: SortedDirList.java
// Displays sorted directory listing
import java.io.*;
import c08.*;

public class SortedDirList {
  private File path;
  private String[] list;
  public SortedDirList(final String afn) {
    path = new File(".");
    if(afn == null)
      list = path.list();
    else
      list = path.list(
          new FilenameFilter() {
            public boolean 
            accept(File dir, String n) {
              String f = new File(n).getName();
              return f.indexOf(afn) != -1;
            }
          });
    sort();
  }
  void print() {
    for(int i = 0; i < list.length; i++)
      System.out.println(list[i]);
  }
  private void sort() {
    StrSortVector sv = new StrSortVector();
    for(int i = 0; i < list.length; i++)
      sv.addElement(list[i]);
    // The first time an element is pulled from
    // the StrSortVector the list is sorted:
    for(int i = 0; i < list.length; i++)
      list[i] = sv.elementAt(i);
  }
  // Test it:
  public static void main(String[] args) {
    SortedDirList sd;
    if(args.length == 0)
      sd = new SortedDirList(null);
    else
      sd = new SortedDirList(args[0]);
    sd.print();
  }
} ///:~

这里举办了别的少许改造。不再是将path(路径)和list(列表)建设为main()的当地变量,它们酿成了类的成员,使它们的值能在工具“保留”期间利便地会见。事实上,main()此刻只是对类举办测试的一种方法。各人可以看到,一旦列表建设完毕,类的构建器就会自动开始对列表举办排序。
这种排序不要求区分巨细写,所以最终不会获得一组全部单词都以大写字母开头的列表,随着是全部以小写字母开头的列表。然而,我们留意到在以沟通字母开头的一组文件名中,大写字母是排在前面的——这对尺度的排序来说仍是一种不及格的行为。Java 1.2已乐成办理了这个问题。

 

    关键字:

天才代写-代写联系方式