File类是Java中IO部分的一个类,用于表示文件或者目录的。关于File类有很多的常规操作这里就不介绍了,来看一下不常规的东西。

File英文意思是文件,但是它也可以用来表示目录,文件的概念还是比较广的。

public class File implements Serializable, Comparable<File>

File类实现的Comparable接口

File类实现了Serializable和Comparable接口,可是为什么要实现Comparable接口呢?

/**
* 比较两个抽象路径的字典序. 比较的结果依赖于底层的文件系统.
* 在UNIX上路径是大小写敏感的, 在Microsoft Windows系统上则不是.
*
* @param pathname The abstract pathname to be compared to this abstract
* pathname
*
* @return Zero if the argument is equal to this abstract pathname, a
* value less than zero if this abstract pathname is
* lexicographically less than the argument, or a value greater
* than zero if this abstract pathname is lexicographically
* greater than the argument
*
* @since 1.2
*/
public int compareTo(File pathname) {
return fs.compare(this, pathname);
}

这就要看一下接口中的方法是干啥的。然后这就要和文件系统有关系。

其中有个fs.compare(),这个是文件系统对象的比较方法

File类中有一个关于文件系统的引用

abstract class FileSystem; // 一个抽象类表示文件系统

然后一个类是DefaultFileSystem,这个类中有一个静态方法返回本地默认的文件系统。

class DefaultFileSystem {

    /**
* Return the FileSystem object for Windows platform.
*/
public static FileSystem getFileSystem() {
return new WinNTFileSystem();
}
}

然后这个WinNTFileSystem继承的是抽象的FileSystem:

class WinNTFileSystem extends FileSystem;

WinNTFileSystem的compare方法为:

@Override
public int compare(File f1, File f2) {
return f1.getPath().compareToIgnoreCase(f2.getPath());
}

final和static配合使用

final表示的对象是不可变的,但是有时候我们需要根据情况来初始化final属性。这里在File类中用的方法就是static代码段。

private static final long PATH_OFFSET;
private static final long PREFIX_LENGTH_OFFSET;
private static final sun.misc.Unsafe UNSAFE;
static {
try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
PATH_OFFSET = unsafe.objectFieldOffset(
File.class.getDeclaredField("path"));
PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
File.class.getDeclaredField("prefixLength"));
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}

前面三个final属性没有在定义的时候进行初始化,而是在static代码中进行的。这个可以借鉴一下哦。

文件过滤器

在列举一个目录的文件的时候使用了文件过滤器:

public File[] listFiles(FilenameFilter filter) {
String ss[] = list();
if (ss == null) return null;
ArrayList<File> files = new ArrayList<>();
for (String s : ss)
if ((filter == null) || filter.accept(this, s))
files.add(new File(s, this));
return files.toArray(new File[files.size()]);
}

先是由list方法列举这个文件下所有的文件(包括目录),然后将文件过滤器用于文件的过滤。

这也算一个小的设计模式吧。

文件删除的钩子

这个也可以学习一下,在虚拟机退出的时候如果干一点事的。

在File类中的:

public void deleteOnExit() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkDelete(path);
}
if (isInvalid()) {
return;
}
DeleteOnExitHook.add(path);
}
package java.io;

import java.util.*;
import java.io.File; /**
* 虚拟机关闭时删除文件的钩子
* 使用LinkedHashSet可以防止同名文件的二次插入, 同时可以快速移除
*/ class DeleteOnExitHook {
private static LinkedHashSet<String> files = new LinkedHashSet<>();
static {
// DeleteOnExitHook必须是最后一个被激活的关闭虚拟机的钩子.
sun.misc.SharedSecrets.getJavaLangAccess()
.registerShutdownHook(2 /* Shutdown hook invocation order */,
true /* register even if shutdown in progress */,
new Runnable() {
public void run() {
runHooks();
}
}
);
} private DeleteOnExitHook() {} // 这是一个将文件添加到删除列表的同步方法
static synchronized void add(String file) { // 判断DeleteOnExitHook是否正在运行中
if(files == null) {
// DeleteOnExitHook正在运行中, 此时已经不能加入到删除文件列表了
throw new IllegalStateException("Shutdown in progress");
} files.add(file);
} static void runHooks() {
LinkedHashSet<String> theFiles; synchronized (DeleteOnExitHook.class) {
theFiles = files;
files = null;
} ArrayList<String> toBeDeleted = new ArrayList<>(theFiles); // reverse the list to maintain previous jdk deletion order.
// 最后进来的首先被删除
Collections.reverse(toBeDeleted);
for (String filename : toBeDeleted) {
(new File(filename)).delete();
}
}
}

临时文件内部类

内部类还是挺有用的,在File类中就用到了内部类。

