java关于File类源码的详细分析 附代码(全)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 添加链接描述磁驱动分割符中,在unix中使用/表示,在window中使用\\\查看其源码,实现Serializable,Comparable的接口java之序列化与反序列化的详细解析(全)javaSE从入门到精通的二十万字总结(二)

前言

磁驱动分割符中,在unix中使用/表示,在window中使用\\\

查看其源码,实现Serializable, Comparable的接口

public class File
    implements Serializable, Comparable<File>
{

对于Serializable的具体功能可看我这篇文章:java之序列化与反序列化的详细解析(全)
对于Comparable的接口可看我这篇文章稍微提及的知识点:javaSE从入门到精通的二十万字总结(二)

1. 属性

其具体属性定义如下:

// 文件系统对象
// 后面很多方法也用到了文件系统类的方法,比如系统创建文件的时间等,这里简称fs,后面多处都用到了
private static final FileSystem fs = DefaultFileSystem.getFileSystem();

// 路径名
private final String path;

// 枚举类型
// file类对象的地址是否合法通过枚举类判定
private static enum PathStatus { INVALID, CHECKED };

// 文件路径是否有效
private transient PathStatus status = null;
// 检查路径是否有效 但只涉及nul字符,true绝对无效,false不一定有效
final boolean isInvalid() {
    if (status == null) {
        status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                   : PathStatus.INVALID;
    }
    return status == PathStatus.INVALID;
}

// 路径名前缀长度
private final transient int prefixLength;
int getPrefixLength() {
    return prefixLength;
}

// 依赖系统分隔符
public static final char separatorChar = fs.getSeparator();
// 将其转换为字符串表示
public static final String separator = "" + separatorChar;

2. 构造函数

函数 描述
public File(String pathname) 创建路径名实例
public File(String parent, String child) 父+子路径 创建实例
public File(URI uri) 根据URI 路径创建一个新的 File 实例

源码如下:(部分已加注释, 可配合下方的具体例子理解)

private File(String pathname, int prefixLength) {
    this.path = pathname;
    this.prefixLength = prefixLength;
}

private File(String child, File parent) {
    assert parent.path != null;
    assert (!parent.path.equals(""));
    this.path = fs.resolve(parent.path, child);
    this.prefixLength = parent.prefixLength;
}

// 路径名
public File(String pathname) {
    if (pathname == null) {
        throw new NullPointerException();
    }
    this.path = fs.normalize(pathname);
    this.prefixLength = fs.prefixLength(this.path);
}

/* 从父路径名字符串和子路径名字符串创建新的文件实例。

如果parent为null,则将通过调用给定子路径名字符串上的单参数文件构造函数来创建新的文件实例。

否则,父路径名字符串表示目录,子路径名字符串表示目录或文件。如果子路径名字符串是绝对的,则会以系统相关的方式将其转换为相对路径名。如果parent是空字符串,则通过将child转换为抽象路径名并根据系统相关的默认目录解析结果来创建新的文件实例。否则,每个路径名字符串将转换为抽象路径名,子抽象路径名将根据父路径名进行解析

*/
public File(String parent, String child) {
    if (child == null) {
        throw new NullPointerException();
    }
    if (parent != null) {
        if (parent.equals("")) {
            this.path = fs.resolve(fs.getDefaultParent(),
                                   fs.normalize(child));
        } else {
            this.path = fs.resolve(fs.normalize(parent),
                                   fs.normalize(child));
        }
    } else {
        this.path = fs.normalize(child);
    }
    this.prefixLength = fs.prefixLength(this.path);
}

// 同上,注意区别
public File(File parent, String child) {
    if (child == null) {
        throw new NullPointerException();
    }
    if (parent != null) {
        if (parent.path.equals("")) {
            this.path = fs.resolve(fs.getDefaultParent(),
                                   fs.normalize(child));
        } else {
            this.path = fs.resolve(parent.path,
                                   fs.normalize(child));
        }
    } else {
        this.path = fs.normalize(child);
    }
    this.prefixLength = fs.prefixLength(this.path);
}

// 根据URI 路径创建一个新的 File 实例
public File(URI uri) {

    // Check our many preconditions
    if (!uri.isAbsolute())
        throw new IllegalArgumentException("URI is not absolute");
    if (uri.isOpaque())
        throw new IllegalArgumentException("URI is not hierarchical");
    String scheme = uri.getScheme();
    if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
        throw new IllegalArgumentException("URI scheme is not \"file\"");
    if (uri.getAuthority() != null)
        throw new IllegalArgumentException("URI has an authority component");
    if (uri.getFragment() != null)
        throw new IllegalArgumentException("URI has a fragment component");
    if (uri.getQuery() != null)
        throw new IllegalArgumentException("URI has a query component");
    String p = uri.getPath();
    if (p.equals(""))
        throw new IllegalArgumentException("URI path component is empty");

    // Okay, now initialize
    p = fs.fromURIPath(p);
    if (File.separatorChar != '/')
        p = p.replace('/', File.separatorChar);
    this.path = fs.normalize(p);
    this.prefixLength = fs.prefixLength(this.path);
}

具体实现代码如下:

public class file {
    public static void main(String [] args){
        // 这样子会出错
        // File file = new File();
        
        File file = new File("");
        System.out.println(file); // 输出为空

        File file1 = new File("manongyanjiuseng");
        System.out.println(file1); // 输出manongyanjiuseng

        /*----------------父路径 + 子路径构造函数------------*/
        
        // manong为父路径名字 ,yanjiuseng 为子路径名字
        // 父路径不为空的时候,既通过父+子路径的拼接
        File file2 = new File("manong","yanjiuseng");
        System.out.println(file2); // 输出manongyanjiuseng
        
        // 如果父路径为空的时候,既通过输出子路径创建实例即可
        String parent = null;
        File file3 = new File(parent, "manongyanjisueng");
        System.out.println(file3);// 输出manongyanjiuseng
        
        // 如果子路径为空,后面跟着null,空指针就会抛出异常
        String child = null;
        File file4 = new File("manongyanjisueng", child);
        System.out.println(file4);// 抛出异常
        // 异常 Exception in thread "main" java.lang.NullPointerException
    }
}

结果输出如下:
在这里插入图片描述
最后一种构造函数比较特殊 单独拎出来
根据URI 路径创建一个新的 File 实例

public class file {
    public static void main(String [] args){
        File file5;
        try {
            file5 = new File(new URI("file:///C:/Users/13399/Desktop"));
            System.out.println(file5.getName());// 输出 Desktop
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
}       

截图如下:
在这里插入图片描述

3. 方法

函数 描述
getName() 获取文件名
getParent() 获取上级目录
getParentFile() 默认 以上级目录为父路径创建实例
getPath() 输出文件实际路径
isAbsolute() 是否以window系统的磁盘文件
getAbsolutePath() 获取文件的绝对路径
exists() 实例的file类对象是否存在
isFile() 是否为文件
isDirectory() 是否为目录
createNewFile() 创建文件
mkdir() 创建(前提是父目录存在)单目录true,文件false
mkdirs() 可创建多级目录,即使单目录也可,区分一点就是,父目录不存在也可创建
delete() 删除文件或者文件夹(文件夹必须为空才可删除)

使用方法,按照惯例,先看一波源码(已加注释)

3.1 常用方法

常用方法源码具体如下(已加上注释):

// 返回文件或者目录的名称
public String getName() {
    // public static final char separatorChar = fs.getSeparator();
    // 此处的separatorChar 为系统分割符号,也就是获取最后一个分割符的名字
    int index = path.lastIndexOf(separatorChar);
    // 判断下,防止异常
    if (index < prefixLength) return path.substring(prefixLength);
    return path.substring(index + 1);
}

// 获取上级目录
// 代码注释跟上面一样,唯一的区别在于获取上级目录,所以通过substring截取即可
public String getParent() {
    int index = path.lastIndexOf(separatorChar);
    if (index < prefixLength) {
        if ((prefixLength > 0) && (path.length() > prefixLength))
            // 截取上级目录的关键部分
            return path.substring(0, prefixLength);
        return null;
    }
    return path.substring(0, index);
}

// 获取上级目录之后在实例对象
public File getParentFile() {
    // 通过this指针获取上级目录
    String p = this.getParent();
    if (p == null) return null;
    if (getClass() != File.class) {
        p = fs.normalize(p);
    }
    return new File(p, this.prefixLength);
}

// 返回路径,抽象路径的字符串形式
public String getPath() {
   return path;
}

// 测试是否是绝对路径
/* 在 UNIX 系统上,如果路径名的前缀为“/”,则该路径名是绝对的。
在 Microsoft Windows 系统上,如果路径名的前缀是后跟“”的驱动器说明符,
或者其前缀是“”,则路径名是绝对的 */
public boolean isAbsolute() {
   return fs.isAbsolute(this);
}

// 获取绝对路径
public String getAbsolutePath() {
   return fs.resolve(this);
}

// 获取绝对路径,相当于new File(this.getAbsolutePath)
// 注意与上面的区别,一个是file类一个是String类
public File getAbsoluteFile() {
    String absPath = getAbsolutePath();
    if (getClass() != File.class) {
        // 给定的路径字符串转换为正常形式,如果字符串已经是正常形式 无需转换 
        absPath = fs.normalize(absPath);
    }
    return new File(absPath, fs.prefixLength(absPath));
}

对于上面的normalize格式化函数
有如下三个源代码函数

public String normalize(String path)
private String normalize(String path, int len, int off)
private int normalizePrefix(String path, int len, StringBuilder sb)

内部函数代码用到的变量

// 区分系统盘符
slash = props.getProperty("file.separator").charAt(0);
altSlash = (this.slash == '\\') ? '/' : '\\';

核心代码如下 浅显易懂就post图出来
在这里插入图片描述

==是否存在、被隐藏、读取修改等源码==
源代码如下:

// FileSystem类 属性
/* Constants for simple boolean attributes */
@Native public static final int BA_EXISTS    = 0x01;
@Native public static final int BA_REGULAR   = 0x02;
@Native public static final int BA_DIRECTORY = 0x04;
@Native public static final int BA_HIDDEN    = 0x08;

// 判断文件或者路径是否存在
public boolean exists() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(path);
    }
    if (isInvalid()) {
        return false;
    }
    return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
}


// 判断此抽象路径名表示的是否为目录
public boolean isDirectory() {
  // 代码同exists()函数
    return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
            != 0);
}

