第九周学习总结
第一部分:理论知识
异常、断言和调试、日志
1.捕获异常:
要捕获一个异常,必须设置try/catch语句块
例如:
try{
}catch(ExceptionType e){
}
如果方法中的任何代码抛出一个在catch字句中没有声明的异常类型,那么这个方法就会立刻退出
通常,应该捕获那些知道如何处理的异常,而将那些不知道怎么处理的异常继续传递
2.捕获多个异常:
例如:
try{
}catch(FileNotFoundException e){
}catch(UnknownHostException e){
}catch(IOException e){
}
异常对象可能包含与异常本身相关的信息。要想获得对象的更多信息,可以试着使用
e.getMessage()得到详细的错误信息
e.getClass().getName()得到异常对象的实际类型
在Java SE 7中,同一个catch字句中可以捕获多个异常类型,例如:
try{
}catch(FileNotFoundException | UnknownHostException e){
}
3.常见的断言方式
前置条件断言:代码执行之前必须具备的特性
后置条件断言:代码执行之后必须具备的特性
前后不变断言:代码执行前后不能变化的特性
4.断言使用方式
断言可以有两种形式
1.assert Expression1
2.assert Expression1:Expression2
5.分析堆栈轨迹元素:
堆栈轨迹是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置
可以使用Throwable类的printStackTrace方法访问堆栈轨迹的文本描述信息
Throwable t = new Throwable();
StringWriter out = new StringWriter();
t.printStackTrace(new PrintWriter(out));
String description = out.toString();
也可以使用getStackTrace方法,它会得到StackTraceElement对象的一个数组
StackTraceElement类含有能够获得文件名和当前执行代码行号的方法,同时,还含有能够获得类名和方法名的方法
静态的Thread.getAllStackTrace方法,它可以产生所有线程的堆栈轨迹,例如:
Map<Thread,StackTraceElement[]> map = Thread.getAllStackTrace();
for(Thread t : map.keySet()){
StackTraceElement[] f = map.get(t);
}
6.java.lang.Throwable 1.0:
Throwable(Throwable cause) 1.4
Throwable(String message,Throwable cause) 1.4
用给定的原因构造一个Throwable对象
Throwable initCause(Throwable cause) 1.4
将这个对象设置为原因,如果这个对象已经被设置为原因,则抛出一个异常,返回this引用
Throwable getCause() 1.4
获得设置为这个对象的原因的异常对象,如果没有,返回null
StackTraceElement[] getStackTrace() 1.4
获得构造这个对象时调用堆栈的跟踪
void addSuppressed(Throwable t) 7
为这个异常增加一个抑制异常
Throwable[] getSuppressed() 7
得到这个异常的所有“抑制”异常
7.java.lang.Exception 1.0:
Exception(Throwable cause) 1.4
Exception(String message,Throwable cause)
用给定的原因构造一个异常对象
8.java.lang.RuntimeException 1.0:
RuntimeException(Throwable cause) 1.4
RuntimeException(String message,Throwable cause) 1.4
用给定的原因构造一个RuntimeException对象
9.java.lang.StackTraceElement 1.4:
String getFileName()
返回这个元素运行时对应的源文件名。
int getLineNumber()
返回这个元素运行时对应的源文件行数
String getClassName()
返回这个元素运行时对应的类完全限定名
String getMethodName()
返回这个元素运行时对应的方法名
boolean isNativeMethod()
如果这个元素运行时在一个本地方法中,则返回true
String toString()
如果存在的话,返回一个包含类名、方法名、文件名和行数的格式化字符串
另:. java随机函数用法Random - leihupqrst - 博客园 file:///G:/java%E9%9A%8F%E6%9C%BA%E5%87%BD%E6%95%B0%E7%94%A8%E6%B3%95Random%20-%20leihupqrst%20-%20%E5%8D%9A%E5%AE%A2%E5%9B%AD.html
第二部分:实验部分
1、实验目的与要求
(1) 掌握java异常处理技术;
(2) 了解断言的用法;
(3) 了解日志的用途;
(4) 掌握程序基础调试技巧;
2、实验内容和步骤
实验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)
(2)
//异常示例2
import java.io.*; public class ExceptionDemo2 {
public static void main(String args[]) throws Exception
{
FileInputStream fis=new FileInputStream("text.txt");//JVM自动生成异常对象
int b;
while((b=fis.read())!=-1)
{
System.out.print(b);
}
fis.close();
}
}
实验2: 导入以下示例程序,测试程序并进行代码注释。
测试程序1:
l 在elipse IDE中编辑、编译、调试运行教材281页7-1,结合程序运行结果理解程序;
l 在程序中相关代码处添加新知识的注释;
l 掌握Throwable类的堆栈跟踪方法;
源代码:
package thesecond; import java.util.Scanner; /**
* 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();//在lang包中,不必写出;
StackTraceElement[] frames = t.getStackTrace();//调用getStackTrace方法,得到StackTraceElement对象的一个数组; for (StackTraceElement f : frames)
System.out.println(f);
//递归算法;
//每次return都是return栈顶那个计算得到的值,然后出栈,再把return得值作为已知条件来计算下个表达式
int r;
if (n <= 1) r = 1;
else r = n * factorial(n - 1);//n!=n*(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);
}
}
截图:
StackTrace就是当程序运行时一系列的函数调用的轨迹。
测试程序2
l Java语言的异常处理有积极处理方法和消极处理两种方式;
l 下列两个简答程序范例给出了两种异常处理的代码格式。在elipse IDE中编辑、调试运行源程序ExceptionalTest.java,将程序中的text文件更换为身份证号.txt,要求将文件内容读入内容,并在控制台显示;
l 掌握两种异常处理技术的特点。
//积极处理方式 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"); } } |
package thesecond;
//积极处理方式
import java.io.*;
import java.io.BufferedReader;
import java.io.FileReader; class ExceptionTest {
public static void main (String args[])
{
try{
File fis=new File("身份证号.txt");// 创建File类对象fis,传递一个本地文件的绝对路径 FileReader f = new FileReader(fis);
BufferedReader b= new BufferedReader(f);
try {
String s, s2 = new String();
while ((s = b.readLine()) != null) {
s2 += s + "\n ";
}
b.close();
System.out.println(s2);
}
catch (IOException e) { e.printStackTrace();
}
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}
package thesecond;
import java.io.*;
import java.io.BufferedReader;
import java.io.FileReader; //消极处理方式 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 在以上程序适当位置加入异常捕获代码。
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; public class Search{ private static ArrayList<Person> Personlist1;
public static void main(String[] args) { Personlist1 = new ArrayList<>(); Scanner scanner = new Scanner(System.in);
File file = new File("E:\\面向对象程序设计Java\\实验\\实验六\\身份证号.txt"); try {
FileInputStream F = new FileInputStream(file);
BufferedReader in = new BufferedReader(new InputStreamReader(F));
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);
Personlist1.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:输入你的年龄,查询年龄与你最近人的信息;");
System.out.println("5:退出");
System.out.println("******************************************");
int type = scanner.nextInt();
switch (type) {
case 1:
Collections.sort(Personlist1);
System.out.println(Personlist1.toString());
break;
case 2: int max=0,min=100;int j,k1 = 0,k2=0;
for(int i=1;i<Personlist1.size();i++)
{
j=Personlist1.get(i).getage();
if(j>max)
{
max=j;
k1=i;
}
if(j<min)
{
min=j;
k2=i;
} }
System.out.println("年龄最大:"+Personlist1.get(k1));
System.out.println("年龄最小:"+Personlist1.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 <Personlist1.size(); i++)
{
if(Personlist1.get(i).getbirthplace().substring(1,4).equals(place))
{
System.out.println("你的同乡:"+Personlist1.get(i));
}
} break;
case 4:
System.out.println("年龄:");
int yourage = scanner.nextInt();
int close=ageclose(yourage);
int d_value=yourage-Personlist1.get(close).getage();
System.out.println(""+Personlist1.get(close)); break;
case 5:
isTrue = false;
System.out.println("再见!");
break;
default:
System.out.println("输入有误");
}
}
}
public static int ageclose(int age) {
int m=0;
int max=53;
int d_value=0;
int k=0;
for (int i = 0; i < Personlist1.size(); i++)
{
d_value=Personlist1.get(i).getage()-age;
if(d_value<0) d_value=-d_value;
if (d_value<max)
{
max=d_value;
k=i;
} } return k; } } //jiekouwenjiaan 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"; } }
注:以下实验课后完成
练习2:
l 编写一个计算器类,可以完成加、减、乘、除的操作;
l 利用计算机类,设计一个小学生100以内数的四则运算练习程序,由计算机随机产生10道加减乘除练习题,学生输入答案,由程序检查答案是否正确,每道题正确计10分,错误不计分,10道题测试结束后给出测试总分;
l 将程序中测试练习题及学生答题结果输出到文件,文件名为test.txt;
import java.util.*;
import java.util.Scanner; public class Calculator { public static void main(String[] args) {
// 用户的答案要从键盘输入,因此需要一个键盘输入流
Scanner in = new Scanner(System.in);
// 定义一个变量用来统计得分
int sum = 0;
// 通过循环生成10道题
for (int i = 0; i < 10; i++) { // 随机生成两个10以内的随机数作为被除数和除数
int a = (int) Math.round(Math.random() * 10);
int b = (int) Math.round(Math.random() * 10);
int c = (int) Math.round(Math.random() * 4); int s; switch(c) { case 1:
s=a+b;
System.out.println(a + "+" + b + "=");
break;
case 2:
s=s=a-b;
System.out.println(a + "-" + b + "=");
break;
case 3:
s=a*b;
System.out.println(a + "*" + b + "=");
break;
case 4: s=a/b;
System.out.println(a + "/" + b + "="); break; } int s1 = in.nextInt(); if (s1==s) {
sum += 10;
System.out.println("恭喜答案正确");
}
else { System.out.println("抱歉,答案错误");
}
}
//输出用户的成绩
System.out.println("你的得分为"+sum);
} }
l 在以上程序适当位置加入异常捕获代码。
实验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); } } |
l 在elipse下调试程序AssertDemo,结合程序运行结果理解程序;
//断言程序示例
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);
}
}
l 注释语句test1(-5);后重新运行程序,结合程序运行结果理解程序;
注释后运行:
l 掌握断言的使用特点及用法。
实验程序2:
l 用JDK命令调试运行教材298页-300页程序7-2,结合程序运行结果理解程序;
l 并掌握Java日志系统的用途及用法。
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的常用调试技术。
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();
}
}
LoggingImageViewer
第三部分:总结
这周学习java异常处理技术,了解断言的用法,了解日志的用途; 以及学习程序基础调试技巧。对程序编译以及运行时可能出现的异常问题有了初步认识,以及对出现的异常相对相应需要的处理技术。