首页 > 其他分享 >JTCR-I/O,Try-with-Resources 及其他-11

JTCR-I/O,Try-with-Resources 及其他-11

时间:2024-04-22 15:57:12浏览次数:28  
标签:JTCR 字节 字符 静态 try Try 文件 使用 Resources

I/O 基础

Java 的 I/O 操作通过流来实现。流是对输入、输出数据的抽象,每个流都和一个具体的物理实体关联,比如在输入中,流可以和键盘、磁盘文件或者网络输入等关联,虽然每个物理实体不同,但是流可以以同样的方式进行处理。

Java 定义了字节流和字符流。字节流处理的对象是二进制数据,以字节的方式处理。字符流处理的对象是字符,字符编码为 Unicode,方便国际化。最底层而言,所有的 I/O 操作都是面向字节的。

字节流定义了两个类层次,最高层分别为抽象类 InputStream、OutputStream,这两个类都有若干个具体的子类处理不同情况的 I/O 操作。这两个抽象类分别定义了 read()write() 方法用于读写字节数据,具体实现由子类完成。

字符流与字节流类似,抽象类为 Reader 和 Writer,分别定义了 read()write() 方法用于读写字符数据。

java.lang 包中定义了 System 类,这个类中定义了 3 个流类型静态变量,分别为 in、out、err。使用 public static final 修饰,不需要实例化 System 类就可以使用。in、out、err 三者分别默认表示标准输入流键盘、标准输出流控制台、标准错误流控制台。可以自行更改,表示不同的设备。in 的类型为 InputStream,out、err 的类型为 PrintStream,三者都是字节流。

读控制台输入

从控制台读取即从 System.in 读取。为得到和控制台绑定的基于字符的流,需要将 System.in 包装成表示字符流的类。

// 将一个字符输入流转换成有缓存的字符输入流
BufferedReader(Reader);
// 将一个字节流转换成字符流
InputStreamReader(InputStream);
// 将控制台输入字节流转成有缓存的字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

使用 int read() 方法可以从 BufferedReader 对象中每次读取一个字符并返回该字符表示的整数,如果到达了流的末尾,则返回 -1。
System.in 是行缓冲,在没有按换行键之前输入不会传递给程序。
使用 BufferedReader 类的 String readLine() 方法每次读取一行作为字符串返回。

写控制台输出

PrintStream 类的 void write(int) 方法写出的字节个数由参数指定,参数类型虽然为 int,但只有低 8 位有效。

PrintWriter 类

控制台输出使用 PrintWriter 流。PrintWriter(OutputStream, boolean) 构造器中第一个参数为输出流对象,第二个参数如果为 true,则自动刷新;否则,不自动刷新。

// 这里 pw 相当于 System.out,只不过类型是基于字符流的,优点是易于国际化
PrintWriter pw = new PrintWriter(System.out, true);
pw.println("string");

读写文件

和文件相关的常见类为 FileInputStream 和 FileOutputStream,两者都是与文件关联的字节流。 FileInputStream(String)FileOutputStream(String) 构造器的参数为想要打开的文件名。对于输入流,文件不存在,则抛出异常;对于输出流,文件不存在或者打不开,抛出异常,当文件打开时,之前同名的文件被销毁。

使用完文件后,使用 close() 方法关闭文件,释放分配给文件的系统资源。这个方法定义在 AutoCloseable 接口中。一般在 finally 子句中关闭文件。

从 JDK7 开始,try-with-resources 语句可以在文件不再使用时自动关闭。

每次使用 int read() 读取文件时,读取文件的一个字节并返回这个字节表示的整数,当到文件末尾时返回 -1。void write(int) 写文件与之类似,每次写入一个字节。

自动关闭文件

try (resource) {
 // use
}

JDK7 开始,提供了 try-with-resoucres 块。resouce 是一条用于定义和初始化要用的资源的语句,当资源在 try 块中使用完毕后,会自动释放该资源。resouce 也可以是之前定义和初始化的变量,此时该变量必须由 final 修饰才能在 try 块中使用。