// 判断此抽象路径名表示的是否为文件
public boolean isFile() {
    // 代码同exists()函数
    return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
}

// 路径名命名的文件是否为隐藏文件,取决于操作系统
public boolean isHidden() {
     // 代码同exists()函数
     return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
 }

文件是否被读取修改等权限源码:
关于下面这个注解可看我之前的文章:Springboot中@SuppressWarnings注解详细解析
主要为了屏蔽一些错误警告,但不是代码错误警告

// FileSystem类 属性
@Native public static final int ACCESS_READ    = 0x04;
@Native public static final int ACCESS_WRITE   = 0x02;
@Native public static final int ACCESS_EXECUTE = 0x01;

// 文件或者目录可否被读取
public boolean canRead() {
    @SuppressWarnings("removal")
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(path);
    }
    if (isInvalid()) {
        return false;
    }
    return fs.checkAccess(this, FileSystem.ACCESS_READ);
}

// 文件或者目录可否被修改
public boolean canWrite() {
    @SuppressWarnings("removal")
    // 代码同上
    if (security != null) {
        security.checkWrite(path);
    }
    // ...
    return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
}

// 文件或者目录可否被执行
public boolean canExecute() {
    @SuppressWarnings("removal")
   // 代码同上
    if (security != null) {
        security.checkExec(path);
    }
    // ...
    return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
}

