Java4Android自學記錄(22-3):java中的I/O

道阻且長,行則將至。埋頭苦幹,不鳴則已,一鳴驚人!加油,騷年!

目錄及資源索引

  Java4Android自學過程目錄及資源索引

1 處理流使用實例

  參考老師課件,具體解釋內容如下圖:
image-20200530141430426

  全稱:字符輸入處理流;使用這個類的時候,大部分都是爲了使用其中這個方法:如上圖所示,讀取一行。

  比如有一個類似這樣的文件需要處理,每一行都是一個用戶的信息

張三 F 20
李四 M 21
王五 F 22
趙六 M 23

  這個時候,讀取這個文件怎樣最方便?當然是一次讀取一行;這樣就可以利用上述函數;

  那麼具體的使用方法是怎麼樣的呢?生成方法,接收的是一個 Reader 類的對象,下邊用代碼實驗如下:

import java.io.*;

class Test 
{
	public static void main(String args[])
	{
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		
		try
		{
			fileReader = new FileReader("users.txt");
			bufferedReader = new BufferedReader(fileReader);
			
			String line = bufferedReader.readLine();
			System.out.println(line);
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
		finally
		{
			try
			{
				fileReader.close();
				bufferedReader.close();
			}
			catch(Exception e)
			{
				System.out.println(e);
			}
		}		
	}
}

  上述代碼,編譯運行後結果如下:
image-20200530143257015

  可以看到第一次出現了亂碼,即使之前是加上了編譯所使用的字符集,還是不可以。後來發現,

  1. 第一次出現亂碼,users.txt 文本的編碼爲 UTF-8 編碼;
  2. 第二次正常顯示,是此文本編碼修改爲 ANSI 後,恢復正常;
  3. 具體原因暫時未知。

  如何把這幾行內容,全部打印出來呢?修改部分代碼如下,我們只需要增加一個 while 循環即可

import java.io.*;

class Test 
{
	public static void main(String args[])
	{
		FileReader fileReader = null;
		BufferedReader bufferedReader = null;
		
		try
		{
			fileReader = new FileReader("users.txt");
			bufferedReader = new BufferedReader(fileReader);
			
			String line = null;
			while(true)
			{
				line = bufferedReader.readLine();
				if(null == line)
				{
					break;
				}
				System.out.println(line);
			}				
		}
		catch(Exception e)
		{
			System.out.println(e);
		}
		finally
		{
			try
			{
				fileReader.close();
				bufferedReader.close();
			}
			catch(Exception e)
			{
				System.out.println(e);
			}
		}		
	}
}

  上述代碼,編譯運行後的結果如下:
image-20200530143602265

  這個函數什麼時候返回 NULL 呢?當讀到末尾的時候,就返回 NULL ;

  上述就是所謂的處理流,凡是要使用處理流的,都必須首先有一個節點流。

2 “裝飾者(Decorator)”模式

2.1 示例演示

  老師舉了一個例子,先來一步一步深入,具體如下:
image-20200530145322431

  疑問:當工人的類別,及工人所屬的公司,越來越多時,怎麼辦呢?

  此時可以先定義一個 Worker 的接口,代碼如下:

interface Worker
{
	public void doSomeWork();
}

  接着定義一個修水管的類,Plumber,此類繼承 Worker 接口,需要實現父類中的函數,具體代碼如下:

class Plumber implements Worker
{
	public void doSomeWork()
	{
		System.out.println("修水管");
	}
}

  接着定義一個木工類,修門窗的,Carpenter,同樣繼承 Worker 接口,需要實現父類中的函數,具體代碼如下:

class Carpenter implements Worker
{
	public void doSomeWork()
	{
		System.out.println("修門窗");
	}
}

  然後定義一個子類 AWorker,繼承 Worker ,相當於是 A 公司的員工,同樣需要實現父類中的函數,還需要加上一個構造函數(參數類型爲父類 Worker),此時代碼如下:

class AWorker implements Worker
{
	private Worker worker;
	
	public AWorker(Worker worker)
	{
		this.worker = worker;
	}
	
	public void doSomeWork()
	{
		System.out.println("你好");
		worker.doSomeWork();
	}
}

