Java基础整理(下)

部分内容参考自JavaGuide Java基础以及JavaGuide IO模型

三 异常处理

Java通过异常处理解决运行错误

异常类层次结构

在这里插入图片描述

  • 受检查异常

    IO 相关的异常、ClassNotFoundExceptionSQLException

  • 不受检查异常

    NullPointerExceptionNumberFormatException(字符串转换为数字)、ArrayIndexOutOfBoundsException(数组越界)、ClassCastException(类型转换错误)、ArithmeticException(算术错误)

Throwable 类常用方法
  • public string getMessage():返回异常发生时的简要描述
  • public string toString():返回异常发生时的详细信息
  • public string getLocalizedMessage():返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • public void printStackTrace():在控制台上打印 Throwable 对象封装的异常信息
抛出异常
  • throw

    throw new Exception();

  • throws

    public void m1() throws Exception {}

捕获和处理异常

try-catch-finally

  • try块: 用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch块: 用于处理 try 捕获到的异常。
  • finally 块: 无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。
  • 注意catch子句的顺序,子类catch要放在父类catch之前
try {
    
} catch(Exception e) {
    e.printStackTrace();
} finally {
    
}

在以下 3 种特殊情况下,finally 块不会被执行:

  1. tryfinally块中用了 System.exit(int)退出程序。但是,如果 System.exit(int) 在异常语句之后,finally 还是会被执行
  2. 程序所在的线程死亡。
  3. 关闭 CPU。

当 try 语句和 finally 语句中都有 return 语句时,在方法返回之前,finally 语句的内容将被执行,并且 finally 语句的返回值将会覆盖原始的返回值

try-with-resource
  1. 适用范围(资源的定义): 任何实现 java.lang.AutoCloseable或者 java.io.Closeable 的对象
  2. 关闭资源和 finally 块的执行顺序:try-with-resources 语句中,任何 catch 或 finally 块在声明的资源关闭后运行
try(/*初始化资源对象的语句*/) {
    //使用资源对象的语句
} catch(Exception e) {
    e.printStackTrace();
}

四 I/O 流

File类常用方法
getName();
getPath();
getAbsolutePath();
getParent();
exists();
canWrite();
canRead();
isDirectory();
isFile();
isHidden();
lastModified();
length();
listFiles();
I/O 流分类
  • 按照流的流向分,可以分为输入流和输出流;
  • 按照操作单元划分,可以划分为字节流和字符流;
  • 按照流的角色划分为节点流和处理流

Java I0 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

在这里插入图片描述
流操作的方法都声明抛出java.io.IOException或其后代类,需要进行异常处理

获取用键盘输入常用的两种方法

方法 1:通过 Scanner

Scanner input = new Scanner(System.in);
String s  = input.nextLine();
input.close();

方法 2:通过 BufferedReader

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
对象流

对可序列化对象读写操作

可序列化对象:实现java.io.Serializable接口

  • ObjectOutputStream

    writeInt();
    writeUTF();
    writeObject();
    
  • ObjectInputStream

    readInt();
    readUTF();
    readObject();//需要强制类型转换
    
序列化与反序列化
  • 序列化: 将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程

序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中

