如何在Java中使用泛型作为参数使用两个接口?

时间:2014-08-16 12:39:41

标签: java generics interface

我试图将两个接口包装在一个中,而不必使用每个接口重写每个方法。我搜索了很多,但我不知道怎么能这样做:

class ApplyFilter
{

  public static File[] filter (File directory, FileFilterORFilenameFilter filterWrapper)
  {
    return directory.listenFiles(filterWrapper);
  }

}

我尝试创建一个实现两个接口的类,但后来我需要转换变量。我也尝试使用类似这样的类来使用java泛型:

public class CustomFilter<T>
{

  /*  Where we store our filter  */
  private T filter = null;

  /*  The method to return it  */
  public T getFilter ()
  {
    return filter;
  }

  /*  The constructor to define the filter  */
  public CustomFilter (T filt)
  {
    if ( !(filt instanceof FileFilter) || !(filt instanceof FilenameFilter) ) throw new IllegalArgumentException("The argument must be an instance of FilenameFilter or a FileFilter.");
    this.filter = filt;
  }

}

然后我像这样使用它并且它起作用了:

class test
{

  public static void main (String[] args)
  {
    CustomFilter<FileFilter> onlyShowFolders = new CustomFolder<FileFilter>(new FileFilter ()
    {
      @Override
      public boolean accept (File file)
      {
        return file.isDirectory();
      }
    });

    File root = new File("/");
    for (File folder : root.listFiles(onlyShowFolders.getFilter()))
    {
      System.out.print(folder.toPath());
    }
  }

}

但是当我在ApplyFilter类中使用它时,它不起作用。

class ApplyFilter
{

  /*  DOESN'T WORK :(  */
  public static File[] filter (File directory, CustomFilter filterWrapper)
  {
    return directory.listenFiles(filterWrapper.getFilter());
  }

}

提前致谢。

2 个答案:

答案 0 :(得分:2)

你可以像java库本身对File.listFiles所做的那样,即两个具有相同名称和不同参数类型的函数。

class ApplyFilter {

    public static File[] filter(File directory, FileFilter filter) {
        return directory.listFiles(filter);
    }

    public static File[] filter(File directory, FilenameFilter filter) {
        return directory.listFiles(filter);
    }

}

示例持有者类,见注释

public class FilterHolder {
    private FileFilter fileFilter;
    private FilenameFilter filenameFilter;

    public FilterHolder(FileFilter fileFilter) {
        this.fileFilter = fileFilter;
    }

    public FilterHolder(FilenameFilter filenameFilter) {
        this.filenameFilter = filenameFilter;
    }

    public FileFilter getFileFilter() {
        return fileFilter;
    }

    public FilenameFilter getFilenameFilter() {
        return filenameFilter;
    }
}

答案 1 :(得分:2)

它不起作用,因为您省略了编译器最重要的部分,以便编译:

  public static File[] filter (File directory, CustomFilter filterWrapper)
  {
    return directory.listenFiles(filterWrapper.getFilter());
  }

实际的类型表示是:

  public static File[] filter (File directory, CustomFilter<Object> filterWrapper)
  {
    return directory.listenFiles(filterWrapper.getFilter());
  }

然后,它会查找以listenFiles作为单个参数的方法Object

旁边,FilenameFilterFileFilter没有共同的祖先,你不能限制T的类型,如下所示:

public class CustomFilter<T extends FileFilter>
{

  /*  Where we store our filter  */
  private T filter = null;

  /*  The method to return it  */
  public T getFilter () {
    return filter;
  }

  /*  The constructor to define the filter  */
  public CustomFilter (T filt) {
    this.filter = Objects.requireNonNull(filt, "filt");
  }
}

如果您确定始终使用FileFilter,则可能不应使用CustomFilter并坚持使用FileFilter,除非您知道将添加更多功能。但在这种情况下,请CustomFilter实现FileFilter