  最後定義一個有主函數的類,生成一個 A 公司修水管的工人,此時需要向上轉型,具體代碼如下:

class Test01
{
	public static void main(String args[])
	{
		// 生成一個A公司水管工對象
		Plumber plumber = new Plumber();
		AWorker aWorker = new AWorker(plumber);	// 向上轉型
		aWorker.doSomeWork();
	}
}

  最後代碼編譯運行結果如下:
image-20200530151406311

  分析一下,在 AWorker 中有一個 Worker 的引用,其實這是一個面向對象的思想,不使用繼承,而是在 A 公司這個類中,有 Worker 的一個成員變量;好處是什麼呢?通用性;假如此時要生成一個 A 公司的木匠工,此時就可以使用這個通用的類,只是傳進去的參數類型爲木匠工向上轉型後的類型。

  上代碼看一下,就一目瞭然了,如下:

class Test01
{
	public static void main(String args[])
	{
		// 生成一個A公司水管工對象
		Plumber plumber = new Plumber();
		AWorker aWorker = new AWorker(plumber);	// 向上轉型
		aWorker.doSomeWork();
		
		Carpenter carpenter = new Carpenter();
		AWorker aWorker2 = new AWorker(carpenter);
		aWorker2.doSomeWork();
	}
}

  上述代碼,編譯運行後,結果如下,可以看到木匠的修門窗,也打印出來了。
image-20200530152401100

2.2 示例分析

  上述示例,已經演示完畢,那麼我的疑問來了,感覺有很多不理解的地方,比如:

  1. 爲什麼要這麼設計?好處是什麼?
  2. 目前看來定義了很多類,感覺很複雜呀,可是我目前不需要這麼複雜、這麼多的類,就能實現功能了呀?

  別慌,我們仔細理解,分析一下就很容易得出結論,面向對象編程的終極目標是什麼?消除程序中的重複代碼;好了,這就讓我們來解答之前的問題:

  1. 這樣設計,便於後續擴展,便於消除重複代碼!
  2. 不要被目前的需求侷限了思維,目前只是舉這麼簡單一個例子,如果我們寫出來一個程序,後續隨着用戶量增加,產品需求增加,需要改變時,還要重構一遍代碼,那就很麻煩了。就像天宮一號空間站一樣,每次送上去的肯定是留有一個或多個對接下次設備的接口,如果你直接就封死了,後續再要發射設備,怎麼辦???哈哈,道理就是這麼個樣子。

  那麼先消除上邊這些疑問,再來分析一下這樣寫的意義,個人感覺的有如下幾個方面

  1. 雖然剛開始看起來要定義很多類,很複雜,但其實不然;
  2. 把共同的部分,一層一層的抽出來,比如最抽象的,大家都是工人;其次再分水管工、木匠工;接着可以再分 A 公司的水管工、木匠工,B 公司的水管工、木匠工;等等
  3. 這樣把公共的抽出來,最抽象的就可以作爲父類,就像大家交流的一個通道似的;舉個例子,我在深圳,就是深圳人,你在鄭州就是鄭州人;深圳是廣東省的,鄭州是河南省的;而廣東又是中國的,河南也是中國的,你看,我們倆的聯繫/共同點不就出來了嗎?這樣我們對外,就可以一致的說,我是中國人!
  4. 在進一步的分析,你在河南省new出一個對象,我在廣東省new出來一個對象;這樣你的就是中國河南省的對象,我的就是中國廣東省的對象,哈哈哈哈;

3 總結

  1. 上述示例,都是自己根據自己的理解想象出來的,如果有誤,還望多多指教~
  2. 裝飾者模式:把類似 AWorker 這種類稱爲裝飾者,把木匠等稱爲被裝飾者;
  3. 壓縮流,實現壓縮和解壓縮文件;
  4. 裝飾者模式,理解還不夠深入,後續有時間,要進一步深入瞭解一下,或者結合實踐,多多練習!加油啦~

如果文章內容有誤,麻煩評論/私信多多指教,謝謝!如果覺得文章內容還不錯,留個讚唄,您的點贊就是對我最大的鼓勵,謝謝您嘞!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章