1. 程式人生 > >201771010135楊蓉慶 《面對對象程序設計(java)》第九周學習總結

201771010135楊蓉慶 《面對對象程序設計(java)》第九周學習總結

應用 script 常對象 sum app 註釋 NPU 練習題 產生

第7章 異常、日誌、斷言和調試

1、實驗目的與要求

(1) 掌握java異常處理技術;

(2) 了解斷言的用法;

(3) 了解日誌的用途;

(4) 掌握程序基礎調試技巧;

一、理論知識

1、異常:在程序的執行過程中所發生的異常事件,它 中斷指令的正常執行。

2、Java的異常處理機制可以控制程序從錯誤產生的 位置轉移到能夠進行錯誤處理的位置。

3、異常分類:Java把程序運行時可能遇到的錯誤分為兩類:

–非致命異常:通過某種修正後程序還能繼續執行。 這類錯誤叫作異常。如:文件不存在、無效的數組 下標、空引用、網絡斷開、打印機脫機、磁盤滿等。 Java中提供了一種獨特的處理異常的機制,通過異 常來處理程序設計中出現的錯誤。

–致命異常:程序遇到了非常嚴重的不正常狀態,不 能簡單恢復執行,是致命性錯誤。如:內存耗盡、 系統內部錯誤等。這種錯誤程序本身無法解決。

4、Java中的異常類可分為兩大類:

- Error類層次結構描述了Java 運行時系統的內部錯誤 和資源耗盡錯誤。應用程序不應該捕獲這類異常,也 不會拋出這種異常 。

- Exception Exception類:重點掌握的異常類。Exception層次結 構又分解為兩個分支:一個分支派生於 RuntimeException;另一個分支包含其他異常。

5、 編譯器要求程序必須對這類異常進行處理 (checked),稱為已檢查異常。

6、聲明拋出異常:如果一個方法可能會生成一些異 常,但是該方法並不確切知道如何對這些異常事 件進行處理,此時,這個方法就需聲明拋出這些 異常。

“一個方法不僅需要告訴編譯器將要返回什麽值 ,還要告訴編譯器可能發生什麽異常”。

7、聲明拋出異常在方法聲明中用throws子句中來指 明。例如: – public FileInputStream(String name ) throws FileNotFoundException

8、以下4種情況需要方法用throws子句聲明拋出異常:

–方法調用了一個拋出已檢查異常的方法。

–程序運行過程中可能會發生錯誤,並且利用throw語句 拋出一個已檢查異常對象。

–程序出現錯誤。例如,a[-1] = 0;

–Java虛擬機和運行時庫出現的內部異常。

9、一個方法必須聲明該方法所有可能拋出的已檢查異常,而 未檢查異常要麽不可控制(Error),要麽應該避免發生 (RuntimeException)。如果方法沒有聲明所有可能發生 的已檢查異常,編譯器會給出一個錯誤消息。

10、當Java應用程序出現錯誤時,會根據錯誤類型產 生一個異常對象,這個對象包含了異常的類型和 錯誤出現時程序所處的狀態信息。把異常對象遞 交給Java編譯器的過程稱為拋出。

11、程序運行期間,異常發生時,Java運行系統從異常 生成的代碼塊開始,尋找相應的異常處理代碼,並 將異常交給該方法處理,這一過程叫作捕獲。

12、catch塊是對異常對象進行處理的代碼; ? 每個try代碼塊可以伴隨一個或多個catch語句,用於處理 try代碼塊中所生成的各類異常事件; ? catch語句只需要一個形式參數指明它所能捕獲的異常類 對象,這個異常類必須是Throwable的子類,運行時系統 通過參數值把被拋出的異常對象傳遞給catch塊; ? catch塊可以通過異常對象調用類Throwable所提供的方法。

日誌:

全局日誌記錄(global logger)

Logger.getGlobal().info("test");

Logger.getGlobal().serLevel(Level.OFF);

可以使用getLogger方法創建或獲取記錄器,未被任何變量引用的日誌記錄器可能會被垃圾回收,所以可以使用靜態變量存儲日誌記錄器的一個引用

private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp");

、實驗內容和步驟

實驗1:用命令行與IDE兩種環境下編輯調試運行源程序ExceptionDemo1、ExceptionDemo2,結合程序運行結果理解程序,掌握未檢查異常和已檢查異常的區別。

//異常示例1
public class ExceptionDemo1 {
    public static void main(String args[]) {
        int a = 0;
        System.out.println(5 / a);
    }
}
//異常示例2
import java.io.*;

