天天看点

黑马程序员 五、异常处理和常用类)

<a target="_blank" href="http://www.javahelp.com.cn/">java帮帮-it资源分享网</a>

 五、黑马程序员—异常处理和常用类

第五篇

1、异常

异常:就是不正常,是指程序在运行时出现的不正常情况。其实就是程序中出现的问题。

这个问题按照面向对象思想进行描述,并封装成了对象。因为问题的产生有产生的原因、有

问题的名称、有问题的描述等多个属性信息存在。当出现多属性信息最方便的方式就是将这

些信息进行封装。异常就是 java 按照面向对象的思想将问题进行对象封装。这样就方便于

操作问题以及处理问题。

出现的问题有很多种,比如角标越界,空指针等都是。就对这些问题进行分类。而且这

些问题都有共性内容比如:每一个问题都有名称,同时还有问题描述的信息,问题出现的位

置,所以可以不断的向上抽取。形成了异常体系。

异常的体系 throwable

error

通常指 jvm 出现重大问题如:运行的类不存在或者内存溢出等。

不需要编写针对代码对其处理,程序无法处理。

exception

在运行时运行出现的一些情况,可以通过 try,catch,finally 处理

异常处理两种方式:

1、捕获异常:try catch 直接处理可能出现的异常!

2、声明异常:throws 声明告诉调用者可能的异常,暴露问题,调用者自己

处理!

我的总结:

exception 和 error 的子类名大都是以父类名作为后缀。

java 异常其实是对不正常情况的一种描述,并将其封装成对象;

java 在 设计异常体系时,将容易出现的异常情况都封装成了对象。

2、异常处理格式

异常处理的 5 个关键字

try ,catch,

finally

throw, throws

捕获异常:先捕获小异常再捕获大异常。

程序是调出来的,不是写出来的;多测试是程序员的必修课。

异常处理后,程序不会因为出现异常而退出!

异常处理格式

try{

//可能出异常的代码

} catch(异常类 对象){

//处理该异常类型的语句

}

