国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java中的構(gòu)建器

2019-11-18 13:20:01
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  為違例編寫(xiě)代碼時(shí),我們經(jīng)常要解決的一個(gè)問(wèn)題是:“一旦產(chǎn)生違例,會(huì)正確地進(jìn)行清除嗎?”大多數(shù)時(shí)候都會(huì)非常安全,但在構(gòu)建器中卻是一個(gè)大問(wèn)題。構(gòu)建器將對(duì)象置于一個(gè)安全的起始狀態(tài),但它可能執(zhí)行一些操作——如打開(kāi)一個(gè)文件。除非用戶(hù)完成對(duì)象的使用,并調(diào)用一個(gè)非凡的清除方法,否則那些操作不會(huì)得到正確的清除。若從一個(gè)構(gòu)建器內(nèi)部“擲”出一個(gè)違例,這些清除行為也可能不會(huì)正確地發(fā)生。所有這些都意味著在編寫(xiě)構(gòu)建器時(shí),我們必須非凡加以留意。
  由于前面剛學(xué)了finally,所以大家可能認(rèn)為它是一種合適的方案。但事情并沒(méi)有這么簡(jiǎn)單,因?yàn)閒inally每次都會(huì)執(zhí)行清除代碼——即使我們?cè)谇宄椒ㄟ\(yùn)行之前不想執(zhí)行清除代碼。因此,假如真的用finally進(jìn)行清除,必須在構(gòu)建器正常結(jié)束時(shí)設(shè)置某種形式的標(biāo)志。而且只要設(shè)置了標(biāo)志,就不要執(zhí)行finally塊內(nèi)的任何東西。由于這種做法并不完美(需要將一個(gè)地方的代碼同另一個(gè)地方的結(jié)合起來(lái)),所以除非非凡需要,否則一般不要嘗試在finally中進(jìn)行這種形式的清除。
  在下面這個(gè)例子里,我們創(chuàng)建了一個(gè)名為InputFile的類(lèi)。它的作用是打開(kāi)一個(gè)文件,然后每次讀取它的一行內(nèi)容(轉(zhuǎn)換為一個(gè)字串)。它利用了由java標(biāo)準(zhǔn)IO庫(kù)提供的FileReader以及BufferedReader類(lèi)(將于第10章討論)。這兩個(gè)類(lèi)都非常簡(jiǎn)單,大家現(xiàn)在可以毫無(wú)困難地把握它們的基本用法:
  
  //: Cleanup.java
  // Paying attention to exceptions
  // in constrUCtors
  import java.io.*;
  
  class InputFile {
   PRivate BufferedReader in;
   InputFile(String fname) throws Exception {
    try {
     in =
      new BufferedReader(
       new FileReader(fname));
     // Other code that might throw exceptions
    } catch(FileNotFoundException e) {
     System.out.println(
      "Could not open " + fname);
     // Wasn't open, so don't close it
     throw e;
    } catch(Exception e) {
     // All other exceptions must close it
     try {
      in.close();
     } catch(IOException e2) {
      System.out.println(
       "in.close() unsuccessful");
     }
     throw e;
    } finally {
     // Don't close it here!!!
    }
   }
   String getLine() {
    String s;
    try {
     s = in.readLine();
    } catch(IOException e) {
     System.out.println(
      "readLine() unsuccessful");
     s = "failed";
    }
    return s;
   }
   void cleanup() {
    try {
     in.close();
    } catch(IOException e2) {
     System.out.println(
      "in.close() unsuccessful");
    }
   }
  }
  
  public class Cleanup {
   public static void main(String[] args) {
    try {
     InputFile in =
      new InputFile("Cleanup.java");
     String s;
     int i = 1;
     while((s = in.getLine()) != null)
      System.out.println(""+ i++ + ": " + s);
     in.cleanup();
    } catch(Exception e) {
     System.out.println(
      "Caught in main, e.printStackTrace()");
     e.printStackTrace();
    }
   }
  } ///:~
  
  該例使用了Java 1.1 IO類(lèi)。
  用于InputFile的構(gòu)建器采用了一個(gè)String(字串)參數(shù),它代表我們想打開(kāi)的那個(gè)文件的名字。在一個(gè)try塊內(nèi)部,它用該文件名創(chuàng)建了一個(gè)FileReader。對(duì)FileReader來(lái)說(shuō),除非轉(zhuǎn)移并用它創(chuàng)建一個(gè)能夠?qū)嶋H與之“交談”的BufferedReader,否則便沒(méi)什么用處。注重InputFile的一個(gè)好處就是它同時(shí)合并了這兩種行動(dòng)。
  若FileReader構(gòu)建器不成功,就會(huì)產(chǎn)生一個(gè)FileNotFoundException(文件未找到違例)。必須單獨(dú)捕捉這個(gè)違例——這屬于我們不想關(guān)閉文件的一種非凡情況,因?yàn)槲募形闯晒Υ蜷_(kāi)。其他任何捕捉從句(catch)都必須關(guān)閉文件,因?yàn)槲募言谶M(jìn)入那些捕捉從句時(shí)打開(kāi)(當(dāng)然,假如多個(gè)方法都能產(chǎn)生一個(gè)FileNotFoundException違例,就需要稍微用一些技巧。此時(shí),我們可將不同的情況分隔到數(shù)個(gè)try塊內(nèi))。close()方法會(huì)擲出一個(gè)嘗試過(guò)的違例。即使它在另一個(gè)catch從句的代碼塊內(nèi),該違例也會(huì)得以捕捉——對(duì)Java編譯器來(lái)說(shuō),那個(gè)catch從句不過(guò)是另一對(duì)花括號(hào)而已。執(zhí)行完本地操作后,違例會(huì)被重新“擲”出。這樣做是必要的,因?yàn)檫@個(gè)構(gòu)建器的執(zhí)行已經(jīng)失敗,我們不希望調(diào)用方法來(lái)假設(shè)對(duì)象已正確創(chuàng)建以及有效。
  在這個(gè)例子中,沒(méi)有采用前述的標(biāo)志技術(shù),finally從句顯然不是關(guān)閉文件的正確地方,因?yàn)檫@可能在每次構(gòu)建器結(jié)束的時(shí)候關(guān)閉它。由于我們希望文件在InputFile對(duì)象處于活動(dòng)狀態(tài)時(shí)一直保持打開(kāi)狀態(tài),所以這樣做并不恰當(dāng)。
  getLine()方法會(huì)返回一個(gè)字串,其中包含了文件中下一行的內(nèi)容。它調(diào)用了readLine(),后者可能產(chǎn)生一個(gè)違例,但那個(gè)違例會(huì)被捕捉,使getLine()不會(huì)再產(chǎn)生任何違例。對(duì)違例來(lái)說(shuō),一項(xiàng)非凡的設(shè)計(jì)問(wèn)題是決定在這一級(jí)完全控制一個(gè)違例,還是進(jìn)行部分控制,并傳遞相同(或不同)的違例,或者只是簡(jiǎn)單地傳遞它。在適當(dāng)?shù)臅r(shí)候,簡(jiǎn)單地傳遞可極大簡(jiǎn)化我們的編碼工作。getLine()方法會(huì)變成:
  String getLine() throws IOException {
  return in.readLine();
  }
  但是當(dāng)然,調(diào)用者現(xiàn)在需要對(duì)可能產(chǎn)生的任何IOException進(jìn)行控制。
  用戶(hù)使用完畢InputFile對(duì)象后,必須調(diào)用cleanup()方法,以便釋放由BufferedReader以及/或者FileReader占用的系統(tǒng)資源(如文件句柄)——注釋⑥。除非InputFile對(duì)象使用完畢,而且到了需要棄之不用的時(shí)候,否則不應(yīng)進(jìn)行清除。大家可能想把這樣的機(jī)制置入一個(gè)finalize()方法內(nèi),但正如第4章指出的那樣,并非總能保證finalize()獲得正確的調(diào)用(即便確定它會(huì)調(diào)用,也不知道何時(shí)開(kāi)始)。這屬于Java的一項(xiàng)缺陷——除內(nèi)存清除之外的所有清除都不會(huì)自動(dòng)進(jìn)行,所以必須知會(huì)客戶(hù)程序員,告訴他們有責(zé)任用finalize()保證清除工作的正確進(jìn)行。
  
  ⑥:在C++里,“破壞器”可幫我們控制這一局面。
  
  在Cleanup.java中,我們創(chuàng)建了一個(gè)InputFile,用它打開(kāi)用于創(chuàng)建程序的相同的源文件。同時(shí)一次讀取該文件的一行內(nèi)容,而且添加相應(yīng)的行號(hào)。所有違例都會(huì)在main()中被捕捉——盡管我們可選擇更大的可靠性。
  這個(gè)示例也向大家展示了為何在本書(shū)的這個(gè)地方引入違例的概念。違例與Java的編程具有很高的集成度,這主要是由于編譯器會(huì)強(qiáng)制它們。只有知道了如何操作那些違例,才可更進(jìn)一步地把握編譯器的知識(shí)。

發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄冈市| 来安县| 山东省| 衡阳市| 兴文县| 正安县| 嘉鱼县| 嘉峪关市| 都江堰市| 孝感市| 崇义县| 扶余县| 琼中| 延长县| 汪清县| 读书| 阿鲁科尔沁旗| 浑源县| 马关县| 洪洞县| 滁州市| 汶川县| 平利县| 措勤县| 祥云县| 东山县| 淳化县| 若尔盖县| 河东区| 镇平县| 韶关市| 临沭县| 博爱县| 甘孜| 丰顺县| 绥芬河市| 商城县| 潮州市| 灵宝市| 呼伦贝尔市| 神木县|