以及最后的修改时间lastModified,长度length

public long lastModified() {
    @SuppressWarnings("removal")
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkRead(path);
    }
    if (isInvalid()) {
        return 0L;
    }
    
    // 获取的系统文件时间 
    // 等同于 调用的最终函数 public native long getLastModifiedTime(File f);
    return fs.getLastModifiedTime(this);
}

// 路径名表示的文件的长度。如果此路径名表示目录,则返回值未指定
public long length() {
    @SuppressWarnings("removal")
    // 省略代码,同lastModified函数
    
    // 获取系统文件长度
    // 等同于 调用的最终函数 public native long getLength(File f);
    return fs.getLength(this);
}

具体例子如下:

import java.io.IOException;
import java.io.File;
public class file {
    public static void main(String [] args){
        File file = new File("C:/Users/13399/Desktop");
        // 输出文件名
        System.out.println(file.getName()); // Desktop

        // 输出上级目录
        System.out.println(file.getParent()); // C:\Users\13399

        File file1 = new File("C:/Users/13399","Desktop");
        // 未指定父路径,默认以上级目录为父路径创建实例
        System.out.println(file.getParentFile()); // C:\Users\13399
        // 指定父路径,则以父路径创建实例
        System.out.println(file1.getParentFile()); // C:\Users\13399

        // 输出文件实际路径
        System.out.println(file.getPath()); // C:\Users\13399\Desktop

        // 是否以window系统的磁盘文件
        System.out.println(file.isAbsolute()); // true

        // 获取文件的绝对路径
        System.out.println(file.getAbsolutePath()); // C:\Users\13399\Desktop

        // 实例的file类对象是否存在
        System.out.println(file.exists()); // true

        //  是否为文件
        System.out.println(file.isFile()); // false

        // 是否为目录
        System.out.println(file.isDirectory()); // true

        // 创建新文件,只有文件不存在的时候才可以创建
        try {
            System.out.println(file.createNewFile()); // false 已存在无需创建
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 删除,为空的时候才可以删除
        System.out.println(file.delete()); // false
    }
}

==创建、删除操作源码==

// 创建文件
public boolean createNewFile() throws IOException {
    SecurityManager security = System.getSecurityManager();
    if (security != null) security.checkWrite(path);
    if (isInvalid()) {
        throw new IOException("Invalid file path");
    }
    // 获取系统文件长度
    // 等同于 调用的最终函数 public native boolean createFileExclusively(String path) throws IOException;
    return fs.createFileExclusively(path);
}

/*
删除此抽象路径名所表示的文件或目录。
如果此路径名表示一个目录,则该目录必须为空才能删除
*/
public boolean delete() {
    @SuppressWarnings("removal")
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkDelete(path);
    }
    if (isInvalid()) {
        return false;
    }
    return fs.delete(this);
}