[finally] {

//一定会执行的代码

//catch 块使用 system.exit(1);除外

备注:当 try 语句块出现异常,程序会自动跳到 catch 语句块去找匹配的异常类型,并执行

异常处理语句,finally 语句块是异常的统一出口。

3、多异常处理

声明异常时尽可能声明具体异常类型,方便更好的处理;

方法声明几个异常就对应有几个 catch 块;

若多个 catch 块中的异常出现继承关系,父类异常 catch 块放在最后;

在 catch 语句块使用 exception 类作为异常类型时:

所有子类实例都可以使用父类接收(向上转型),即所有的异常对象都可以使用 exception 接

收;

注:在 java 处理多异常时捕获小范围的异常必须放在大范围异常之前。

java7 - 同时捕获多个异常类型

java7 之前:

try {

int a = integer.parseint("1");

int b = integer.parseint("0");

int c = a / b;

system.out.println(c);

} catch (numberformatexception e)

{

e.printstacktrace();

} catch(arithmeticexception e)

java7:将多个异常写到了同一个 catch 代码块

integer a = integer.parseint("1");

integer b = integer.parseint("0");

integer c = a / b;

} catch (numberformatexception

| arithmeticexception e ) {

4、异常的分类

异常分类:

编译时被检查异常; ---&gt; checked 异常

在程序中必须使用 try...catch 处理;

编译时不被检测的异常; ---&gt; runtime 异常

可以不使用 try...catch 处理,但一旦出现异常就将由 jvm 处理。

异常的分类之 runtime 异常

runtimeexception(运行时异常)是指因设计或实现方式不当而导致的问题.

说白了,就是程序员造成的,程序员小心谨慎是完全可以避免的异常.比如,事先判断对象是否

为 null 就 可 以 避 免 nullpointerexception 异 常 , 事 先 检 查 除 数 不 为 0 就 可 以 避 免

arithmeticexception 异常;

特点:

这种异常java编译器不会检查它,也就说程序中出现这类异常的时候,即使不处理也没有

问题,但是一旦出现异常,程序将异常终止,若采用异常处理,则会被相应的程序执行处理.

异常的分类之 checked 异常

除了 runtimeexception 以及子类,其他的 exception 及其子类都是受检查异常,我们也可

以称为非 runtimeexception 异常.

java 编译器会检查它,也就说程序中一旦出现这类异常,要么是没有 try-catch 语句捕获,

或 throws 语句没有声明抛出它,编译就不会通过,也就说这种异常,程序要求必须处理.

5、声明异常(throws)

在可能出现异常的方法上声明抛出可能出现异常的类型:

声明的时候尽可能声明具体的异常,方便更好的处理.

当前方法不知道如何处理这种异常,可将该异常交给上一级调用者来处理(非

runtimeexception 类型的异常)。

方法一旦使用 throws 声明抛出方法内可能出现的异常类型, 该方法就可以不再过问该

异常了;

一个方法调用另一个使用 throws 声明抛出的方法,自己要么 try...catch , 要么也 throws;

格式:

public 返回值类型 方法名(参数列表...)

throws 异常类 a,异常类 b... {

6、throw

自行抛出一个异常对象,抛出异常类的对象;

若 throw 抛出的是 runtime 异常:

程序可以显示使用 try...catch 来捕获并处理,也可以不管,直接交给方法调用者处理;

若 throw 抛出 checked 异常:

要么放在 try 里自己处理,要么放在一个 throws 声明的方法里面,交给调用者处理。

eg:

public static void main(string[] args) {

fn1(1);

} catch (exception e) { e.printstacktrace(); }

fn2(2);

public static void fn1(int a) throws exception{

if(a &gt;0) { throw new exception("fn1 -- a 值不合法"); }

public static void fn2(int a) {

if(a &gt;0) { throw new runtimeexception("a 值不合法"); }

throws &amp; throw

throws 用于在方法上声明该方法不需要处理的异常类型。

throw 用于抛出具体异常类的对象。

throws 与 throw 的区别:

thorws 用在方法上,后面跟异常类名,可以是多个异常类。

throw 用在方法内,后面跟异常对象,只能是一个。

7、finally

异常的统一出口:

不管 try 块程序是否异常,也不管哪个 catch 执行,finally 块总会执行。

try 语句块或会执行的 catch 语句块使用了 jvm 系统退出语句例外;//system.exit(1);

try 块必须和 catch 块或和 finally 同在,不能单独存在,二者必须出现一个。

不要在 finally 中使用 return 或 throw 语句,否则将会导致 try、catch 中的 return 或 throw 失

效。

我的总结:finally 代码块只在一种情况下不执行:system.exit(0);

package reviewdemo;

public class demo19 {

system.out.println(17/0);

}catch(exception e){

//e.printstacktrace();

system.out.println("程序错误,请修正!");

}finally{

system.out.println("这是finally代码块!");

输出:

程序错误,请修正!

这是finally代码块!

8、throw 和 catch 同时使用

当异常出现在当前方法中,程序只对异常进行部分处理,还有一些处理需要在方法的调用

者中才能处理完成,此时还应该再次抛出异常,这样就可以让方法的调用者也能捕获到异常;

public static void buy(string price) throws exception {

if(price != null)

double.parsedouble(price);

} catch (exception e) {

throw new exception("价格不能只能是数字组成");

buy(null);

system.out.println(e.getmessage());

9、常用类

string

string 表示字符串,所谓字符串,就是一连串的字符;

string 是不可变类,一旦 string 对象被创建,包含在对象中的字符序列(内容)是不可变的,

直到对象被销毁;

常量池:jvm 中一块独立的区域存放字符串常量和基本类型常量(public static final)。

string 使用 private final char value[]来实现字符串的存储,也就是说 string 对象创建之后,

就不能再修改此对象中存储的字符串内容,就是因为如此,才说 string 类型是不可变的.

string 对象比较:

单独使用""引号创建的字符串都是常量,编译期就已经确定存储到常量池中;

使用 new string("")创建的对象会存储到堆内存中,是运行期新创建的;

使用只包含常量的字符串连接符如"aa" + "bb"创建的也是常量,编译期就能确定,已经确

定存储到常量池中;

使用包含变量的字符串连接符如"aa" + s1 创建的对象是运行期才创建的,存储在堆中;

package string;

public class stringdemo {

/*

* "" 其实表示的是 string 的匿名对象

*/

string s = "";

/**

* string() 初始化一个新创建的 string 对象,使其表示一个空字符序列。

* "",不是表示 null

* string(string original)

* string s = new string("asd");// s 的值就是 asd

s = new string();//""

string s1 = new string("11");

string s2 = new string("11");

system.out.println(s1 == s2);//false

string s3 = "22";

string s4 = "22";

system.out.println(s3 == s4);//true

system.out.println(s3 == s2);//false

string s5 = "2" + "2";//这句话其实在编译器编译后的 class 文件中 已经变成 "22"

//s5 创建了几个对象?//回答:最多一个,如果常量池里面没有就是创建一个,如果

常量池里本来就有就是创建零个!下面的 str 一样的道理。

string str = "a" +"b"+ "c" +"d" +"e";//string str = "abcde";

system.out.println(s3 == s5);//true

* string 特点: 不可变的, 一个 string 对象的内容不能变,一旦内容变量该对象

就变成一个新的 string 对象了

* string str = "aaa";

* str = str+"12";

string str1 = "abcde";

system.out.println(str == str1);//true

string str2 = "abc" + "de";

system.out.println(str == str2);//true

string ss = "ab";

string str3 = ss + "cde";//这里的 str3 在运行期才能确定内容值

system.out.println(str3 == str2);//false

string str4 = getstr() +"cde";//在运行期才能确定 str4 的值

system.out.println(str == str4);//false

system.out.println(str3 == str4);//false

* string s = "cd"; //一个 string 对象

s = s + "itcast"; //itcast 也是 string 对象, 最后的 s 的值 cditcast,也是一个

string 对象

system.out.print(s);

* */

public static string getstr(){

return "ab";

eg:

public class demo20 {

//s1,s2只新建了一个对象

string s1 = "你好";

string s2 = "你好";

//s3,s4新建了两个对象

string s3 = "你好";

string s4 = "你好";

10、string 方法

string():初始化一个新的 string 对象,使其表示一个空字符序列,并不是返回空(不等于

null)。

string(stringbuffer buffer):根据 stringbuffer 对象来创建 string 对象;

string(stringbuilder builder):同上

char charat(int index):取字符串中指定位置的字符,index 从 0 开始计算。

string concat(string str):连接字符串,等同于 “+”;

boolean contentequals(stringbuffer buffer):若二者包含的字符序列相同时就返回 true;

boolean equals(object obj):将该字符串与指定对象比较,若二者包含的字符序列相等返回

true;

boolean equalsignorecase(string anotherstring) 将此 string 与另一个 string 比较,不考虑大

小写;

byte[] getbytes():将该字符串转换成 byte 数组;

int indexof(string str):找出 str 字符串在该字符串中第一次出现的位置;

int indexof(string str, int fromindex) 返回指定子字符串在此字符串中第一次出现处的索引,

从指定的索引开始;

int lastindexof(string str) 返回指定子字符串在此字符串中最后一次出现处的索引;

int length():返回当前字符串长度;

string replace(char oldchar, char newchar) :返回一个新的字符串,它是通过用 newchar 替换

此字符串中出现的所有 oldchar 得到的。

string replaceall(string regex, string replacement) 使用给定的 字符串 replacement 替换此字

符串所有的 regex 字符串;

boolean startswith(string prefix) 测试此字符串是否以指定的前缀开始.

string[] split(string regex): 把字符串按指定的字符串分隔开。

string substring(int beginindex) 返回一个新的字符串,从 beginindex 开始截取,它是此字符

串的一个子字符串;

string substring(int beginindex, int endindex) 返回一个新字符串,它是此字符串的一个子字符

串;[begin,end)

char[] tochararray() 将此字符串转换为一个新的字符数组。

string tolowercase() 将此 string 中的所有字符都转换为小写;

string touppercase()转成大写;

static string valueof(基本类型 obj):把基本类型值转成字符串;

string trim() :忽略字符串前导空白和尾部空白。

string 小练习

判断字符串是否由数字组成:

string s1 = "123456789";

string s2 = "12345 6789";

system.out.print(isnum(s1));

system.out.print(isnum(s2));

public static boolean isnum(string s){

char []ch = s.tochararray();

for (char c : ch) {

if(!(c &gt; '0' &amp;&amp; c &lt;= '9')){

return false;

return true;

true

false

判断字符串是否为空:

分析:

字符串的空有两种情况:1、null;2、"";

public class demo21 {

string s1 = "";

system.out.println(isimpty(s1));

public static string isimpty(string s){

if(s != null &amp; !"".equals(s)){

return "不为空";

return "为空!";

11、stringbuffer 与 stringbuilder

string 是不可变类,一旦 string 对象被创建,包含在对象中的字符序列是不可变的,直到对

象被销毁;

stringbuffer 与 stringbuilder 对象则是可变的!

举例说明这两个的好处:(不用每次新建对象,效率高!)

public class demo22 {

long begintime = system.currenttimemillis();

for(int i = 1;i &lt;= 100000;i++){

s += i;

long endtime = system.currenttimemillis();

long time = endtime - begintime;

system.out.println("运行时间为:"+time);

stringbuffer s1 = new stringbuffer();

s = "";

begintime = system.currenttimemillis();

s = ""+i;

s1 = new stringbuffer(s);

endtime = system.currenttimemillis();

time = endtime - begintime;

运行时间为:82922

运行时间为:15

可以看得出:stringbuffer 这两个效率相当高!

stringbuffer: 是线程安全的;

stringbuilder: 是线程不安全的,性能高点,推荐使 stringbuilder;(jdk1.5 出现)

stringbuffer 的字符序列是可变的(通过 append 等方法操作)

stringbuffer 和 string 之间的转换;

string tostring() 返回此序列中数据的字符串表示形式。

stringbuffer(string str):以指定的字符串创建 stringbuffer 对象。

stringbuffer 方法

public stringbuilder()构造一个不带任何字符的 stringbuilder 对象。

stringbuffer(string str) :构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。

stringbuffer append(object o) :将指定的任意类型对象追加到此 stringbuffer 对象。

stringbuffer insert(int offset, object o) :将任意类型参数的字符串表示形式插入此序列中。

stringbuffer delete(int start, int end) :移除此序列的子字符串中的字符。

stringbuffer deletecharat(int index): 移除此序列指定位置的 char。

* 用stringbuilder 或stringbuffer:

把字符串“abcde”;

转变成字符串“a,b,c,d”

public class demo23 {

//第一种方法:往里面插入;

stringbuilder sb = new stringbuilder("abcde");

sb.deletecharat(sb.length()-1);

system.out.println(sb);

for (int i = 0; i &lt; sb.length(); i+=2) {

sb.insert(i, ",");

sb.deletecharat(0);

//第二种方法:往里面追加,要追加必须遍历,必须换为数组!

sb = new stringbuilder("abcde");

char []cs = sb.tostring().tochararray();

stringbuilder sb1 = new stringbuilder();

for (char c : cs) {

sb1.append(c).append(",");

sb1.deletecharat(sb1.length()-1);

system.out.println(sb1);

编写一个程序,这个程序把一个整数数组中的每个元素用逗号连接成一个字符串,例如,

根据内容为{1,2,3}的数组形成内容为"1,2,3"的字符串。

* 编写一个程序,

* 这个程序把一个整数数组中的每个元素用逗号连接成一个字符串,

* 例如,根据内容为{1,2,3}的数组形成内容为"1,2,3"的字符串。

public class demo24 {

int []i = {1,2,3,4,5};

stringbuilder sb = new stringbuilder();

for (int j : i) {

sb.append(j).append(",");

12、math 和 random 和 uuid

math 类

public final class math extends object

以下 x 表示 double,float,int, long

abs(x x):求绝对值

max(x x1,x x2):求最大值

min(x x1,x x2):求最小值

public static double random():返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。

和使用 new java.util.random 一样

math.pi;

random 类

负责生成伪随机数;

random() 创建一个新的随机数生成器。

int nextint() 返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。

int nextint(int n) 返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)

和指定值 n(不包括)之间均匀分布的 int 值。

public class demo26 {

system.out.println(math.e);//2.718281828459045

int a = 12;

int b = 25;

system.out.println(math.max(a,b));//这里可以使用静态导入(导入

math类中的方法,这样的话前面就不用写上math.)

system.out.println(math.min(a,b));

import java.util.uuid;

public class demo27 {

uuid u = uuid.randomuuid();

string s = u.tostring();

system.out.println(s);//此时是随机生成的,肯定每次都不一样,全网唯

一!

u = new uuid(1222222222, 12);//根据构造方法来

s = u.tostring();

system.out.println(s);//这一个的uuid是固定的。

我的总结:uuid(用来标示文件名等(免得文件上传因为名字可能一样而被覆盖),可以

保证全网唯一!)

uuid 类:用唯一标识符 (uuid) 的类。 uuid 表示一个 128 位的值。

uuid(universally unique identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证

对在同一时空中的所有机器都是唯一的。按照开放软件基金会(osf)制定的标准计算,用到

了以太网卡地址、纳秒级时间、芯片 id 码和许多可能的数字。由以下几部分的组合:当前

日期和时间(uuid 的第一个部分与时间有关,如果你在生成一个 uuid 之后,过几秒又生

成一个 uuid,则第一个部分不同,其余相同),时钟序列,全局唯一的 ieee 机器识别号(如

果有网卡,从网卡获得,没有网卡以其他方式获得),uuid 的唯一缺陷在于生成的结果串

会比较长。

标准的 uuid 格式为:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx (8-4-4-4-12),其中每个 x 是 0-9

或 a-f 范围内的一个十六进制的数字;

uuid uuid = uuid.randomuuid();

string uid = uuid.tostring();

13、date 和 calendar

处理日期,时间;

大部分的方法已过时,不推荐使用,但是你使用过时的方法也不会报错。

date() 分配 date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。

date(long date) 分配 date 对象并初始化此对象,以表示自从标准基准时间(称为“历元

(epoch)”,即 1970 年 1 月 1 日 00:00:00 gmt)以来的指定毫秒数。

simpledateformat

java.text.simpledateformat

simpledateformat 是一个与语言环境有关的方式来格式化和解析日期的具体类。它允许进

行格式化(日期 -&gt; 文本)、解析(文本 -&gt; 日期)和规范化。

simpledateformat(string pattern) 用给定的模式和默认语言环境的日期格式符号构造

simpledateformat。

public final string format(date date)将一个 date 格式化为日期/时间字符串。

public date parse(string source) throws parseexception:把字符串 source 表示的时间按 source

的格式转成 date 对象。

练习:string 与 date 的相互转化

按某种时间格式来输出指定的 string 类型时间

date2string

format

把某种时间格式的 string 时间转成 date 类型时间

string2date

parse

import java.text.simpledateformat;

import java.util.date;

public class demo28 {

public static void main(string[] args) throws exception {

date d = new date();

system.out.println(d);//获取当前时间

//格式化

simpledateformat sd = new simpledateformat("yyyy-m-d

hh:mm:ss e");

string s = sd.format(d);//这个方法继承于simpledateformat的父类

dateformat类!

system.out.println(s);

//反格式化

d = sd.parse(s);

system.out.println(d);

calendar

推荐使用处理日期和时间的类 calendar;

是抽象类,不能实例化,通过

static calendar getinstance() 获得一个 calendar 对象。

int get(int field):返回指定日历字段值

静态常量:

year 表示年的字段数字。

month 表示月份字段数字,月份范围是[0,11]。

date 表示一个月中的某天。

day_of_month 表示一个月中的某天。

day_of_week 表示一个星期中的某天。

hour_of_day / hour 表示第几小时

minute 表示第几分钟

second 表示第几秒

date gettime() 返回一个表示此 calendar 时间值的 date 对象。

void set(int year, int month, int date, int hour, int minute, int second) 设置字段 year、

month、day_of_month、hour、minute 和 second 的值。

abstract void add(int field, int amount) 根据日历的规则,为给定的日历字段添加或减去指定的

时间量。

若 amount 为负数,则减去一天,

若 amount 为正数 ,则加上一天

例子

import java.util.calendar;

public class demo29 {

calendar c = calendar.getinstance();

date d = c.gettime();

* void set(int year, int month, int date, int hour, int minute,

int second)

* 设置字段 year、month、day_of_month、hour、minute 和 second 的

值。

c.set(2015, 07, 15, 12, 24, 55);

d = c.gettime();

c.add(calendar.day_of_month, 3);

我的总结:注意常查看 api!

eg:“查询距今最近三天内的记录”,这里的‘三天内’是什么时间段?

将当前日期时间转换为 只获取当天的 00:00:00

如: 2011-08-08 12:12:12 转化为 2011-08-08 00:00:00、

public class demo30 {

simpledateformat sd = new simpledateformat("yyyy-m-d hh:mm:ss

e");

string s = sd.format(d);

c.set(2015, 8, 23, 13, 24, 15);

system.out.println(sd.format(d));

c.add(calendar.day_of_month, -3);

thu jul 04 08:56:51 cst 2013

2013-7-4 08:56:51 星期四

2015-9-23 13:24:15 星期三

2015-9-20 13:24:15 星期日

14、system

system 类包含一些与系统相关的类字段和方法。它不能被实例化,类中所有属性和方法都

是 static,可直接被 system 调用。

常用方法:

static void exit(int status) 终止虚拟机的运行.对于发生了异常情况而想终止虚拟机的运行,传

递一个非 0 数值,对于正常情况下退出系统传递 0 值;

该方法实际调用的是 runtime.getruntime().exit(int status);

static void arraycopy(object src, int srcpos, object dest, int destpos, int length) 数组拷贝

static long currenttimemillis() 返回以毫秒为单位的当前时间。

string getenv(string name) 获得指定的环境变量;

static void gc() 运行垃圾回收器。

实际上调用了 runtime 中的 gc()方法;

runtime.getruntime().exec("notepad ");

static properties getproperties() 取得当前的系统属性。

static string getproperty(string key) 取得指定键指示的系统属性。

static string getproperty(string key, string def) 获取用指定键描述的系统属性,def 表示默认

信息。

eg:package reviewdemo627;

import java.util.properties;

public class demo32 {

properties p = system.getproperties();

system.out.println(p);

system.out.println(system.getenv());