黎沫

导航

201871010119-帖佼佼《面向对象程序设计(java)》第十周学习总结

博文正文开头格式:(2分)

项目

内容

这个作业属于哪个课程

 https://www.cnblogs.com/nwnu-daizh/

这个作业的要求在哪里

   https://www.cnblogs.com/nwnu-daizh/p/11435127.html

作业学习目标

  1. (1) 掌握接口定义方法;

    (2) 掌握实现接口类的定义要求;

    (3) 掌握实现了接口类的使用要求;

    (4) 掌握程序回调设计模式;

    (5) 掌握Comparator接口用法;

    (6) 掌握对象浅层拷贝与深层拷贝方法;

    (7) 掌握Lambda表达式语法;

    (8) 了解内部类的用途及语法要求。

第一部分:总结第五章理论知识(30分)

1、概念:异常,异常类型、声明抛出异常、异常抛出、异常捕获。

2、异常的概念:程序执行过程中所发生的异常事件,它中断指令的正常执行。

例如:

package chart7;

 

public class HelloWorld {

 

       public static void main(String[] args) {

              // TODO Auto-generated method stub

              int i = 0;

              String greetings[]= {"Hello World!", "Hello!", "HELLLO WORLD!!"};

              while(i < 3) {

                     System.out.println(greetings[i]);

              }

       }

}

(1)Java的异常处理机制可以控制程序从错误产生的位置转移到能够进行错误处理的位置。

(2)程序中出现的常见错误和问题有:

       1)用户输入错误;

       2)设备错误;

       3)物理错误;

       4)代码错误;

3、异常分类:

         Java把程序运行时可能遇到的错误分成了两类:

        1)非致命异常:通过某种修正后程序还能继续执行(异常),如:文件不存在,无效的数组下标,空引用,网络断开,打印机脱机,磁盘满等。Java中提供了一种独特的异常处理机制来处理这类问题;

        2)致命异常:程序遇到了非常不正常的状态,不嫩那个简单恢复执行,是致命的错误。  如:内存耗尽,系统内部错误等。这种错误程序本身无法解决。

4、Java的异常类直接或间接地继承于Throwable类。除内置异常类外,程序员可自定义异常类。

       Java的异常类可分为两大类:

    (1)Error

         Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。应用程序不应该捕获这类异常,也不会抛出这种异常;

    (2)Exception

         Exception类是需重点掌握的异常类。Exception层次结构又分解为两个分支:1)一个分支派生于RuntimeException:2)另一个分支包含其他异常。

    a、RuntimeException为运行时异常类,一般是程序错误产生;

       A、派生于RuntimeException的异常包含下面几种情况:

                     1)错误的类型转换;

           2)数组访问越界;

           3)访问空指针;

       B、Java将派生于Error类或RuntimeException类的所有异常称为未检查异常,编译器允许不对它们异常处理。

注意:“如果出现RuntimeException异常,就一定是程序员的问题!!!”

  C、非运行时异常中程序员本身没有问题,但由于某种情况的变化,程序不能正常运行,导致异常出现。

       D、除运行时异常外,其他继承自Exception类的异常类包括:

1、试图在文件尾部后面读取数据;

2、试图打开一个错误格式的URL;

       编译器要求程序必须对这类异常进行处理,称为已检查异常

3、RuntimeException类(运行时异常)包括:算数异常类;数组存储异常类;类型强制转换异常类;下标越界异常类;空指针异常类;违背安全原则异常类,输入输出异常类。

异常小结:

Error:    很难恢复的严重错误,一般不由程序处理;

RuntimeException:  程序设计或实现上的问题,如数组越界等;

其他异常:  通常是由环境因素引起的,并且可以被处理。如文件不存在,无效URL等。

5、声明抛出异常(已检查异常)

(1)声明抛出异常:如果一个方法可能会生成一些异常,但是该方法并不确切知道如何对这些异常事件进行处理,此时,这个方法就需声明抛出这些异常。

