1、异常:
1.1 捕捉异常:数组下标越界
解决异常:用try{ }catch( ){ }处理;
1.2 异常捕捉机制:
捕捉异常:
try{
//可能产生异常的代码
}catch(Type1 id1){
//处理Type异常的代码
}catch(Type2 id2){
//处理Type2异常的代码
}catch(Type3 id3){
//处理Type3异常的代码
}
异常发生并不意味着程序一定要终止:
package exception;
import java.util.Scanner;
public class ArrayIndex {
public static void f() {
int[] a = new int[10];
a[10] = 10;
System.out.println("hello");
}
public static void main(String[] args) {
try {
f();
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("caught");
}
System.out.println("main");
}
}
package exception;
import java.util.Scanner;
public class ArrayIndex {
public static void f() {
int[] a = new int[10];
a[10] = 10;//抛出异常
System.out.println("hello");
}
public static void g() {
f();
}
public static void h() {
int i=10;
if(i<100) {
g();//不是函数
}
}
public static void k() {
try {
h();
}catch(NullPointerException e) {
System.out.println("k()");
}
}
public static void main(String[] args) {
try {
k();
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("caught");
}
System.out.println("main");
}
}
1.3 捕捉到的异常:
- 捉到了做什么?
- String getMessage();
- String toString();
- void printStackTrace();
- 但是肯定是回不去了,而具体的处理逻辑则取决于你的业务逻辑需要;
-
调用轨迹:
- 再度抛出:
catch(Exception e){
System.err.println("An exception was thrown");
throw e;
}
如果在这个层面上需要处理,但是不能做最终的决定
1.4 异常:
- 如果要读文件:打开文件--判断文件大小--分配足够的内存空间--把文件读入内存--关闭文件;(遇到异常很难处理、时间依赖性较大、缺乏提前预警处理)
用上异常机制(Business Logic)
try{
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}catch(fileOpenFailed){
doSomething;
}catch(sizeDeterminatedFailed){
doSomething;
}catch(memoryAllocationFailed){
doSomething;
}catch(readFailed){
doSomething;
}catch(fileCloseFailed){
doSomething;
}
- 异常:(异常机制最大的好处就是清晰地分开了正常的业务逻辑代码和遇到情况时的处理代码)
- 有不寻常的事情发生了;
- 当这个事情发生的时候,原本打算要接着做的事情不能再继续了,必须得要停下来,让其他地方的某段代码来处理;
1.5 异常的抛出与声明:
- 异常声明:
- 如果你的函数可能抛出异常,就必须在函数头部加以声明;
void f() throws TooBig,TooSmall,DivZero{//....
void f(){..}
- 你可以声明并不会真的抛出的异常;
- 什么能扔?
- 任何继承了Throwable类的对象;
- Exception类继承了Throwable;
- throw new Exception();
- throw new Exception("HELP");
package exception;
class OpenException extends Throwable{
}
class CloseException extends Throwable{
}
public class ArrayIndex {
public static int open() {
// int[]a = new int[10];
// a[10] = 10;
return -1;
}
public static void readFile() throws OpenException,CloseException {
if(open()==-1) {
throw new OpenException();
}
}
public static void main(String[] args) {
try {
readFile();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OpenException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CloseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1.6 异常捕捉时的匹配:
- catch怎么匹配异常的?
- Is-A的关系;
- 就是说,抛出子类异常会被捕捉父类异常的catch给捉到;
- 捕捉任何异常:
catch(Exception e){
System.err.println("Caught an exception");
}
- 运行时刻异常:
- 像ArraylndexOutOfBoundsException这样的异常是不需要声明的;
- 但是如果没有适当的机制来捕捉,就会最终导致程序终止;
- 异常声明:
- 如果你调用一个声明会抛出异常的函数,那么你必须;
- 把函数的调用放在try块中,并设置catch来捕捉所有可能抛出的异常;
- 或声明自己会抛出无法处理的异常;
- 如果你调用一个声明会抛出异常的函数,那么你必须;
- 异常声明遇到继承关系:
- 当覆盖一个函数的时候,子类不能声明抛出比父类的版本更多的异常;
- 在子类的构造函数中,必须声明父类可能抛出的全部异常;
- 成员函数不能增加更多的异常,构造函数可以;
package exception;
class OpenException extends Exception{}
class CloseException extends OpenException{}
class NewException extends Exception{}
public class ArrayIndex{
public ArrayIndex() throws OpenException{}
public void f() throws OpenException{}
public static void main(String[] args) {
}
}
class NewClass extends ArrayIndex{
public NewClass() throws OpenException,NewException {}//构造函数
public void f() {}
public static void main(String[]args) {
try {
ArrayIndex p = new NewClass();//向上造型
p.f();
} catch (OpenException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NewException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2、流:(stream)
2.1 流是输入输出的方式
- 流是一维单向的;
- 流的基础类:
- InputStream:(当做字节流来看待)
- read():int read()表示读到头了,返回-1;read(byte b[]);read(byte[],int off,int len):读字节;
- skip(long n);
- int available();表示流里面现在还有多少字节供你读
- mark();读到流的某个地方做标记,继续往前读
- reset();读到某个地方重新回到之前的某个地方
- boolean markSupported();
- close();
- OutputStream:
- write():write(int b); write(byte b[]); write(byte b[],int off,int len);
- flush();
- close();
-
http://docs.oracle.com/javase/8/docs/api/overviewsummary.html
- InputStream:(当做字节流来看待)
package hello;
import java.io.IOException;
import java.util.Scanner;
public class main {
public static void main(String[] args) {
System.out.println("hello world");//out就是某种用来做输出的流;
byte[] buffer = new byte[1024];
try {
int len = System.in.read(buffer);
String s = new String(buffer,0,len);
System.out.println("读到了"+len+"字节");
System.out.println(s);
System.out.println("s的长度是:"+s.length());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
注意字节和字符的区别
2.2 文件流:
- FileInputStream:
- FileOutputStream:
- 对文件作读写操作;
- 实际工程中已经较少使用;
- 更常用的是以在内存数据或通信数据上建立的流,如数据库的二进制数据读写或网络端口通信;
- 具体的文件读写往往有更专业的类,比如配置文件和日志文件;
package hello;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class main {
public static void main(String[] args) {
System.out.println("hello world");//out就是某种用来做输出的流;
byte[] buf = new byte[10];
for(int i=0;i<buf.length;i++) {
buf[i] = (byte)i;
}
try {
FileOutputStream out = new FileOutputStream("a.dat");
out.write(buf);
out.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.3 流过滤器:
- 以一个介质流对象为基础层层构建过滤器流,最终形成的流对象能在数据的输入输出过程中,逐层使用过滤器的方法来读写数据;
package hello;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class main {
public static void main(String[] args) {
System.out.println("hello world");//out就是某种用来做输出的流;
byte[] buf = new byte[10];
for(int i=0;i<buf.length;i++) {
buf[i] = (byte)i;
}
try {
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream("a.dat")));//写字节,套过滤器
int i=123456;//十进制,到文件自动变成八进制;
out.writeInt(i);
out.close();
DataInputStream in = new DataInputStream(
new BufferedInputStream(
new FileInputStream("a.dat")));
int j = in.readInt();
System.out.println(j);
}catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- Data:
- DataInputStream;
- DataOutputStream;
- 用以读写而金子方式表达的基本数据类型的数据;
3、文本输入输出:
3.1 文本流:
- Reader/Writer:
- 二进制数据采用InputStream/OutputStream;
- 文本数据采用Reader/Writer;
- 在流上建立文本处理:
PrintWriter pw = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("abc.txt")));
try {
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("a.txt"))));//写字节,套过滤器
int i=123456;//十进制,到文件自动变成八进制;
out.println(i);
- Reader:
- 常用的是BufferedReader;
- readLine();
BufferedReader in = new BufferedReader(
new InputStreamReader(
new FileInputStream("src/hello/Main.java")));
String line;
while((line=in.readLine())!=null){
System.out.println(line);
}
- LineNumberReader:
- 可以得到行号;
- getLineNumber();
- 可以得到行号;
- FileReader:
- InputStreamReader类的子类,所有方法都从父类中继承而来;
- FileReader(File file):
- 在给定从中读取数据的File的情况下创建一个新FileReader;
- FileReader(String fileName):
- 在给定从中读取数据的文件名的情况下创建一个新FileReader;
- FileReader不能指定编码转换方式;
3.2 汉字编码:
- InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
- InputStreamReader(InputStream in,Charset cs) 创建使用给定字符集的 InputStreamReader。
- InputStreamReader( InputStream in,CharsetDecoder dec) 创建使用给定字符集解码器的 InputStreamReader。
- InputStreamReader( InputStream in,String charsetName) 创建使用给定字符集的 InputStreamReader。
3.3 格式化输入输出:
- PrintWriter:
- format("格式",...);
- printf("格式",...);
- print(各种基本类型);不带回车
- println(各种基本类型);带回车
- Scanner:
- 在InputStream或Reader上建立一个Scanner对象可以从流中的文本中解析出以文本表达的各种基本类型;
-
next...();
3.4 流的应用:
- 阻塞/非阻塞:
- read()函数时阻塞的,在读到所需的内容之前会停下来等;
- 使用read()的更“高级”的函数,如nextInt()、readLine()都是这样的;
- 所示常用单独的线程来做socket读的等待,或使用nio的channel选择机制;
- 对于socket,可以设置SO时间:
- setSoTimeout(int timeOut);
package main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
public class main {
public static void main(String[] args) {
try {
Socket socket = new Socket(InetAddress.getByName("localhost"),12345);
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())));
out.println("Hello");
out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
String line;
line = in.readLine();
System.out.println(line);
out.close();
socket.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
3.5 对象串行化:
- ObjectInputStream类:
- readObject;
- ObjectOutputStream类:
- writeObject();
- Serializable接口:
package main;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.Socket;
class Student implements Serializable{
private String name;
private int age;
private int grade;
public Student(String name,int age,int grade) {
this.name = name;
this.age = age;
this.grade = grade;
}
public String toString() {
return name+" "+age+" "+grade;
}
}
public class main {
public static void main(String[] args) {
try {
Student s1 = new Student("John",18,5);
System.out.println(s1);
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("obj.dat"));
out.writeObject(s1);
out.close();
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("obj.dat"));
Student s2 = (Student)in.readObject();
System.out.println(s2);
in.close();
System.out.println(s1==s2);
}catch(IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}