public class ExceptionDemo2 {
    public static void main(String args[]) 
     {
          FileInputStream fis=new FileInputStream("text.txt");//JVM自動生成異常對象
          int b;
          while((b=fis.read())!=-1)
          {
              System.out.print(b);
          }
          fis.close();
      }
}

代碼如下:1、

public class ExceptionDemo1 {
    public static void main(String args[]) {
        int a = 0;
        if(a==0) {
            System.out.println("除數為零");
            }
        else {
System.out.println(5 / a);
    }
}}

結果如下:

技術分享圖片

2、

import java.io.*;
public class ExceptionDemo2 {
    public static void main(String args[]) throws IOException 
    {
         FileInputStream fis=new FileInputStream("text.txt");//JVM自動生成異常對象
         int b;
         while((b=fis.read())!=-1)
         {
             System.out.print(b);
         }
         fis.close();
     }
}

或者是

import java.io.*;
public class ExceptionDemo2 {
    public static void main(String args[])  
    {
        try {
            File file=new File("text.txt");
         FileInputStream fis=new FileInputStream(file);//JVM自動生成異常對象
         BufferedReader in=new BufferedReader(new FileReader(file));
         String b;
         while((b=in.readLine())!=null)
         {
             System.out.print(b);
         }
         fis.close();
     }
        catch (Exception e) {
            System.out.print("cuowu");
        }
            
        }
}

結果如下:1技術分享圖片

2、技術分享圖片

實驗2 導入以下示例程序,測試程序並進行代碼註釋。

測試程序1:

  • 在elipse IDE中編輯、編譯、調試運行教材281頁7-1,結合程序運行結果理解程序;
  • 在程序中相關代碼處添加新知識的註釋;
  • 掌握Throwable類的堆棧跟蹤方法;
package stackTrace;

import java.util.*;

/**
 * A program that displays a trace feature of a recursive method call.
 * @version 1.01 2004-05-10
 * @author Cay Horstmann
 */
public class StackTraceTest//方法調用過程
{
   /**
    * Computes the factorial of a number
    * @param n a non-negative integer
    * @return n! = 1 * 2 * . . . * n
    */
   public static int factorial(int n)
   {
      System.out.println("factorial(" + n + "):");
      Throwable t = new Throwable();//調用類的getStackTrace方法
      StackTraceElement[] frames = t.getStackTrace();
      for (StackTraceElement f : frames)
         System.out.println(f);//打印出f
      int r;
      if (n <= 1) r = 1;
      else r = n * factorial(n - 1);
      System.out.println("return " + r);
      return r;//計算過程
   }

   public static void main(String[] args)
   {
      Scanner in = new Scanner(System.in);
      System.out.print("Enter n: ");
      int n = in.nextInt();
      factorial(n);//輸出階乘
   }
}

結果如下:

技術分享圖片

測試程序2:

l Java語言的異常處理積極處理方法和消極處理兩種方式

l 下列兩個簡答程序範例給出了兩種異常處理的代碼格式。在elipse IDE中編輯、調試運行源程序ExceptionalTest.java,將程序中的text文件更換為身份證號.txt,要求將文件內容讀入內容,並在控制臺顯示;

掌握兩種異常處理技術的特點

//積極處理方式  

import java.io.*;

class ExceptionTest {

public static void main (string args[])

{

try{

FileInputStream fis=new FileInputStream("text.txt");

}

catchFileNotFoundExcption e)

{ …… }

……

}

}

//消極處理方式

import java.io.*;

class ExceptionTest {

public static void main (string args[]) throws FileNotFoundExcption

{

FileInputStream fis=new FileInputStream("text.txt");

}

}

代碼如下:

//積極處理方式  
  
  import java.io.*;
  import java.io.BufferedReader;
  import java.io.FileReader;
  class ExceptionTest {
   public static void main (String args[])
 {
    File fis=new File("身份證號.txt");
        try{
 
            FileReader fr = new FileReader(fis);
            BufferedReader br = new BufferedReader(fr);
            //捕獲並處理異常語句
            try {
                String s, s2 = new String();
                while ((s = br.readLine()) != null) {
                    s2 += s + "\n ";
                }
                br.close();
                System.out.println(s2);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 }
   }
package 異常;

//消極處理方式

import java.io.*;
class ExceptionTest {
    public static void main (String args[]) throws  IOException
       {
        File fis=new File("身份證號.txt");
        FileReader fr = new FileReader(fis);
        BufferedReader br = new BufferedReader(fr);
        String s, s2 = new String();

            while ((s = br.readLine()) != null) {
                s2 += s + "\n ";
            }
            br.close();
            System.out.println(s2);
       }
}

結果:

技術分享圖片

實驗3: 編程練習

練習1

l 編制一個程序,將身份證號.txt 中的信息讀入到內存中;

l 按姓名字典序輸出人員信息;

l 查詢最大年齡的人員信息;

l 查詢最小年齡人員信息;

l 輸入你的年齡,查詢身份證號.txt中年齡與你最近人的姓名、身份證號、年齡、性別和出生地;

l 查詢人員中是否有你的同鄉;

l 在以上程序適當位置加入異常捕獲代碼。

package ID;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

@SuppressWarnings("unused")
public class Main{
    private static ArrayList<Person> Personlist;
    @SuppressWarnings("resource")
    public static void main(String[] args) {
        Personlist = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        File file = new File("E:\\新建文件夾\\身份證號.txt");
          //捕獲代碼
        try {
            FileInputStream fis = new FileInputStream(file);
            BufferedReader in = new BufferedReader(new InputStreamReader(fis));
            String temp = null;
            while ((temp = in.readLine()) != null) {
                
                Scanner linescanner = new Scanner(temp);
                
                linescanner.useDelimiter(" ");    
                String name = linescanner.next();
                String ID = linescanner.next();
                String sex = linescanner.next();
                String age = linescanner.next();
                String place =linescanner.nextLine();
                Person Person = new Person();
                Person.setname(name);
                Person.setID(ID);
                Person.setsex(sex);
                int a = Integer.parseInt(age);
                Person.setage(a);
                Person.setbirthplace(place);
                Personlist.add(Person);

            }
        } catch (FileNotFoundException e) {
            System.out.println("查找不到信息");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("信息讀取有誤");
            e.printStackTrace();
        }
        boolean isTrue = true;
        while (isTrue) {
            System.out.println("————————————————————————————————————————");
            System.out.println("1:按姓名字典序輸出人員信息");
            System.out.println("2:查詢最大年齡人員信息和最小年齡人員信息");
            System.out.println("3:輸入你的年齡,查詢年齡與你最近人的所有信息");
            System.out.println("4:查詢人員中是否有你的同鄉");
           
            int nextInt = scanner.nextInt();
            switch (nextInt) {
            case 1:
                Collections.sort(Personlist);
                System.out.println(Personlist.toString());
                break;
            case 2:
                
                int max=0,min=100;int j,k1 = 0,k2=0;
                for(int i=1;i<Personlist.size();i++)
                {
                    j=Personlist.get(i).getage();
                   if(j>max)
                   {
                       max=j; 
                       k1=i;
                   }
                   if(j<min)
                   {
                       min=j; 
                       k2=i;
                   }

                }  
                System.out.println("年齡最大:"+Personlist.get(k1));
                System.out.println("年齡最小:"+Personlist.get(k2));
                break;
            case 3:
                System.out.println("place?");
                String find = scanner.next();        
                String place=find.substring(0,3);
                String place2=find.substring(0,3);
                for (int i = 0; i <Personlist.size(); i++) 
                {
                    if(Personlist.get(i).getbirthplace().substring(1,4).equals(place)) 
                        System.out.println(""+Personlist.get(i));

                } 

                break;
            case 4:
                System.out.println("年齡:");
                int yourage = scanner.nextInt();
                int near=agenear(yourage);
                int d_value=yourage-Personlist.get(near).getage();
                System.out.println(""+Personlist.get(near));
           /*     for (int i = 0; i < Personlist.size(); i++)
                {
                    int p=Personlist.get(i).getage()-yourage;
                    if(p<0) p=-p;
                    if(p==d_value) System.out.println(Personlist.get(i));
                }   */
                break;
            case 5:
           isTrue = false;
           System.out.println("退出程序!");
                break;
            default:
                System.out.println("輸入有誤");            }
        }
    }
    public static int agenear(int age) {
     
       int j=0,min=53,d_value=0,k=0;
        for (int i = 0; i < Personlist.size(); i++)
        {
            d_value=Personlist.get(i).getage()-age;
            if(d_value<0) d_value=-d_value; 
            if (d_value<min) 
            {
               min=d_value;
               k=i;
            }

         }    return k;
        }
}

package ID;
public class Person implements Comparable<Person> {
private String name;
private String ID;
private int age;
private String sex;
private String birthplace;

public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID= ID;
}
public int getage() {

return age;
}
public void setage(int age) {
    // int a = Integer.parseInt(age);
this.age= age;
}
public String getsex() {
return sex;
}
public void setsex(String sex) {
this.sex= sex;
}
public String getbirthplace() {
return birthplace;
}
public void setbirthplace(String birthplace) {
this.birthplace= birthplace;
}

public int compareTo(Person o) {
   return this.name.compareTo(o.getname());

}

public String toString() {
    return  name+"\t"+sex+"\t"+age+"\t"+ID+"\t"+birthplace+"\n";

}
}

結果如下:

技術分享圖片

技術分享圖片

練習2

l 編寫一個計算器類,可以完成加、減、乘、除的操作;

l 利用計算機類,設計一個小學生100以內數的四則運算練習程序,由計算機隨機產生10道加減乘除練習題,學生輸入答案,由程序檢查答案是否正確,每道題正確計10分,錯誤不計分,10道題測試結束後給出測試總分;

l 將程序中測試練習題及學生答題結果輸出到文件,文件名為test.txt

l 在以上程序適當位置加入異常捕獲代碼。

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;


public class Demo {
    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        jf counter=new jf();
        PrintWriter out = null;
        try {
            out = new PrintWriter("text.txt");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        int sum = 0;

        
        
        for (int i = 1; i <=10; i++) {
            int a = (int) Math.round(Math.random() * 100);
            int b = (int) Math.round(Math.random() * 100);
            int m= (int) Math.round(Math.random() * 3);

            
           switch(m)
           {
           case 0:
               System.out.println(i+": "+a+"/"+b+"=");
               
               while(b==0){  b = (int) Math.round(Math.random() * 100); }
               
            int c0 = in.nextInt();
            out.println(a+"/"+b+"="+c0);
            if (c0 == jf.division(a, b)) {
                sum += 10;
                System.out.println("恭喜答案正確");
            }
            else {
                System.out.println("抱歉,答案錯誤");
            }
            
            break;
            
           case 1:
               System.out.println(i+": "+a+"*"+b+"=");
               int c = in.nextInt();
               out.println(a+"*"+b+"="+c);
               if (c == counter.multiplication(a, b)) {
                   sum += 10;
                   System.out.println("恭喜答案正確");
               }
               else {
                   System.out.println("抱歉,答案錯誤");
               }
               break;
           case 2:
               System.out.println(i+": "+a+"+"+b+"=");
               int c1 = in.nextInt();
               out.println(a+"+"+b+"="+c1);
               if (c1 == counter.add(a, b)) {
                   sum += 10;
                   System.out.println("恭喜答案正確");
               }
               else {
                   System.out.println("抱歉,答案錯誤");
               }
               
               break ;
           case 3:
               System.out.println(i+": "+a+"-"+b+"=");
               int c2 = in.nextInt();
               out.println(a+"-"+b+"="+c2);
               if (c2 == counter.reduce(a, b)) {
                   sum += 10;
                   System.out.println("恭喜答案正確");
               }
               else {
                   System.out.println("抱歉,答案錯誤");
               }
               break ;

               } 
    
          }
        System.out.println("成績"+sum);
        out.println("成績:"+sum);
         out.close();

         
    }
    }
public class Counter {
   private int a;
   private int b;
    public int  add(int a,int b)
    {
        return a+b;
    }
    public int   reduce(int a,int b)
    {
        return a-b;
    }
    public int   multiplication(int a,int b)
    {
        return a*b;
    }
    public int   division(int a,int b)
    {
        if(b!=0)
        return a/b;
        else return 0;
    }

    
}

 

結果如下:

技術分享圖片

技術分享圖片

實驗4:斷言、日誌、程序調試技巧驗證實驗。

實驗程序1

/斷言程序示例
public class AssertDemo {
    public static void main(String[] args) {        
        test1(-5);
        test2(-3);
    }
    
    private static void test1(int a){
        assert a > 0;
        System.out.println(a);
    }
    private static void test2(int a){
       assert a > 0 : "something goes wrong here, a cannot be less than 0";
        System.out.println(a);
    }
}

結果是:

技術分享圖片

如果註釋語句test1(-5);後重新運行程序,結果是:

技術分享圖片

實驗程序2:

l 用JDK命令調試運行教材298頁-300頁程序7-2,結合程序運行結果理解程序;

l 並掌握Java日誌系統的用途及用法。

package logging;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.logging.*;
import javax.swing.*;

/**
 * A modification of the image viewer program that logs various events.
 * @version 1.03 2015-08-20
 * @author Cay Horstmann
 */
public class LoggingImageViewer
{
   public static void main(String[] args)
   {
      if (System.getProperty("java.util.logging.config.class") == null
            && System.getProperty("java.util.logging.config.file") == null)
      {
         try
         {
            Logger.getLogger("com.horstmann.corejava").setLevel(Level.ALL);
            final int LOG_ROTATION_COUNT = 10;
            Handler handler = new FileHandler("%h/LoggingImageViewer.log", 0, LOG_ROTATION_COUNT);
            Logger.getLogger("com.horstmann.corejava").addHandler(handler);
         }
         catch (IOException e)
         {
            Logger.getLogger("com.horstmann.corejava").log(Level.SEVERE,
                  "Can‘t create log file handler", e);
         }
      }

      EventQueue.invokeLater(() ->
            {
               Handler windowHandler = new WindowHandler();
               windowHandler.setLevel(Level.ALL);
               Logger.getLogger("com.horstmann.corejava").addHandler(windowHandler);

               JFrame frame = new ImageViewerFrame();
               frame.setTitle("LoggingImageViewer");
               frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

               Logger.getLogger("com.horstmann.corejava").fine("Showing frame");
               frame.setVisible(true);
            });
   }
}

/**
 * The frame that shows the image.
 */
class ImageViewerFrame extends JFrame
{
   private static final int DEFAULT_WIDTH = 300;
   private static final int DEFAULT_HEIGHT = 400;   

   private JLabel label;
   private static Logger logger = Logger.getLogger("com.horstmann.corejava");

   public ImageViewerFrame()
   {
      logger.entering("ImageViewerFrame", "<init>");      
      setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

      // set up menu bar
      JMenuBar menuBar = new JMenuBar();
      setJMenuBar(menuBar);

      JMenu menu = new JMenu("File");
      menuBar.add(menu);

      JMenuItem openItem = new JMenuItem("Open");
      menu.add(openItem);
      openItem.addActionListener(new FileOpenListener());

      JMenuItem exitItem = new JMenuItem("Exit");
      menu.add(exitItem);
      exitItem.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent event)
            {
               logger.fine("Exiting.");
               System.exit(0);
            }
         });

      // use a label to display the images
      label = new JLabel();
      add(label);
      logger.exiting("ImageViewerFrame", "<init>");
   }

   private class FileOpenListener implements ActionListener
   {
      public void actionPerformed(ActionEvent event)
      {
         logger.entering("ImageViewerFrame.FileOpenListener", "actionPerformed", event);

         // set up file chooser
         JFileChooser chooser = new JFileChooser();
         chooser.setCurrentDirectory(new File("."));

         // accept all files ending with .gif
         chooser.setFileFilter(new javax.swing.filechooser.FileFilter()
            {
               public boolean accept(File f)
               {
                  return f.getName().toLowerCase().endsWith(".gif") || f.isDirectory();
               }

               public String getDescription()
               {
                  return "GIF Images";
               }
            });

         // show file chooser dialog
         int r = chooser.showOpenDialog(ImageViewerFrame.this);

         // if image file accepted, set it as icon of the label
         if (r == JFileChooser.APPROVE_OPTION)
         {
            String name = chooser.getSelectedFile().getPath();
            logger.log(Level.FINE, "Reading file {0}", name);
            label.setIcon(new ImageIcon(name));
         }
         else logger.fine("File open dialog canceled.");
         logger.exiting("ImageViewerFrame.FileOpenListener", "actionPerformed");
      }
   }
}