“一个方法不仅需要告诉编译器将要返回什么值,还要告诉编译器可能发生什么异常”。

(2)声明抛出异常在方法声名中用throws子句来指明。

例如:

public  FileInputStream(String name) throws FileNotFoundException

throws子句可以同时指明多个异常,说明该方法将不对这些异常进行处理,而是声明抛出它们。

(3)一下四种情况需要方法用throws子句声明抛出异常:

A、方法调用了一个抛出已检查异常的方法;

B、程序运行过程中可能会发生错误,并且利用子句throw语句抛出一个已检查异常对象;

C、程序出现错误;

D、Java虚拟机和运行时库出现的内部异常。

注意:一个方法必须声明该方法所有可能抛出的已检查异常,而未检查异常要么不可控制(Error),要么避免发生(RuntimeException)。

如果方法没有声明所有可能发生的已检查异常,编译器会给出一个错误信息。

6、抛出异常

(1)当Java应用程序出现错误时,会根据错误类型产生一个异常对象,这个对象包含了异常的类型和错误出现时程序所处的状态信息。把异常对象递交给Java编译器的过程称为抛出。

(2)抛出异常要生成异常对象,异常对象可由某些类的实例生成,也可以由JVM生成。

(3)抛出异常对象通过throw语句来实现。

(4)如何抛出异常:

1)首先要决定抛出异常的类型。

2)对于已存在的异常类,抛出该类的异常对象非常容易,步骤是:

a、找到一个合适的异常类;

b、创建这个类的一个对象;

c、将该对象抛出。

3)一个方法抛出了异常后,它就不会返回调用者了。

7、创建异常类:

1)自定义异常类:

定义一个派生于Exception的直接或间接子类。如一个派生于IOException的类。

2)自定义异常类应该包括两个构造器:

默认构造器;

带有详细描述信息的构造器(超类Throwable的toString方法会打印出这些详细的信息,有利于代码调试)

8、捕获异常:

程序运行期间,异常发生时,Java运行系统从异常生成的代码块开始,寻找相应的异常处理代码,并将异常交给该方法处理,这一过程叫做捕获。

某个异常发生时,若程序没有在任何地方进行该异常的捕获,则程序就会终止执行,并在控制台上输出异常信息。

若捕获一个异常,需要在程序中设置一个try/catch/finally块:

——try语句括住可能抛出异常的代码块;

——catch语句指明要捕获的异常类及相应的处理代码;

——finally语句指明必须执行的代码块。

(1) try子句:

捕获异常的第一步是用try{……}子句选定捕获异常的代码范围,由try所限定的代码块中的语句在执行过程中可能会自动生成异常对象并抛出。

对于异常处理可以捕获,也可以只声明抛出不作任何处理;

(2) catch子句:

1)         catch块是对异常对象进行处理的代码:

2)         每个try代码块可以伴随一个或多个catch语句,用于处理try代码块中所生成的各类异常事件;

3)         Catch语句只需要一个形式参数指明它所能捕获的异常类对象,这个异常类必须是Throwable类的子类,运行时系统通过参数值把被抛出的异常对象传递给catch块:

4)         Catch块可以通过异常对象调用类Throwable所提供的方法,

getMessage():用来得到有关异常事件的信息;

printStackTrace():用来跟踪异常事件发生时执行堆栈的内容;

5)可以在一个try块中不或多个异常类型,每个异常类型需要一个单独的catch子句;

6)catch语句的顺序:

捕获异常的顺序和不同catch语句的顺序有关,当捕获到一个异常时,剩下的catch语句就不再进行匹配;

因此在安排catch语句的顺序时,首先应该捕获最特殊的异常,然后再逐一一般化,也就是一般先安排子类,再安排父类;

再次抛出异常与异常链:

Catch子句也可以抛出一个异常,这样做的目的时改变一刹那过的类型。

(3) finally子句:

捕获异常的最后一步就是通过finally语句为异常处理提供一个有统一的出口,使得控制流程再转到程序其他部分以前,能够对程序状态做统一的管理。

不论在try代码块中是否发生了异常事件,finally块中的语句都会被执行。

9、异常处理中分析堆栈跟踪元素:

 堆栈跟踪是程序执行中一个方法调用过程中的列表,它包括了程序执行过程中方法调用的特定位置;

10、使用异常机制的建议:

  程序编码时已成处理的两种方式

  (1)积极处理方式:确切知道如何如何处理的异常应该捕获;

//积极处理方式  

import java.io.*;

 

class ExceptionTest {

    public static void main (string args[])

   {

       try{

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

       }

       catchFileNotFoundExcption e)

       {   ……  }

    ……

    }

}

  (2)消极处理方式:不知道如何去处理的异常声明抛出;

//消极处理方式

 

import java.io.*;

class ExceptionTest {

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

     {

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

     }

}

异常处理的原则

         (1)异常处理不能代替简单的条件检测,只在异常情况下使用异常机制。

        (2)程序代码不要过分细化异常,尽量将有可能产生异常的语句放在一个try语句块中;

   (3)抛出的异常尽可能明确;

   (4)不要压制异常,对于很少发生的异常,应该将其关闭;

    (5)早抛出,晚捕获,尽量让高层次的方法通告用户发生了错误。

 11、断言:

  断言是程序开发和测试阶段用于插入一些代码错误检测语句的工具。

  断言语法如下:

    assert   条件      或者     assert  条件:   表达式

这两个形式都会对布尔“条件”进行判断,如果判断结果为假(false),说明程序已经处于不正确的状态下,系统则抛出AssertionError,给出警告并且退出,在第二种形式中,“表达式”会传入AssertionError的构造函数中并转成一个消息字符串; 

第二部分:实验部分

实验1:用命令行与IDE两种环境下编辑调试运行源程序ExceptionDemo1、ExceptionDemo2,结合程序运行结果理解程序,掌握未检查异常和已检查异常的区别。(5分)

public class ExceptionDemo1 {
	public static void main(String args[]) {
		int a = 0;
		System.out.println(5 / a);    //分母为零,程序报错。
	}
}

  运行结果如下:

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();
      }
}

  运行结果如下:

 

 

实验2:

导入以下示例程序,测试程序并进行代码注释。

测试程序1:(5分)

l  在elipse IDE中编辑、编译、调试运行教材281页7-1,结合程序运行结果理解程序;

l  在程序中相关代码处添加新知识的注释;

l  掌握Throwable类的堆栈跟踪方法;

实验代码如下:

package stackTrace;

import java.util.*;