/*
请求在虚拟机终止时删除此抽象路径名所表示的文件或目录。
文件(或目录)的删除顺序与注册顺序相反。
调用此方法删除已注册删除的文件或目录不起作用。只有在虚拟机正常终止时才会尝试删除
*/
public void deleteOnExit() {
    @SuppressWarnings("removal")
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkDelete(path);
    }
    if (isInvalid()) {
        return;
    }
    DeleteOnExitHook.add(path);
}

// 创建以此抽象路径名命名的目录
public boolean mkdir() {
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(path);
    }
    if (isInvalid()) {
        return false;
    }
    // 此为Filesystem类下的抽象方法
    return fs.createDirectory(this);
}

// 由该路径名命名的目录
public boolean mkdirs() {
    if (exists()) {
        return false;
    }
    if (mkdir()) {
        return true;
    }
    File canonFile = null;
    try {
    // 返回此抽象路径名的规范形式
        canonFile = getCanonicalFile();
    } catch (IOException e) {
        return false;
    }
    // 返回此抽象路径名的父目录的抽象路径名,如果此路径名未命名父目录,则返回null
    File parent = canonFile.getParentFile();
    return (parent != null && (parent.mkdirs() || parent.exists()) &&
            canonFile.mkdir());
}

对于创建文件、单目录、多目录、删除操作都是由File类新建对象来决定的

File file = new File("???")

mkdir的例子具体如下:

// 原路径为C:/Users/13399/Desktop
File file3 = new File("C:/Users/13399/Desktop/11"); 
System.out.println(file3.mkdir()); // 创建11目录,成功创建为true

