设备做外贸哪个网站好,抖音代运营一般收费,南京前十名传媒广告公司,个人如何缴纳社保11 异常、断言、日志和调试
异常处理#xff08;exception handing#xff09;
使用断言来启动检测
Java日志框架
调试技巧
11.1 处理错误
如果一个方法不能够采用正常的途径完成任务#xff0c;就通过另外一个路径退出方法。
在这种情况下#xff0c;方法不返回任何…11 异常、断言、日志和调试
异常处理exception handing
使用断言来启动检测
Java日志框架
调试技巧
11.1 处理错误
如果一个方法不能够采用正常的途径完成任务就通过另外一个路径退出方法。
在这种情况下方法不返回任何值而是抛出一个封装了错误信息的对象。此外调用这个方法的代码也将无法继续执行。
异常处理机制开始搜索能够处理这种异常情况的异常处理器exception handler。
异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种情况的错误处理器。 异常对象是派生于Throwable类的一个实例。
可以创建自己的异常类。 异常的分类 Throwable Exception RuntimeException ArrayIndexOutOfBoundsException NullPointerException IOException Error Error类层次描述的是Java运行时系统的内部错误和资源耗尽。
应用程序不应抛出此类错误。
除了通告给用户并尽力使程序安全地中止之外再也无能为力。
此种情况很少出现。 派生于Error类或RuntimeException类的所有异常称为未检查unchecked异常
所有其他的异常称为已检查checked异常。
编译器将检查是否为所有已检查异常提供了异常处理器。 声明已检查异常
public FileInputStream(String name) throws FileNotFoundException 一个方法要么返回其返回值要么抛出一个异常。
一个方法必须声明所有可能抛出的已检查异常而未检查异常要么不可控Error要么应避免RuntimeException。
如果子类中覆盖了超类的一个方法子类方法中声明的已检查异常不能比超类方法中声明的异常更通用。 如何抛出异常
1、找到一个合适的异常类
2、创建其类对象
3、将对象抛出。
如throw new EOFException();
throw new EOFException(String); 一旦方法抛出异常这个方法就不能返回到调用者。
C中可以抛出任何类型的值Java中只能抛出Throwable子类的对象。 创建异常类
定义一个派生于Exception的类或者派生于Exception子类的类。
包含两个构造器默认构造器带有详细描述信息的构造器。 class FileFormatException extends IOException
{public FileFormatException(){}public FileFormatException(String message){super(massage);}
}11.2 捕获异常
如果某个异常发生的时候没有在任何地方进行捕获那程序就会终止执行并在控制台上打印出异常信息其中包括异常的类型和堆栈信息。
捕获异常 try
{code that might throw exception
}
catch(FileNotFoundException | UnknownHostException e) //捕获多个异常时e隐含为final变量。
{emergency action for missing files and unknown hosts
}
catch(IOException e)
{emergency action for all other I/O problems
}如果try语句块中的任何代码抛出了一个在catch子句中说明的异常类则跳过try语句块的其余代码执行catch子句中的处理器代码
如果try语句块中抛出的异常没有在catch子句中说明则立即退出这个方法
如果try语句块没有抛出异常则跳过catch子句。 通常异常处理的最好选择是什么都不做而是将异常传递给调用者。
如果调用了一个抛出已检查异常的方法要么处理要么传递。
通常捕获那些知道如何处理的异常传递那些不知怎样处理的异常。 在catch子句中还可以抛出一个异常这样做目的是改变异常的类型。
如 try
{access the database
}
catch (SQLException e)
{Throwable se new ServletException(“database error”);se.initCause(e);throw se;
}
finally
{close resource;
}Throwable e se.getCause();//可以得到原始异常使用这种包装技术可以让用户抛出子系统中的高级异常而不会丢失原始异常的细节。
如果在一个方法中发生了一个已检查异常而方法不允许抛出它那么包装技术可以将这个已检查异常包装成一个运行时异常。 强烈建议使用try/catch、try/finally子句。
finally子句一定会被执行。 带资源的try语句 try(Resource res ...)
{work with res;
}
//try块退出时自动调用res.close()方法。
//此时try块抛出的异常被抛出close方法抛出的异常被抑制。带资源的try语句自身也可以有catch子句和一个finally子句。这些子句会在关闭资源后执行。
在实际中一个try语句中加入这么多内容可能不是一个好主意。 堆栈跟踪stack trace
是一个方法调用过程的列表包含了程序执行过程中方法调用的特定位置。 Throwable t new Throwable();
StackTraceElement[] frames t.getStackTrace();
for (StackTraceElement frame : frames)analyze frame;
//多线程堆栈跟踪
MapThread, StackTraceElement[] map Thread.getAllStackTraces();
for (Thread t : map.keySet())
{StachTraceElement[] frames map.get(t);analyze frames
}11.3 使用异常的技巧
1、异常处理不能代替简单的测试
2、不要过分细化异常
3、利用异常层次结构
4、不要压制异常对于不常发生的异常catch语句块的内容可以先空着待日后感觉需要处理时再填上。
5、不要羞于传递异常。 11.4 使用断言
断言机制允许在测试期间向代码中插入一些检查语句。
当代码发布时这些插入的检测语句将会被自动移走。 assert 条件;
assert 条件:表达式; 这两种形式都会对条件进行检测如果结果为false则抛出一个AssertionError异常。
在第二种形式中表达式将被传入AssertionError的构造器并转换成一个消息字符串。
表达式的唯一目的就是产生一个消息字符串。 assert x 0;
assert x 0 : x;
assert x 0 “x 0”; 默认情况下断言被禁用。
在运行时用-enableassertions 或 -ea 选项启用它。
java -enableassertions MyApp
在启用或禁用断言时不必重新编译程序。启用或禁用断言时类加载器class loader的功能。
当断言被禁用时类加载器将跳过断言代码因此不会降低程序运行的速度。
也可选用-disableassertions或-da禁用某个特定类或包的断言。 在Java中给出了三种处理系统错误的机制
异常
日志
断言。 断言是致命的不可恢复的错误。只用于开发和测试阶段。
断言是一种测试和调试阶段所使用的战术性工具
日志记录是一种在程序的整个生命都可以使用的策略性工具。 11.5 记录日志
优点
·可以取消全部日志记录或仅取消某个级别的日志而且打开和关闭这个操作也很容易
·可以很简单的禁止日志记录的输出因此这些日志代码留在程序中的开销很小
·日志记录可以在控制台中显示也可以在文件中存储
·可以对日志记录进行过滤只保留重要日志
·可以采用不同格式纯文本或XML
·可使用多个日志记录
·默认情况下日志系统的配置由配置文件控制如果需要的话应用程序可以替换这个配置。 基本日志
日志系统管理着一个名为Logger.global的默认日志记录器可通过info方法记录日志信息
Logger.getGlobal().info(“File-Open menu item selected”); //记录日志
Logger.getGlobal().setLevel(Level.OFF); //取消所有日志 高级日志
在一个应用程序中不要将所有的日志都记录到一个全局日志记录器中而是自定义日志记录器。
调用getLogger方法可以创建或检索记录器
private static final Logger myLogger Logger.getLogger(“com.mycompany.myapp”);
日志记录具有层次结构上下层之间将共享某些属性例如对com.mycompany日志记录器设置了日志级别它的子记录器也会继承这个级别。
SERVER WARNING INFO CONFIG FINE FINER FINEST
默认记录前三个级别。 级别设置
logger.setLevel(Level.FINE); //Level.ALL开启所有级别 Level.OFF关闭所有级别 记录方法
logger.waring(message);
logger.fine(message);
logger.log(level.FINE, message); 默认的日志配置记录了INFO或更高级别的所有记录。
应该使用CONFIG、FINE、FINEST级别来记录那些有助于诊断但对于程序员又没有太大意义的调试信息。 默认的日志记录将显示包含日志调用的类名和方法名如同堆栈所显示的那样。
但是如果虚拟机对执行过程进行了优化就得不到准确的调用信息。
此时可用logp方法获得调用类和方法的确切位置
void logp(Level l, String className, String methodName, String Message) 跟踪执行流的方法
void entering(String className, String methodName)
void entering(String className, String methodName, Object param)
void entering(String className, String methodName, Object[] params)
void exiting(String className, String methodName)
void exiting(String className, String methodName, Object result)
如 int read(String file, String pattern)
{logger.entering(“com.mycompany.mylib.Reader”,”read”,new Object[]{file, pattern};...logger.exiting(“com.mycompany.mylib.Reader”,”read”,count);return count;
}这些调用将产生FINER级别和以字符串ENTRY和RETURN开始的日志记录。 日志记录的常见用途是记录那些不可预料的异常。
两种方法
void throwing(String className, String methodName, Throwable t)
void log(Level l, String message, Throwable t)
典型用法 if(...)
{IOException exception new IOException(“...”);logger.throwing(“com.mucompany.mylib.Reader”,”read”,exception);throw exception;
}
//调用throwing可以记录一条FINER级别的记录和一条以THROW开始的信息。try
{...
}
catch(IOException)
{Logger.getLogger(“com.mycompany.myapp”).log(Level.WARNING, “Reading image”, e);
}修改日志管理器配置文件jre/lib/logging.properties
日志管理器在VM启动过程中被初始化在main之前执行。
.levelINFO //修改默认的日志记录级别
com.mycompany.myapp.levelFINE 指定自己的日志记录级别 本地化
本地化的应用程序包含资源包resource bundle中的本地特定信息。
资源包由各个地区的映射集合组成。如某个资源包可以将redingFile映射成英文的Reading file或者德文的Achtung! Datei wired eingelesen。
一个程序可以包含多个资源包一个用于菜单其他用于日志消息。
每个资源包都有一个名字如com.mycompany.logmessages。
要想将映射添加到一个资源包中需要为每个地区创建一个文件。
英文消息映射位于com/mycompany/logmessages_en.properties文件中
德文消息映射位于com/mycompany/logmessages_de.properties文件中。
可以将这些文件与应用程序的类文件放在一起以便ResourceBundle类自动对它们进行定位。
这些文件都是纯文本文件内容如下
readigFileAchtung! Datei wird eingelesen
renamingFileDatei wird umbenannt 在请求日志记录器时可以指定一个资源包
Logger logger Logger.getLogger(loggerName, “com.mycompany.logmessages”);
然后为日志消息指定资源包的关键字而不是实际的日志消息字符串
logger.info(“readingFile”); 通常需要在本地化的消息中增加一些参数因此消息应该包括占位符{0}、{1}等。
例如在日志消息中包含文件名需要使用下列方式包含占位符
readingFileReading file {0}
renamingFileChange name file {0} to {1} logger.log(Level.INFO, “readingFile”, fileName);
logger.log(Level.INFO, “renamingFile”, new Object[]{oldName, newName}; 处理器:
默认情况下日志记录器将记录发送到ConsoleHandler中并由它输出到System.err流中。
日志记录器还会将记录发送到父处理中最终处理器命名为””有一个ConsoleHandler。
处理器也有一个日志记录级别。 安装自己的处理器
Logger logger Logger.getLogger(“com.mycompany.myapp”);
logger.setLevel(Level.FINE);
logger.setUseParentHandlers(false);
Handler handler new ConsoleHandler();
handler.setLevel(Level.FINE);
logger.addHandler(handler); 其他处理器
FileHandler 将记录发送到用户主目录的javan.log文件中n是文件的唯一编号默认XML格式。
SocketHandler 将记录发到特定的主机和端口。 过滤器
默认情况下过滤器根据日志记录的级别进行过滤。
每个日志记录器和处理器都可以有一个可选的过滤器来完成附加的过滤。
另外可通过实现Filter接口的boolean isLoggable(LogRecord record)方法来自定义过滤器。
调用setFilter方法安装过滤器。
一个时刻最多只能有一个过滤器。 日志记录说明日志记录器最好与主应用程序包名相同