try-with-resoucres 块仅能用于实现了 AutoCloseable 接口的类,该接口定义了一个 close() 方法,流类都实现了该接口。该块中 resouce 的定义隐式被 final 修饰,作用域为整个 try 块。

从 JDK10 开始,可以在 try-with-resoucres 块中使用局部变量类型推导。

try (var fin = new FileInputStream("name.dat"))

try 语句中,可以定义多个变量,每个用分号相隔。当该块中产生异常时,很容易引发另一个异常,第二个异常会和第一个异常关联,并被抑制,可以使用 getSuppressed() 方法获取。

transient 和 volatile 修饰符

transient 修饰的变量表示其内容不需要持久保存,在序列化时忽略该变量。

// 当一个 T 类型对象保存到持久化存储介质(比如磁盘)时,
// 属性 a 不会写入,b 会写入其中。
class T {
  transient int a;
  int b;
}

volatile 告知编译器它修饰的变量内容可能会被其他线程修改,变量的内容对其他线程可见,一般发生在多线程共享变量的情形。

instanceof

子类可以转换成超类,反之不然。instanceof 语法为:

objectRef instanceof type

如果引用的对象类型为 type 或者可以转换成 type,则返回 true,否则返回 false。

strictfp

strictfp 修饰的类、接口或方法中浮点数的计算使用老模型,在计算时中间结果发生截断,而使用新模型中间结果不会发生截断。

本地方法

native 用于定义本地码方法,该方法是用非 Java 语言编写的。定义之后可以在 Java 程序中调用,这个机制称为 Java Native Interface(JNI)。例如:

// 不需要方法体
public native int m();

assert

assert 用于开发过程中,判断条件是否发生,条件发生,则无事发生;否则,抛出 AssertionError 错误。
断言的一般形式为:

// cond 是一个计算结果为 boolean 类型的表达式
assert cond
// exp 是传递给 AssertionError 构造器的值,当错误发生时,显示该值。
// exp 一般是断言失败时,想要显示的信息
assert cond:exp

assert n > 0 : "n less than or equal to 0"

使用断言加上 -ea,例如 java -ea programName

断言中不能依赖任何正常流代码,否则,当断言被禁用时,可能产生问题。

使用 -ea:Name/-da:Name 可以分别启用、禁用特定范围的断言,Name 可以是类名、包名。

静态导入

静态导入会导入类或接口中的静态成员。使用时直接使用静态成员名称,不需要加上类名或接口名限定。

import static pkg.typeName.staticMember; 导入特定静态成员。
import static pkg.typeNname.*; 导入所有静态成员。

需要多次使用某个静态成员时,使用静态导入比较方便。但是,仅少数使用几次的静态成员没必要使用静态导入,因为可能造成属于不同命名空间具有相同名称的静态成员引入同一个文件造成命名冲突。

通过 this() 调用重载构造器

this(argList) 在构造器第一行调用 this,根据传入的参数类型和个数调用匹配的构造器。可以用于减少重复代码,能减少加载类的时间。

在构造器内调用 this 会有一定的开销,当调用这种类型的构造器创建大量对象时,会带来很大的开销。需要权衡减少加载类的时间和创建对象的开销。

构造器内的初始化代码很少时,是否使用 this 差别不大,因为字节码将 this 的初始化内容添加到当前文件中,当初始化代码少时,能减少的类加载时间很少。对于有大量初始化代码的构造器,this 的使用能明显减少类加载时间。

不能使用类实例调用 this() 方法;不能在同一构造器中同时使用 super()this() 方法,因为这两个方法都必须是构造器的第一条语句。

紧凑 API Profiles

JDK8 将 API 库划分成了多个子集,称为紧凑 profiles,分别称为 compact1, compact2, compact3,其中 compact3 包含 compact2, compact2 包含 compact1。使用紧凑 profiles 的好处是当某个应用只需要使用 API 库的一部分功能时,使用 compact 可以减少代码库大小,减少加载程序的时间。