// 原路径为C:/Users/13399/Desktop
File file4 = new File("C:/Users/13399/Desktop/11.txt");
System.out.println(file4.mkdir()); // 创建的11.txt为文件,则为false,不成功

// 无法创建不存在的多级目录 或者 不存在的父目录下创建 

mkdirs的例子具体如下:

// 原路径为C:/Users/13399/Desktop
File file3 = new File("C:/Users/13399/Desktop/13");
System.out.println(file3.mkdirs()); // 创建13目录,成功创建为true

// 原路径为C:/Users/13399/Desktop
File file4 = new File("C:/Users/13399/Desktop/13.txt");
System.out.println(file4.mkdirs()); // 创建的13.txt为文件,也可创建,为true

// 创建不存在的多级目录 也可创建成功

==遍历列表源码==

// 返回一个数组表示文件
public File[] listFiles() {
    String[] ss = normalizedList();
    if (ss == null) return null;
    int n = ss.length;
    File[] fs = new File[n];
    for (int i = 0; i < n; i++) {
        fs[i] = new File(ss[i], this);
    }
    return fs;
}

// 这个与上面的不同,多了一个filter 主要是过滤
public File[] listFiles(FilenameFilter filter) {
    String ss[] = normalizedList();
    if (ss == null) return null;
    ArrayList<File> files = new ArrayList<>();
    for (String s : ss)
        // 区别在于这个核心代码中,filter为null 或者对应过滤相应文件,this表示当前路径
        // accept 主要是 测试是否应将指定的文件包含在文件列表中
        // 核心函数 boolean accept(File dir, String name); 重构这个函数即可
        if ((filter == null) || filter.accept(this, s))
            files.add(new File(s, this));
    return files.toArray(new File[files.size()]);
}

// 注意与上方函数模块的不同
public File[] listFiles(FileFilter filter) {
    String ss[] = normalizedList();
    if (ss == null) return null;
    ArrayList<File> files = new ArrayList<>();
    for (String s : ss) {
        File f = new File(s, this);
        //测试指定的抽象路径名是否应包含在路径名列表中
        // 核心函数 boolean accept(File pathname);重构这个函数即可
        if ((filter == null) || filter.accept(f))
            files.add(f);
    }
    return files.toArray(new File[files.size()]);
}

具体示例代码如下:
为了对比不同,此处引入list返回的是String类型

File file = new File("C:/Users/13399/Desktop/13");

System.out.println(Arrays.toString(file.list())); // 输出目录中各个文件名
System.out.println(Arrays.toString(file.listFiles())); // 输出目录中各个文件的绝对路径

// 查看源码可得知 重构函数即可
// 区分list 返回值 String[] list = file.list(
File[] list = file.listFile((File dir, String name) ->name.endsWith(".xml") // 筛选过滤出.xml文件,之后输出这个文件的绝对路径
);
System.out.println(Arrays.toString(list));

// 区别在于重构函数不同
File[] list1 = file.listFiles((File dir, String name) -> name.endsWith(".xml")); // 筛选过滤出.xml文件,之后输出这个文件的绝对路径
System.out.println(Arrays.toString(list1));

3.2 磁盘与临时文件

==磁盘文件源码==

/* -- Disk usage -- */
@Native public static final int SPACE_TOTAL  = 0;
@Native public static final int SPACE_FREE   = 1;
@Native public static final int SPACE_USABLE = 2;

// 返回由此抽象路径名命名的分区的大小
// 分区的大小(以字节为单位),如果此抽象路径名未命名分区,则为0L
public long getTotalSpace() {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
        sm.checkRead(path);
    }
    if (isInvalid()) {
        return 0L;
    }
    return fs.getSpace(this, FileSystem.SPACE_TOTAL);
}


// 此抽象路径名命名的分区中未分配的字节数 注意区别,就一行代码不同
public long getFreeSpace() {
    // 代码同getTotalSpace()
    return fs.getSpace(this, FileSystem.SPACE_FREE);
}

// 返回此抽象路径名命名的分区上此虚拟机可用的字节数 注意区别,就一行代码不同
public long getUsableSpace() {
    // 代码同getTotalSpace()
    return fs.getSpace(this, FileSystem.SPACE_USABLE);
}