对于不想进行序列化的变量,使用transient关键字修饰。`

transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。

3种常见IO模型
BIO (Blocking I/O)

BIO 属于同步阻塞 IO 模型

同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到在内核把数据拷贝到用户空间。

在客户端连接数量不高的情况下,是没问题的。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

NIO (Non-blocking/New I/O)

Java 中的 NIO 于 Java 1.4 中引入,对应 java.nio 包,提供了 Channel , SelectorBuffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。

Java 中的 NIO 可以看作是 I/O 多路复用模型NIO 属于同步非阻塞 IO 模型

同步非阻塞 IO 模型中,应用程序会一直发起 read 调用(此时线程不阻塞),等待数据从内核空间拷贝到用户空间的这段时间里,线程依然是阻塞的,直到在内核把数据拷贝到用户空间。

相比于同步阻塞 IO 模型,同步非阻塞 IO 模型确实有了很大改进。通过轮询操作,避免了一直阻塞。

但是,这种 IO 模型同样存在问题:应用程序不断进行 I/O 系统调用轮询数据是否已经准备好的过程是十分消耗 CPU 资源的。

I/O 多路复用模型

IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间->用户空间)还是阻塞的。

IO 多路复用模型,通过减少无效的系统调用,减少了对 CPU 资源的消耗。

Java 中的 NIO ,有一个非常重要的选择器 ( Selector ) 的概念,也可以被称为 多路复用器。通过它,只需要一个线程便可以管理多个客户端连接。当客户端数据到了之后,才会为其服务。

AIO (Asynchronous I/O)

AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改进版 NIO 2,它是异步 IO 模型

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

总结
  • BIO

    应用程序阻塞等待,直到处理完成

  • NIO

    应用程序查询数据状态后非阻塞,服务端线程通过选择器监听多个通道,处理完成就返回

  • AIO

    应用程序请求后非阻塞,操作系统处理完成后会把结果回调给应用程序

五 泛型

泛型定义
  • 泛型类

    [修饰符] class 类名<T>

  • 泛型接口

    [修饰符] interface 接口名<T>

  • 泛型方法

    [修饰符] [static] <T> 返回类型 方法名(T参数)

限制泛型的可用类型
  • 传入类型是指定类或其子类

    <T extends 类>

  • 传入类型是指定实现了指定接口的类

    <T extends 接口>

泛型通配符

用于泛型类声明变量(方法形参)

  • 无边界

    泛型类名<?> var

  • 固定上边界

    泛型类名<? extends E> var

  • 固定下边界

    泛型类名<? super E> var

注意事项
  1. 不能使用泛型的类型参数创建对象/数组对象
  2. 不能在静态变量、方法、初始化器使用泛型的类型参数
  3. 定义异常类不能使用泛型

六 注解

概述
  • 注解(Annotation)是元数据,元数据是用来描述数据的数据
  • 注解主要用于告诉编译器要做什么事情
  • 注解可以声明在:包、类、接口、成员变量、成员方法、局部变量、方法参数等的前面,对这些程序元素进行注解说明
  • java.lang.Annotation是注解接口,所有注解都默认实现该接口
  • 语法:@注解名(参数列表)
基本注解
  • @Deprecated:表示已经过时,不建议使用
  • @Override:方法重写
  • @SuppressWarnings:抑制出现警告信息
  • @SafeVarargs:抑制堆污染警告
  • @FuntionalInterface:表示函数式接口,即只有一个抽象方法
元注解
  • @Target:表明了自定义注解的作用域
  • @Retention:声明注解信息的保留策略
  • @Documented:表明制作javadoc时,是否将注解信息加入文档
  • @Inherited:表明注解是否会被子类继承
  • @Repeatable:表明其声明(元)注释的注释类型是可重复的
自定义注解
[public] @interface 注解名 {
    数据类型 成员变量名() [default=初始值]
}

七 反射

概述

在程序运行过程中,可以通过对象了解其所属类,获取类的成员变量和方法,调用对象的属性和方法

优缺点
  • 优点 : 可以让代码更加灵活、为各种框架提供开箱即用的功能提供了便利
  • 缺点 :让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。另外,反射的性能也要稍差点,不过,对于框架来说实际是影响不大的。
获得Class类的对象
  • 类名.class
  • 对象名.getClass()
  • Class.forName(类或接口的完整路径名)
获取Constructor对象
  • Class对象.getConstructor(参数类型)
  • Class对象.getConstructors()
  • Class对象.getDeclaredConstructor(参数类型)
  • Class对象.getDeclaredConstructors()
获取Method对象
  • Class对象.getMethod(方法名,参数类型)
  • Class对象.getMethods()
  • Class对象.getDeclaredMethod(方法名,参数类型)
  • Class对象.getDeclaredMethods()
获取Field对象
  • Class对象.getField(成员变量名)
  • Class对象.getFields()
  • Class对象.getDeclaredField(成员变量名)
  • Class对象.getDeclaredFields()

八 内部类与Lambda表达式

概述

类的内部定义类称为嵌套类/内部类

内部类分为静态内部类和非静态内部类

内部类编译完成之后,产生的文件名为外部类$内部类.class

  • 一个嵌套类是其外部类的一个成员, 其访问权限可以声明为public、private、protected或包。

  • 非静态内部类中可以直接访问其外部类的其他成员, 即使这些成员使用private修饰。
    当内部类与其外部类有同名实例成员时**,** 如成员名data

    内部类的成员:this.data

    外部类的成员:外部类名.this.data

  • 静态内部类中不能访问其外部类的实例成员;但是可以访问其外部类的静态成员

  • 外部类中可以访问其内部类的所有成员, 即使这些成员使用private修饰

匿名内部类

没有名字的内部类

只能继承一个类或实现一个接口

组成部分

  • new
  • 继承的父类或实现的接口
  • 圆括号,实现接口时不带参数
  • 类的主体,声明数据域、方法
函数式接口

只包含一个抽象方法,用@FunctionalInterface注解标记

可以覆盖Object类方法、定义静态方法和默认方法

Lambda表达式

使用精简语法的匿名内部类

格式:(类型1 参数1,类型2 参数2,…)-> {方法体}

Lambda表达式可以作为实参传递给方法。方法对应的形参必须是一个函数式接口类型

常用类/接口名

java.util.Scanner

java.util.Arrays

java.util.Random

java.util.Date

java.util.Calendar

java.util.Comparator

java.util.function

java.util.Objects

java.lang.String

java.lang.StringBuilder

java.lang.StringBuffer

java.lang.Math

java.lang.Object

java.lang.Comparable

java.lang.Cloneable

java.lang.Throwable

java.lang.Annotation

java.lang.Class

java.lang.reflect.Constructor

java.lang.reflect.Field

java.lang.reflect.Method

java.lang.reflect.Parameter

java.lang.System

java.io.File

java.io.IOException

java.io.Serializable

java.text.DateFormat

java.text.SimpleDateFormat

java.math.BigDecimal

java.math.BigInteger

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值