/**
 * A program that displays a trace feature of a recursive method call.
 * @version 1.10 2017-12-14
 * @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)     //求n的阶乘
   {
      System.out.println("factorial(" + n + "):");
      StackWalker walker = StackWalker.getInstance();    //创建一个表示指定执行点的堆栈跟踪元素walker,调用getInstance()方法
      walker.forEach(System.out::println);      
      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)
   {
      try (Scanner in = new Scanner(System.in))   //try子句
      {
         System.out.print("Enter n: ");
         int n = in.nextInt();
         factorial(n);
      }
   }
}

  运行结果如下:

实验2:测试程序2

l  Java语言的异常处理有积极处理方法和消极处理两种方式;

//积极处理方式  
import java.io.*;

class ExceptionTest {
	public static void main (string args[])
   {
       try{
	       FileInputStream fis=new FileInputStream("text.txt");
       }
       catch(FileNotFoundExcption e)
    	{   ……  }
	……
    }
}

  

//消极处理方式

import java.io.*;
class ExceptionTest {
	public static void main (string args[]) throws  FileNotFoundExcption
     {
 	    FileInputStream fis=new FileInputStream("text.txt");
     }
}

l  下列两个简单程序范例给出了两种异常处理的代码格式。在elipse IDE中编辑、调试运行源程序ExceptionTest.java,将程序中的text文件更换为身份证号.txt,要求将文件内容读入内容,并在控制台显示;

l  掌握两种异常处理技术的特点。(10分)

实验代码如下:

//积极处理方式
import java.io.*; class ExceptionTest { public static void main (String args[]) { try{ FileInputStream fis=new FileInputStream("D:\\身份证号.txt"); BufferedReader in = new BufferedReader(new InputStreamReader(fis)); String s = new String(); while ((s = in.readLine()) != null) { System.out.println(s); } in.close(); fis.close(); } catch (FileNotFoundException e) { System.out.println("文件找不到"); e.printStackTrace(); } catch (IOException e) { System.out.println("文件读取错误"); e.printStackTrace(); } } }

  运行结果如下:

//消极处理方式
import java.io.*;

public class ExceptionTest {
    public static void main (String args[]) throws IOException
   {
         
       try{
           FileInputStream fis=new FileInputStream("D:\\身份证号.txt");
           BufferedReader in = new BufferedReader(new InputStreamReader(fis));
           String s = new String();
           while ((s = in.readLine()) != null) {
               System.out.println(s);
           }
           in.close();
           fis.close();
       }
       finally {
    	   
       }
 
   }
}

  

实验3:编程练习(25分)

l  编写一个计算器类,可以完成加、减、乘、除的操作;

l  利用计算机类,设计一个小学生100以内数的四则运算练习程序,由计算机随机产生10道加减乘除练习题,学生输入答案,由程序检查答案是否正确,每道题正确计10分,错误不计分,10道题测试结束后给出测试总分;

l  将程序中测试练习题及学生答题结果输出到文件,文件名为test.txt;

|  在以上程序适当位置加入异常捕获代码。

实验代码如下:

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

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

        Scanner in = new Scanner(System.in);
        Number counter = new Number();
        PrintWriter out = null;
        //try——catch语句
        try {
            out = new PrintWriter("text.txt");
            } 
        catch (FileNotFoundException e) {
            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 c = in.nextInt();
                out.println(a + "/" + b + "=" + c);
                if (c == counter.division(a, b)) {
                    sum += 10;
                    System.out.println("回答正确");
                } else {
                    System.out.println("回答错误");
                }

                break;

            case 1:
                System.out.println(i + ": " + a + "*" + b + "=");
                int c1 = in.nextInt();
                out.println(a + "*" + b + "=" + c1);
                if (c1 == counter.multiplication(a, b)) {
                    sum += 10;
                    System.out.println("回答正确");
                } else {
                    System.out.println("回答错误");
                }
                break;
            case 2:
                System.out.println(i + ": " + a + "+" + b + "=");
                int c2 = in.nextInt();
                out.println(a + "+" + b + "=" + c2);
                if (c2 == counter.add(a, b)) {
                    sum += 10;
                    System.out.println("回答正确");
                } else {
                    System.out.println("回答错误");
                }

                break;
            case 3:
                System.out.println(i + ": " + a + "-" + b + "=");
                int c3 = in.nextInt();
                out.println(a + "-" + b + "=" + c3);
                if (c3 == 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 Number {
    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)       //分母不为0
            return a / b; 
        else
            return 0;
    }
}

运行结果如下:

 

实验代码如下:

public class TestHello {

	public static void main(String[] args) {
		  TestHello  test = new TestHello();
		  int sum = test.sum(8,9);
		  int subduction = test.subduction(52,12);
		  int multiplication= test.multiplication(3, 7);
		  double division = test.division(81, 9);
		  System.out.println("加法运算的结果为:" + sum);
		  System.out.println("减法运算的结果为:" + subduction);
		  System.out.println("乘法运算的结果为:" + multiplication);
		  System.out.println("除法运算的结果为:" + division);
	}	
          //System.out.println("总分为:" + score);
public int sum(int a, int b) {  //定义加法方法
	  int resultsum = a + b;
      return resultsum;
  }

public int subduction(int a, int b) {  //定义减法方法
	  int resultsubduction = a - b;
      return resultsubduction;
  }

public int multiplication(int a, int b) {    //定义乘法方法
  int resultmultiplication =  a * b;
  return resultmultiplication;
}

public double division(int a, int b) {     //定义除法方法
	double resultdiv = 0;
  if (b != 0) {      //分母不为0
  	resultdiv = a / b; 
  }
  else {
  	resultdiv = 0;
 }
	return resultdiv;
 }
}

  运行结果如下:

程序步骤分析:

        新建一个TestHello类,定义加法的方法。定义方式为声明两个变量,然后相加,赋给第三个变量,并使用return返回出来;

同样地,定义减法,乘法以及除法的方法。不同的是,在定义除法方法时,不再是int型的,而是double类型的变量,除数不能为0,所以判断一下。

最后在main函数中,实例化该TestHello类,并通过实例化的别名点方法名实现调用加减乘除的方法                                                         

实验4::断言、日志、程序调试技巧验证实验。

测试程序1

l  在elipse下调试程序AssertDemo,结合程序运行结果理解程序;

l  注释语句test1(-5);后重新运行程序,结合程序运行结果理解程序;

l  掌握断言的使用特点及用法。(5分)

实验代码如下:

//断言程序示例
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);
    }
}

  运行结果如下:

实验4:测试程序2

l  用JDK命令调试运行教材298页-300页程序7-2,结合程序运行结果理解程序;

l  并掌握Java日志系统的用途及用法。(5分)

实验代码如下:

//断言程序示例
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);
    }
}

  运行结果如下:

实验4:

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;
            FileHandler 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(() ->
            {
               WindowHandler windowHandler = new WindowHandler();
               windowHandler.setLevel(Level.ALL);
               Logger.getLogger("com.horstmann.corejava").addHandler(windowHandler);

               ImageViewerFrame 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();
      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的常用调试技术。

①条件断点 –在Eclipse Java 编辑区的行头双击就会得到一个断点, 代码会运行到此处时停止。

–条件断点,顾名思义就是一个有一定条件的断点,只有满足了用户设置的条件,代码才会在运行到断点处时停止。

–在断点处点击鼠标右键,选择后一个“Breakpoint Properties”.(5分)

实验代码如下:

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;
            FileHandler 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(() ->
            {
               WindowHandler windowHandler = new WindowHandler();
               windowHandler.setLevel(Level.ALL);
               Logger.getLogger("com.horstmann.corejava").addHandler(windowHandler);

               ImageViewerFrame 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();
      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();
   }
}

  

实验总结:(15分)

       这周主要学习了异常以及异常的处理方法。异常是程序执行过程中所发生的异常事件,它中断指令的正常执行。因此在编写代码时需要及时处理这些错误。对于异常处理,老师用两节理论课给我们讲,在课下总结有关异常以及异常处理的知识点时,感觉上课听的不是太懂。知道了用抛出异常和将可能出错的语句放入try子句中两种方法,try——catch子句是一起存在的。对于断言以及日志等内容,也学的不明白,自己在讲之前看了课本内容,完全不理解。在运行最后一个实验程序时,对程序不理解,没看懂为什么运行结果是那样的。还有就是老师布置的编程题,我自己能做出来的就是第二种了,虽然不符合老师的要求,但是是自己尽力做的,之后我会好好看网上给出的答案,尽力去理解。

获奖感言:对于期中考试之后获得小黄衫,我很荣幸。可能自己真正学到的有关Java编程的知识不是很好,在具体应用学到的知识这一方面还很欠缺。小黄衫,它不仅是一种奖励,是一种动力,同时它也给我一种压力,它让我意识到接下来的学习要更加的努力,才不会辜负老师的期望,才能对得起小黄衫的价值。在接下来的学习中,我会坚持,尽力而为。

posted on 2019-11-03 17:30  黎沫  阅读(302)  评论(1编辑  收藏  举报