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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 添加链接描述磁驱动分割符中,在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("\\\\", "/");
    }
相关文章
|
17天前
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
53 7
|
28天前
|
数据采集 人工智能 Java
Java产科专科电子病历系统源码
产科专科电子病历系统,全结构化设计,实现产科专科电子病历与院内HIS、LIS、PACS信息系统、区域妇幼信息平台的三级互联互通,系统由门诊系统、住院系统、数据统计模块三部分组成,它管理了孕妇从怀孕开始到生产结束42天一系列医院保健服务信息。
30 4
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
72 2
|
9天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
60 13
|
22天前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
51 12
|
17天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
22天前
|
监控 算法 Java
jvm-48-java 变更导致压测应用性能下降,如何分析定位原因?
【11月更文挑战第17天】当JVM相关变更导致压测应用性能下降时,可通过检查变更内容(如JVM参数、Java版本、代码变更)、收集性能监控数据(使用JVM监控工具、应用性能监控工具、系统资源监控)、分析垃圾回收情况(GC日志分析、内存泄漏检查)、分析线程和锁(线程状态分析、锁竞争分析)及分析代码执行路径(使用代码性能分析工具、代码审查)等步骤来定位和解决问题。
|
28天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
45 8
|
28天前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
64 1
|
1月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。