JAVA笔记【20130103】

一、异常

Java中所有异常对象都是由于Throwable类继承而来。但在Throwable类的下一层就立即分为Error和Exception两个类。

Error类层次结构描述了JAVA运行时系统的内部错误和资源耗尽错误。应用程序不该抛出这类型的错误对象。

Exception类层次结构又分为两支,一支派生于RuntimeException的异常,另一支是其它异常。

划分规则是由于程序错误导致的异常属于RuntimeException,曾经能够正常运行,现由于某些特定情况造成的不能运行不属于RuntimeException。

常见RuntimeException如数组越界,空指针以及错误的类型转换。常见非RuntimeException如IO操作异常。

JAVA中将所有派生于RuntimeException类或Error类的所有异常称为“未检查异常”,其它异常称为“已检查异常”。

一个方法不需要抛出从Error继承的异常,也不需要抛出从RuntimeException继承的异常未检查异常。一个方法可能抛出多个已检查异常,使用逗号分隔即可。

如果子类覆盖了超类的一个方法,那么子类抛出的已检查异常范围比超类的范围更小。

已存在异常抛出方法

FileNotFoundException e = new FileNotFoundException();
throw e;

定义自定义异常,自定义异常要么派生于Exception类,要么派生于Exception类的子类,一般提供两个构造方法。

class FileFormatException extends IOException
{
	public FileFormatException(){};
	public FileFormatException(String s)
	{
		super(s);
	}
}
抛出自定义的异常与抛出已存在的异常方法一样。


异常捕获:

捕获异常需要使用try/catch语句,也可以捕获多个异常。

try
{
	//.........
}
catch(ExceptionXXX e)
{
	//.........
}
catch(ExceptionYYY e)
{
	//.........
}

有些时候对于子系统类型,捕获到异常后需要抛出另外一个异常类型,

try
{
	//........
}
catch(SQLException e)
{
	throw new ServletException("database error: "+e.getMessage());
}

更好的处理办法是抛出子系统高级异常的同时保存原始异常。

try
{
	//........
}
catch(SQLException e)
{
	Throwable se = new ServletException("database error");
	se.setCause(e);
	throw se;
}

当捕获到异常的时候,可以使用Throwable e = se.getCause()方法获取原始异常。


finally子句:

对于有些方法中,在退出方法的时候需要释放资源,如果发生异常,则回收就会出现问题,因此提供了finally方法,

不论是否捕获异常,finally子句中的代码都会被执行。

使用finally的时候需要注意当finally子句中出现return语句的情况。

public static int f(int n)
{
	try
	{
		int r=n*n;
		return n;
	}
	finally
	{
		if(n==2) return 0;
	}
}

当n为2时,执行到try中的return语句时,需要先执行finally中的语句,即return 0,最终返回结果为0。


堆栈跟踪元素分析:

堆栈跟踪(stack trace)是一个方法调用过程的列表,它包含了程序执行中方法调用的特定位置。

JDK1.4以前的版本中可以通过调用Throwable类的printStackTrace方法访问堆栈跟踪的文本描述。

现在可以使用getStackTrace方法获得一个StackTraceElement对象的数组,其中含有获取文件名、当前执行代码行号、类名以及方法名的方法。可以在程序中分析这个对象。

Throwable t = new Throwable();
StackTraceElement[] ele = t.getStackTrace();
for(StackTraceElement e:ele)
{
	//........
	System.out.println(e.toString());
}

JDK5.0中,增加了静态的Thread.getAllStackTrace()方法,可以产生所有线程的堆栈跟踪。

Map<Thread,StackTraceElement[]> map = Thread.getAllStackTrace();
for(Thread t:map.keySet())
{
	StackTraceElement[] e = map.get(t);
	//......................
}

打印递归阶乘堆栈跟踪情况

import java.util.*;
public class StackTraceTest01
{
	public static int fact(int n)
	{
		System.out.println("fact("+n+");");
		Throwable t = new Throwable();
		/**/StackTraceElement[] e = t.getStackTrace();
		for(StackTraceElement s:e)
		{
			System.out.println(s);
		}
		//t.printStackTrace();
		int r;
		if(n<1)
			r=1;
		else
		{
			System.out.println("此时n:"+n);
			r=n*fact(n-1);
		}
		System.out.println("return:"+r);
		return r;
	}
	public static void main(String[] args)
	{
		Scanner in = new Scanner(System.in);
		System.out.println("Enter: n");
		int n=in.nextInt();
		fact(n);
	}
}