==临时文件源码==

private static class TempDirectory {
    private TempDirectory() { }

    // temporary directory location
    private static final File tmpdir = new File(AccessController
        .doPrivileged(new GetPropertyAction("java.io.tmpdir")));
    static File location() {
        return tmpdir;
    }

    // file name generation
    private static final SecureRandom random = new SecureRandom();
    static File generateFile(String prefix, String suffix, File dir)
        throws IOException
    {
        long n = random.nextLong();
        if (n == Long.MIN_VALUE) {
            n = 0;      // corner case
        } else {
            n = Math.abs(n);
        }

        // Use only the file name from the supplied prefix
        prefix = (new File(prefix)).getName();

        String name = prefix + Long.toString(n) + suffix;
        File f = new File(dir, name);
        if (!name.equals(f.getName()) || f.isInvalid()) {
            if (System.getSecurityManager() != null)
                throw new IOException("Unable to create temporary file");
            else
                throw new IOException("Unable to create temporary file, " + f);
        }
        return f;
    }
}

/*
指定目录创建新的空文件,使用给定的前缀和后缀字符串生成器名称,成功即返回
*/
public static File createTempFile(String prefix, String suffix,
                                      File directory)
    throws IOException
{
    // 前缀长度小于3 会抛出异常,必须至少是3的长度以上
    if (prefix.length() < 3) {
        throw new IllegalArgumentException("Prefix string \"" + prefix +
            "\" too short: length must be at least 3");
    }
    // 如果后缀为null,则默认给予赋值
    if (suffix == null)
        suffix = ".tmp";
    
    // 判断目录是否为空,为空则创建一个临时的文件目录
    // 具体文件目录有系统决定,unix默认值为 /tmp 或 /var/tmp,windiow下为C:WINNTTEMP
    File tmpdir = (directory != null) ? directory
                                      : TempDirectory.location();

    @SuppressWarnings("removal")
    // 次函数与安全管理器有关
    SecurityManager sm = System.getSecurityManager();
    File f;
    do {
    // 该方法调用在上方
        f = TempDirectory.generateFile(prefix, suffix, tmpdir);

        if (sm != null) {
            try {
                sm.checkWrite(f.getPath());
            } catch (SecurityException se) {
                // don't reveal temporary directory location
                if (directory == null)
                    throw new SecurityException("Unable to create temporary file");
                throw se;
            }
        }
    } while (fs.hasBooleanAttributes(f, FileSystem.BA_EXISTS));

    if (!fs.createFileExclusively(f.getPath()))
        throw new IOException("Unable to create temporary file");

    return f;
}

/*
默认临时文件目录中创建一个空文件, 并使用给定的前缀和后缀生成其名称
调用此方法等效于调用 createTempFile(前缀、后缀、空值)
通过该方法创建的文件可能对此方法创建的文件具有更严格的访问权限
因此可能更适合安全敏感的应用程序
*/
public static File createTempFile(String prefix, String suffix)
    throws IOException
{
    return createTempFile(prefix, suffix, null);
}

3.3 其他

基本的方法函数源码:

// 比较两个抽象路径名,通过字典顺序的方法
// 具体比较还是根据操作系统,毕竟unix字母大小写很重要
public int compareTo(File pathname) {
   return fs.compare(this, pathname);
}

// 测试路径名与给定的对象是否相等,是否相等取决于操作系统
public boolean equals(Object obj) {
    // instanceof 判断是否是这个实例对象
    if (obj instanceof File file) {
        return compareTo(file) == 0;
    }
    return false;
}

// 哈希码
public int hashCode() {
   return fs.hashCode(this);
}

// 返回路径名,只不过通过getPath返回字符串
public String toString() {
   return getPath();
}

以上代码都是基本的代码,没什么特殊之处

源码部分中还跟其他的类集成源码:

// 保存文件名以及分隔符,不同系统如果不同的时候可以重建,并且替换
@java.io.Serial
private synchronized void writeObject(java.io.ObjectOutputStream s)
    throws IOException
{
    s.defaultWriteObject();
    s.writeChar(separatorChar); // Add the separator character
}