/**
 * A handler for displaying log records in a window.
 */
class WindowHandler extends StreamHandler
{
   private JFrame frame;

   public WindowHandler()
   {
      frame = new JFrame();
      final JTextArea output = new JTextArea();
      output.setEditable(false);
      frame.setSize(200, 200);
      frame.add(new JScrollPane(output));
      frame.setFocusableWindowState(false);
      frame.setVisible(true);
      setOutputStream(new OutputStream()
         {
            public void write(int b)
            {
            } // not called

            public void write(byte[] b, int off, int len)
            {
               output.append(new String(b, off, len));
            }
         });
   }

   public void publish(LogRecord record)
   {
      if (!frame.isVisible()) return;
      super.publish(record);
      flush();
   }
}

實驗程序3:

l 用JDK命令調試運行教材298頁-300頁程序7-2,結合程序運行結果理解程序;

l 按課件66-77內容練習並掌握Elipse的常用調試技術。

技術分享圖片

三:總結

本章我學習了有關於java異常處理技術,了解了斷言的用法和日誌的用途;在老師和學長得講解下,我基本掌握了一些關於java異常處理技術得基礎應用,了解到異常和捕獲的用法,在適當的位置添加try……catch語句,實驗方面,在上周實驗的基礎上添加、深化,得到新的表現形式,總得來說,還是有很大的收獲,就是在一些語句上面還是,模棱兩可,不是特別透徹。

201771010135楊蓉慶 《面對對象程序設計(java)》第九周學習總結