参考

[1] Herbert Schildt, Java The Complete Reference 11th, 2019.

标签:JTCR,字节,字符,静态,try,Try,文件,使用,Resources
From: https://www.cnblogs.com/xdreamc/p/16393711.html

相关文章

  • Spring-Retry框架简单使用
    前言Spring-Retry框架是Spring自带的功能,具备间隔重试、包含异常、排除异常、控制重试频率等特点,是项目开发中很实用的一种框架。SpringCloudConfig请求配置中心服务器时就使用到了此功能,具体可以看ConfigServicePropertySourceLocator。使用添加依赖底层使用AOP实现的,......
  • web server apache tomcat11-08-JNDI Resources
    前言整理这个官方翻译的系列,原因是网上大部分的tomcat版本比较旧,此版本为v11最新的版本。开源项目从零手写实现tomcatminicat别称【嗅虎】心有猛虎,轻嗅蔷薇。系列文章webserverapachetomcat11-01-官方文档入门介绍webserverapachetomcat11-02-setup启动web......
  • python使用pip安装模块出错 Retrying (Retry(total=0, connect=None, read=None, redi
    问题:在使用python时,使用pip安装psutil出错(pipinstallpsutil),错误信息:Retrying(Retry(total=0,connect=None,read=None,redirect=None,status=None))afterconnectionbrokenby‘SSLError(SSLError(1,u’[SSL:CERTIFICATE_VERIFY_FAILED]certificateverifyfailed......
  • JTCR-枚举、装箱和注解-10
    枚举枚举定义了一个数据类型和该数据类型允许的若干个值,这些值为命名常量。一个枚举实例的值必须是定义的值。Java中,枚举是类类型,可以有构造器、方法和实例变量,甚至实现接口。但不能使用new实例化。enumName{value1,value2,...}//定义Namen=Name.value1;//......
  • JTCR-多线程-09
    基于进程和线程的多任务,其最小的调度单位分别是进程和线程。在基于线程的环境中,单个进程可以同时处理不同的任务,每个线程共享地址空间。基于线程的多任务和基于进程的相比,开销小。相互间的通信和上下文切换开销不同。Java的线程模型Java的运行时系统使用多线程,当某一个线程......
  • JTCR-异常处理-08
    异常处理基础try{//可能产生异常的代码块}catch(ExceptionTypeex){//处理异常}catch(ExceptionTypeex){//处理异常}...finally{//无论是否发生异常,必须执行的代码块}异常类型所有异常类型的超类是Throwable,该类有两个直接子类,一个是Excepti......
  • JTCR-包和接口-07
    包包用于划分类的命名空间,使得不同包中的同名类不会冲突。Java使用文件夹存储包,文件夹名和包名一致。Java运行时系统从当前目录中、CLASSPATH变量定义的值、-classpath指定的值这三种途径寻找包。包和成员访问可访问性private无修饰符protectedpublic同一个......
  • JTCR-深入了解方法和类-05
    方法重载一个类中存在多个同名方法,这些方法的形参类型或数量不同的现象称为方法重载。同名方法的返回值类型在判断是否构成重载时不予考虑。方法重载是支持多态的方式之一。当调用同名方法时,Java根据传入方法的实参类型、数量和顺序确定某个唯一精确匹配的方法,然后调用该方法;如......
  • JTCR-继承-06
    继承基础classA{inti;voidm(){//body}}classBextendsA{intk;voidn(){//body}}没有类可以成为其自身的超类(superclass)。子类不能访问超类中的private成员。超类类型变量可以引用派生自该超类的子类对象,但是使用该变量只......
  • JTCR-介绍类-04
    类基础类表示一个新的数据类型。简单类的一般形式:classClassName{typeinstanceVariable;//...typemethod(parameterList){//方法体}//...}有些Java应用不需要main方法。定义对象new操作符在运行时动态地给一个对象分配内存并返回指向该......