// 读取文件名以及原始分割符,如果与系统分割符不同,则用旧的替换当前的
@java.io.Serial
private synchronized void readObject(java.io.ObjectInputStream s)
     throws IOException, ClassNotFoundException
{
    ObjectInputStream.GetField fields = s.readFields();
    String pathField = (String)fields.get("path", null);
    char sep = s.readChar(); // read the previous separator char
    if (sep != separatorChar)
        pathField = pathField.replace(sep, separatorChar);
    String path = fs.normalize(pathField);
    UNSAFE.putReference(this, PATH_OFFSET, path);
    UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));
}

// 集成java.nio.file
private transient volatile Path filePath;

// 返回相同的path,如果为空路径名,则可用于访问当前用户目录的 Path
public Path toPath() {
    Path result = filePath;
    if (result == null) {
        synchronized (this) {
            result = filePath;
            if (result == null) {
                result = FileSystems.getDefault().getPath(path);
                filePath = result;
            }
        }
    }
    return result;
}

对于上面toPath()这个方法中用到的synchronized关键字
可看我这篇文章:java并发之synchronized详细分析(全)
抽象出来,类似设计模式中的单例:JAVA设计模式之单例模式详细分析(全)

    public String getAbsolutePath(String filename){
        File file = new File(filename);
        return file.getAbsolutePath().trim().replaceAll("\\\\", "/");
    }
相关文章
|
8天前
|
数据采集 运维 前端开发
【Java】全套云HIS源码包含EMR、LIS (医院信息化建设)
系统技术特点:采用前后端分离架构,前端由Angular、JavaScript开发;后端使用Java语言开发。
29 5
|
10天前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
27 1
|
10天前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
23 0
java基础(13)String类
|
4天前
|
Java API
Java的日期类都是怎么用的
【10月更文挑战第1天】本文介绍了 Java 中处理日期和时间的三个主要类:`java.util.Date`、`java.util.Calendar` 和 `java.time` 包下的新 API。`Date` 类用于表示精确到毫秒的瞬间,可通过时间戳创建或获取当前日期;`Calendar` 抽象类提供丰富的日期操作方法,如获取年月日及时区转换;`java.time` 包中的 `LocalDate`、`LocalTime`、`LocalDateTime` 和 `ZonedDateTime` 等类则提供了更为现代和灵活的日期时间处理方式,支持时区和复杂的时间计算。
26 14
|
6天前
|
传感器 监控 数据可视化
【Java】智慧工地解决方案源码和所需关键技术
智慧工地解决方案是一种新的工程全生命周期管理理念。它通过使用各种传感器、数传终端等物联网手段获取工程施工过程信息,并上传到云平台,以保障数据安全。
30 7
|
8天前
|
安全 Java 编译器
java访问类字段
java访问类字段
|
10天前
|
Java
java的class类
java的class类
18 5
|
8天前
|
Oracle Java 关系型数据库
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
如果遇到"exec format error"问题,文章建议先检查Linux操作系统是32位还是64位,并确保安装了与系统匹配的JDK版本。如果系统是64位的,但出现了错误,可能是因为下载了错误的JDK版本。文章提供了一个链接,指向Oracle官网上的JDK 17 Linux版本下载页面,并附有截图说明。
Linux下JDK环境的配置及 bash: /usr/local/java/bin/java: cannot execute binary file: exec format error问题的解决
|
11天前
|
Java 数据处理
Java Scanner 类详解
`Scanner` 类是 Java 中 `java.util` 包提供的强大工具,用于从多种输入源(如键盘、文件、字符串)读取数据。本文详细介绍如何创建 `Scanner` 对象并使用其常用方法(如 `next()`, `nextInt()`, `nextLine()` 等)。通过示例代码展示如何从标准输入、字符串及文件中读取数据,并进行输入验证。使用时需注意关闭 `Scanner` 以释放资源,并确保输入类型匹配,避免异常。掌握 `Scanner` 可显著提升程序的数据处理能力。
|
6天前
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
21 2
下一篇
无影云桌面