I'm trying to understand arguments with respect to anonymous classes. The examples in books I've seen either don't have arguments or else don't explain them well. Here's the code (from Java in a Nutshell 2nd edition example 5-8 and yes I know it's old :-)...
import java.io.*;
//Print out all the *.java files in the directory.
public static void main(String[] args)
{
File f = new File(args[0]);
String[] list = f.list(new FilenameFilter() {
public boolean accept(File f, String s) {
return s.endsWith(".java");
}
});
for (int i = 0; i < list.length; i++)
System.out.println(list[i]);
}
}
My question开发者_如何学运维s is how the filename f gets applied to the 'File f' argument of 'accept', and also where does the 'String s' argument come from? Why does the 'accept' method get called, is it from the FilenameFilter constructor perhaps?
Thanks!if you take a look into the source files of the java api, you will find following in File.java:
public String[] list(FilenameFilter filter) {
String names[] = list();
if ((names == null) || (filter == null)) {
return names;
}
List<String> v = new ArrayList<>();
for (int i = 0 ; i < names.length ; i++) {
if (filter.accept(this, names[i])) {
v.add(names[i]);
}
}
return v.toArray(new String[v.size()]);
}
which calls the accept method of the given filename filter. String s is in your example names[i]
.
list()
returns an array of strings naming the files and directories in the directory denoted by the files pathname.
to explain your code:
String[] list = f.list(new FilenameFilter() {
public boolean accept(File f, String s) {
return s.endsWith(".java");
}
});
calls the list method of the File class (see above) with a new anonymous class of the FilenameFilter interface with an implementation of the accept method.
Unfortunate coincidence. The two f's have nothing to do with each other: The parameter to accept
is independent from, and has nothing to do with, the local variable in the method.
The code is confusing. It should be this:
File f = new File(args[0]);
String[] list = f.list(new FilenameFilter() {
public boolean accept(File file, String s) {
return s.endsWith(".java");
}
});
The accept
method of the FilenameFilter
is called from within the File.list
method.
FilenameFilter is an interface. When you do new FileNameFilter()
you create a new implementation of this interface.
You could have created this as a regular class instead of doing it inline in your code.
The list
method of File
calls the accept
method of the FilenameFilter
object you pass to it for each file it finds in the directory.
The tricky thing here is that you create a FilenameFilter but with a specific accept
method which is then passed to f.list(FilenameFilter filenameFilter)
.
The code in f.list
knows how to call the accept method in the FilenameFilter with the current file (File f) and its name (String s) for each file considered to determine if the current candidate should be in the result or not.
The File f = new File(args[0])
is unrelated to the File f
argument to accept(...)
. They just have the same name in your code.
In other words, you create your own one-shot FilenameFilter subclass with an accept
overriden, and do it where it is used. The accept method takes two arguments which File.list()
knows how to provide.
Both parameter are given by the list
method when it calls accept()
on the instance of FilenameFilter
anonymous class you passed to it.
Raw flow:
- You call
list()
onf
. - list() checks whether each file meets the given filter (your anonymous class) by calling its
accept
method with two parameters, the file (File f)and its name (String s) - Your implementation of
accept()
decide whether this file should be accepted or not.
精彩评论