private static class TempDirectory {
private TempDirectory() { } // 首先是一个临时目录的生成
private static final File tmpdir = new File(AccessController
.doPrivileged(new GetPropertyAction("java.io.tmpdir")));
static File location() {
return tmpdir;
} // 文件名的生成
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;
}
}

总结一下:

1. Comparable接口以及文件系统的封装

2. final和static的配合使用

3. 文件过滤器

4. 文件删除的钩子

5. 内部类的使用

File类的源码学习的更多相关文章

  1. Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

    Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...

  2. 源码学习-String类

    最近在扫描CodeDex时报了一个不能使用String.intern()的字符串来做锁对象的告警,对这个问题有疑问查了些资料,顺便学习一下String类的源码. 1.类定义 String 被final ...

  3. Java并发包源码学习系列:挂起与唤醒线程LockSupport工具类

    目录 LockSupport概述 park与unpark相关方法 中断演示 blocker的作用 测试无blocker 测试带blocker JDK提供的demo 总结 参考阅读 系列传送门: Jav ...

  4. SpringBoot源码学习1——SpringBoot自动装配源码解析+Spring如何处理配置类的

    系列文章目录和关于我 一丶什么是SpringBoot自动装配 SpringBoot通过SPI的机制,在我们程序员引入一些starter之后,扫描外部引用 jar 包中的META-INF/spring. ...

  5. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  6. 【iScroll源码学习00】模拟iScroll

    前言 相信对移动端有了解的朋友对iScroll这个库非常熟悉吧,今天我们就来说下我们移动页面的iScroll化 iScroll是我们必学框架之一,我们这次先根据iScroll功能自己实现其功能,然后再 ...

  7. [tomcat7源码学习]初始化之catalina.home和catalina.base(转)

    我们在代码中为了获取某个配置文件路径下的文件经常会这么写 String tomcatPath = System.getProperty("catalina.home") + &qu ...

  8. Dubbo源码学习--注册中心分析

    相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 注册中心 关于注册中心,Dubbo提供了多个实现方式,有比较成熟的使用zookeeper 和 redis 的 ...

  9. Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md

    写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...

随机推荐

  1. 解决android模拟器连接本机服务器”Connection refused”问题

      在本机用模拟器连接 localhost 的服务器不成功,经查询是我反了一个小错误. android 模拟器其本身的localhost就是它自己的ip,而如果我要连接本机的localhost则需要将 ...

  2. 【译】PHP之道(PHP the right way)

    刚入门的同学觉得自己能用PHP写出各种程序就很NB了,但其实作为一个专业程序员,你得有个全面点的知识结构.单元测试总得听过,文档工具总得用用,Xss总得会防.推荐大家把<PHP the righ ...

  3. 移动 web 1px 边框解决方案

    在移动端web页面开发中,为了使css中使用的尺寸与设计稿一致,通常会采用 rem 单位配合 lib-flexible 来实现移动端的适配,在IOS设备上 flexible.js 会根据设备的分辨率动 ...

  4. 【SQL】在SQL Server中多表关联查询问题

    好久没有写SQL语句的多表连接查询,总在用框架进行持久化操作.今天写了一个多表关联查询,想根据两个字段唯一确定一条数据 失败的案例如下: SELECT cyb.id,ad.name FROM [Gen ...

  5. IOS设置UIView的边框为圆角

    iOS 系统自带的 View 组件都是正方形的,看起来都太生硬,有时候我需要变成圆角形式,如下图:    具体的实现是使用QuartzCore库,下面我具体的描述一下实现过程:    •    首先 ...

  6. quartz---任务调度小试(多任务)

    quartz---任务调度小试         背景 笔者眼下做的项目"jrkj"首页上的信息都是从redis中读取的,每小时更新一次存入redis中,那么问题来了怎么才干让系统每 ...

  7. SQL Server 系统函数

    一组内置函数,对 SQL Server 中的值.对象和设置执行操作,并返回有关它们的信息.   系统函数 功能 APP_NAME() 返回当前会话的应用程序名称(如果应用程序进行了设置) CASE表达 ...

  8. ElasticSearch _xpack用户管理

    权限管理可以通过kibana的Management界面进行,本篇主要介绍的是通过命令进行权限管理,用户API使您能够从本机域创建,读取,更新和删除用户. 这些用户通常被称为本地用户. 要使用此API, ...

  9. JAVA Eclipse如何开发Android的多页面程序

    Fragment可以认为是Activity的一个界面的组成部分,Fragment必须依存于Activity.   在layout文件夹中新建一个xml文件,布局方式采用RelativeLayout,注 ...

  10. MPTCP 理解

    背景      随着技术的发展许多设备具有了多个网络接口,而TCP依然是一个单线路的协议,在TCP的通信过程中发端和收端都 不能随意变换地址.我们可以利用多个网络接口的这一特性来改善性能和有效冗余.例 ...