File是用于表示或者说映射实际文件系统对象,如文件或目录。这样java代码就能操作计算机上的文件系统对象了。像setReadOnly()方法等一看就是设置该文件对象为只读。

File类的实例是不可变的;也就是说,一旦创建,File对象表示的抽象路径名将永不改变。

 

 

File类内部维护一个FileSystem接口的实现类,这个实现类非常重要,File许多方法的具体操作都是由这个FileSystem实现类完成的。不同操作系统文件系统不一样,那各自的JDK的FileSystem实现类也自然不一样。我用的是Windows系统,它的实现类就是WinNTFileSystem。

 

File类主要由两个属性path、prefixLength。代表文件对象路径,以及前缀长度(这个前缀长度表示了路径是绝对还是相对的)。新建一个File实例时就是调用FileSystem实现类来操作这两个属性、

 

public File(String pathname) {
        if (pathname == null) {
            throw new NullPointerException();
        }
//将路径标准化(比如规范路径字符串之间的分隔符等)
        this.path = fs.normalize(pathname);
//判断前缀长度
        this.prefixLength = fs.prefixLength(this.path);
    }

 

 

想看着个File对象到底对应文件系统哪个对象,可以调用getAbsolutePath()方法查看

 

public String getAbsolutePath() {
        return fs.resolve(this);
    }


//WinNTFileSystem中resolve方法
public String resolve(File f) {
        String path = f.getPath();
        int pl = f.getPrefixLength();
        if ((pl == 2) && (path.charAt(0) == slash))
            return path;                        /* UNC */
        if (pl == 3)
            return path;                        /* Absolute local */
        if (pl == 0)
            return getUserPath() + slashify(path); /* Completely relative */
        if (pl == 1) {                          /* Drive-relative */
            String up = getUserPath();
            String ud = getDrive(up);
            if (ud != null) return ud + path;
            return up + path;                   /* User dir is a UNC path */
        }
        if (pl == 2) {                          /* Directory-relative */
            String up = getUserPath();
            String ud = getDrive(up);
            if ((ud != null) && path.startsWith(ud))
                return up + slashify(path.substring(2));
            char drive = path.charAt(0);
            String dir = getDriveDirectory(drive);
            String np;
            if (dir != null) {
                /* When resolving a directory-relative path that refers to a
                   drive other than the current drive, insist that the caller
                   have read permission on the result */
                String p = drive + (':' + dir + slashify(path.substring(2)));
                SecurityManager security = System.getSecurityManager();
                try {
                    if (security != null) security.checkRead(p);
                } catch (SecurityException x) {
                    /* Don't disclose the drive's directory in the exception */
                    throw new SecurityException("Cannot resolve path " + path);
                }
                return p;
            }
            return drive + ":" + slashify(path.substring(2)); /* fake it */
        }
        throw new InternalError("Unresolvable path: " + path);
    }

 可以看到当前缀长度为3时,表示生成对象时使用绝对路径(暂称为传递路径),FIle对象对应文件系统对象的路径就是标准化后的传递路径

前缀长度为1时,传递路径为带斜杠的相对路径,那对应文件系统对象的路径就是工作目录(什么是工作目录后面解释)的根目录(即所在盘符位置)+标准化的传递路径

前缀长度为0时,传递路径为不带斜杠的相对路径,对应文件系统对象路径就是标准化后的工作目录+标准化的传递路径

 

 

工作目录即System.getProperty('user.dir')的值。这个值就是调用java命令的目录,比如cmd中执行一个class文件,值就是执行命令时所在目录。而在tomcat运行web项目,一般是tomcat目录/bin/startup.bat调用命令,则值就是bin目录。

如果是eclipse 新建的tomcat server ,默认为Working Directory ----- eclipse的目录,可以设置 eclipse下右击tomcat server 点击Open(有可能需要先stop)General Information 下的Open Lauch Configuration的Working directory 设置该路径

idea运行web应用时值默认是配置的tomcat server的bin目录,idea运行java应用时值默认是项目所在目录位置,当然可以通过Edit Configuration中的Working directory来配置