1、異常:
1.1 捕捉異常:數(shù)組下標(biāo)越界

image.png
解決異常:用try{ }catch( ){ }處理;

image.png
1.2 異常捕捉機(jī)制:
捕捉異常:
try{
//可能產(chǎn)生異常的代碼
}catch(Type1 id1){
//處理Type異常的代碼
}catch(Type2 id2){
//處理Type2異常的代碼
}catch(Type3 id3){
//處理Type3異常的代碼
}
異常發(fā)生并不意味著程序一定要終止:
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");
}
}

image.png

image.png
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();//不是函數(shù)
}
}
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();
- 但是肯定是回不去了,而具體的處理邏輯則取決于你的業(yè)務(wù)邏輯需要;
-
調(diào)用軌跡:
image.png
- 再度拋出:
catch(Exception e){
System.err.println("An exception was thrown");
throw e;
}
如果在這個層面上需要處理,但是不能做最終的決定
1.4 異常:
- 如果要讀文件:打開文件--判斷文件大小--分配足夠的內(nèi)存空間--把文件讀入內(nèi)存--關(guān)閉文件;(遇到異常很難處理、時間依賴性較大、缺乏提前預(yù)警處理)
用上異常機(jī)制(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;
}
- 異常:(異常機(jī)制最大的好處就是清晰地分開了正常的業(yè)務(wù)邏輯代碼和遇到情況時的處理代碼)
- 有不尋常的事情發(fā)生了;
- 當(dāng)這個事情發(fā)生的時候,原本打算要接著做的事情不能再繼續(xù)了,必須得要停下來,讓其他地方的某段代碼來處理;
1.5 異常的拋出與聲明:
- 異常聲明:
- 如果你的函數(shù)可能拋出異常,就必須在函數(shù)頭部加以聲明;
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的關(guān)系;
- 就是說,拋出子類異常會被捕捉父類異常的catch給捉到;
- 捕捉任何異常:
catch(Exception e){
System.err.println("Caught an exception");
}
- 運(yùn)行時刻異常:
- 像ArraylndexOutOfBoundsException這樣的異常是不需要聲明的;
- 但是如果沒有適當(dāng)?shù)臋C(jī)制來捕捉,就會最終導(dǎo)致程序終止;
- 異常聲明:
- 如果你調(diào)用一個聲明會拋出異常的函數(shù),那么你必須;
- 把函數(shù)的調(diào)用放在try塊中,并設(shè)置catch來捕捉所有可能拋出的異常;
- 或聲明自己會拋出無法處理的異常;
- 如果你調(diào)用一個聲明會拋出異常的函數(shù),那么你必須;
- 異常聲明遇到繼承關(guān)系:
- 當(dāng)覆蓋一個函數(shù)的時候,子類不能聲明拋出比父類的版本更多的異常;
- 在子類的構(gòu)造函數(shù)中,必須聲明父類可能拋出的全部異常;
- 成員函數(shù)不能增加更多的異常,構(gòu)造函數(shù)可以;
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 {}//構(gòu)造函數(shù)
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 流是輸入輸出的方式
- 流是一維單向的;
- 流的基礎(chǔ)類:
- InputStream:(當(dāng)做字節(jié)流來看待)
- read():int read()表示讀到頭了,返回-1;read(byte b[]);read(byte[],int off,int len):讀字節(jié);
- skip(long n);
- int available();表示流里面現(xiàn)在還有多少字節(jié)供你讀
- mark();讀到流的某個地方做標(biāo)記,繼續(xù)往前讀
- 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
image.png
- InputStream:(當(dāng)做字節(jié)流來看待)
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+"字節(jié)");
System.out.println(s);
System.out.println("s的長度是:"+s.length());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

image.png
注意字節(jié)和字符的區(qū)別
2.2 文件流:
- FileInputStream:
- FileOutputStream:
- 對文件作讀寫操作;
- 實(shí)際工程中已經(jīng)較少使用;
- 更常用的是以在內(nèi)存數(shù)據(jù)或通信數(shù)據(jù)上建立的流,如數(shù)據(jù)庫的二進(jìn)制數(shù)據(jù)讀寫或網(wǎng)絡(luò)端口通信;
- 具體的文件讀寫往往有更專業(yè)的類,比如配置文件和日志文件;
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();
}
}
}

image.png
2.3 流過濾器:
- 以一個介質(zhì)流對象為基礎(chǔ)層層構(gòu)建過濾器流,最終形成的流對象能在數(shù)據(jù)的輸入輸出過程中,逐層使用過濾器的方法來讀寫數(shù)據(jù);
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")));//寫字節(jié),套過濾器
int i=123456;//十進(jìn)制,到文件自動變成八進(jìn)制;
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;
- 用以讀寫而金子方式表達(dá)的基本數(shù)據(jù)類型的數(shù)據(jù);
3、文本輸入輸出:
3.1 文本流:
- Reader/Writer:
- 二進(jìn)制數(shù)據(jù)采用InputStream/OutputStream;
- 文本數(shù)據(jù)采用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"))));//寫字節(jié),套過濾器
int i=123456;//十進(jìn)制,到文件自動變成八進(jìn)制;
out.println(i);

image.png
- 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);
}

image.png
- LineNumberReader:
- 可以得到行號;
- getLineNumber();
- 可以得到行號;
- FileReader:
- InputStreamReader類的子類,所有方法都從父類中繼承而來;
- FileReader(File file):
- 在給定從中讀取數(shù)據(jù)的File的情況下創(chuàng)建一個新FileReader;
- FileReader(String fileName):
- 在給定從中讀取數(shù)據(jù)的文件名的情況下創(chuàng)建一個新FileReader;
- FileReader不能指定編碼轉(zhuǎn)換方式;
3.2 漢字編碼:
- InputStreamReader(InputStream in) 創(chuàng)建一個使用默認(rèn)字符集的InputStreamReader。
- InputStreamReader(InputStream in,Charset cs) 創(chuàng)建使用給定字符集的 InputStreamReader。
- InputStreamReader( InputStream in,CharsetDecoder dec) 創(chuàng)建使用給定字符集解碼器的 InputStreamReader。
- InputStreamReader( InputStream in,String charsetName) 創(chuàng)建使用給定字符集的 InputStreamReader。
3.3 格式化輸入輸出:
- PrintWriter:
- format("格式",...);
- printf("格式",...);
- print(各種基本類型);不帶回車
- println(各種基本類型);帶回車
- Scanner:
- 在InputStream或Reader上建立一個Scanner對象可以從流中的文本中解析出以文本表達(dá)的各種基本類型;
-
next...();
image.png
3.4 流的應(yīng)用:
- 阻塞/非阻塞:
- read()函數(shù)時阻塞的,在讀到所需的內(nèi)容之前會停下來等;
- 使用read()的更“高級”的函數(shù),如nextInt()、readLine()都是這樣的;
- 所示常用單獨(dú)的線程來做socket讀的等待,或使用nio的channel選擇機(jī)制;
- 對于socket,可以設(shè)置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();
}
}
}