二、日志

全局日志

Logger log = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
log.info("xxxxxxxx");

会输出Info日志,包含了时间调用类名和方法名。

不必将所有的日志都记录到全局日志记录器中,可以定义自己的日志记录器

Logger myLog = Logger.getLogger("xxxxxxx");

通常有以下7个日志记录级别SEVER,WARNING,INFO,CONFIG,FINE,FINER和FINEST。默认情况下只记录前三个级别。

可以使用setLevel方法设定日志级别,也可以使用log方法指定级别。

可以通过编辑配置文件来修改日志系统的各种属性,默认情况下,配置文件存在于jre/lib/logging.properties中。

修改默认日志记录级别,需修改logging.properties中.level选项即可

.level=INFO

也可以通过添加以下内容来指定自己的日志记录级别

日志记录名.level=FINE

日志记录器并不将消息记录器发送到控制台,这是处理器的任务,因此在jre/lib/logging.properties中还需要修改处理器级别

java.util.logging.ConsoleHandler.level=FINE

当然,如果要使用其它配置文件,可以使用下面命令启动应用程序

java -Djava.util.logging.config.file=xxxx.properties 程序名


本地化:

本地化的应用程序包含资源包中的本地说明信息。一个程序可以含有多个资源包。

每个资源包都有一个名字(例如“com.mycompany.logmessages”)。要将映射添加到资源包中,需要为每个地区添加一个文件。

例如英文消息映射位于com/mycompany/logmessage_en.properties文件中。这些文件为纯文本文件其中存储的是映射。类似

readingfile=Reading file

在请求日志记录器时,可以指定一个资源包

Logger logger = Logger.getLogger(logName,"com.mycompany.logmessages");
logger.info("readingfile");

有时需要在本地化的消息中添加一些参数,因此使用消息占位符{0},{1}等

readingfile=Reading file {0}

然后通过下面方法向占位符传递具体值

logger.log(Level.Info,"readingfile",filename);

处理器:

默认情况下,日志记录器将记录发送到ConsoleHandler中,然后在发送到System.err。

要将日志发送到其它地方,就需要添加其它的处理器,JDK中提供了FileHandler和SocketHandler。具体配置见JDK的API文档。

要想编写复杂的流处理器,应该扩展Handler类,并自定义publish、flush和close方法。


过滤器:

过滤器是对日志中内容的进一步细分,可以通过实现Filter接口并实现isLoggable方法来自定义过滤器

boolean isLoggable(LogRecord record)

格式化器:

对于处理器ConsoleHandler和FileHandler都可以通过配置项指定输出的日志格式,当然也可以通过扩展Formatter类实现format方法来自定义输出的日志格式

String format(LogRecord record)
在format中有可能调用formatMessage方法。

最后通过调用setFormatter(Formatter f)方法将格式化器安装到处理器即可。


断言:

在编写代码的过程中,可能会做出一些假设,而断言就是对这种假设的捕获。

例如在做sqrt运算的时候,断言被操作数大于0。

JDK1.4中引入了关键字assert,其有两种使用形式。

assert 条件;

assert 条件:表达式;

两个都会对条件进行判断,如果结果为false,则会抛出一个AssertionError异常。在第二个中表达式会被传入AssertionError的构造器。

断言机制允许在测试期间向代码中插入一些检查语句,当代码发布时,这些插入的检测语句将会被自动地移走。

使用JDK1.4版本时,需要告诉编译器使用了assert关键字,编译时使用-source 1.4选项,JDK5.0之后默认支持断言。

默认情况下断言是被禁用的,运行时可以通过-enableassertions或者-ea选项来启用它。


调试

JDK5.0中增加了对应用程序进行监控和管理的支持,允许使用虚拟机中的代理装置跟踪内存消耗、线程使用、类加载等情况。JDK加载了一个称为jconsole的图形工具,可以用于显示虚拟机性能的统计结果。

JDK6.0之后无需再使用Dcom.sun.management.jmxremote选项也可以。

java -Dcom.sun.management.jmxremote xxxxxx

jconsole PID






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值