第四章:面向对象(下)
4.5异常
一、什么是异常
在Java语言中,引入了异常,以异常类的形式对这些非正常的情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理
运行结果:
package W;
public class A1 {
public static void main(String[] args) {
int result=divide(4,2);//调用divide()方法//把2改成0的话0不允许做除数就会出现异常
System.out.println(result);
}
//下面的方法实现了两种整数相除
public static int divide(int x,int y){
int result=x/y;
return result;
}
}
异常
package W;
public class A1 {
public static void main(String[] args) {
int result=divide(4,0);//调用divide()方法//把2改成0的话0不允许做除数就会出现异常
System.out.println(result);
}
//下面的方法实现了两种整数相除
public static int divide(int x,int y){
int result=x/y;
return result;
}
}
运行结果:
Throwable类的继承体系
Throwable有两个直接子类Error和Exception,其中Error代表程序中产生的错误,Exception代表程序中产生的异常
接下来就对这两个直接子类进行详细的讲解:
Error类称为错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠修改程序本身是不能恢复执行的。举一个生活中的例子,在盖校的过程中因偷工减料,导致大楼坍塌,这就相当于一个Error。使用iava俞令去运行一个不存在的类就会出现Error错误。
Exception类称为异常类,它表示程序本身可以处理的错误,在开发Java程序中进行的异常处理,都是针对Exception类及其子类。在Exception类的众多子类中有一个特殊的Runtimefxcention类,该类及其子类用于表示运行时异常,除了此类,Exception类下所有其他的子莞都用于表示编译时异常。本节主婴针对Emception类及其子类进行讲解。
Throwable类中的常用方法
二、try...catch和finally
Java中提供了一种对异常进行处理的方式一一异常捕获。异常捕获通常使用
try...catch语句
//语法:
try{
//程序代码块
}catca(ExceptionType(Exception类及其子类 ) e){
//对ExceptionType的处理
}
其中在try代码块中编写可能发生异常的Java语句,catch代码块中编写针对异常进行处理的代码。当tny代码块中的程序发生了异常,系统会将这个异常的信息封装成一个异常对象,并将这个对象传递给catch代码块。catch代码块需要一个参数指明它所能够接收的异常类型,这个参数的类型必须是Exception类或其子类。
package W;
public class A1 {
public static void main(String[] args) {
//下面的代码定义了一个try...catch...finally语句用于捕获异常
try {
int result=divide(4,2);//调用divide()方法
System.out.println(result);
}catch(Exception e) {//对捕获的异常进行处理
System.out.println("捕获的异常信息为:"+e.getMessage());
return;//结束整个方法
}finally {
System.out.println("进入finally代码块");
}
System.out.println("程序继续向下执行");
}
//下面的方法实现了两种整数相除
public static int divide(int x,int y){
int result=x/y;//定义变量result记录两个数相除的结果
return result;
}
}
运行结果:
把2改成0后出现异常打印了一个异常信息
package W;
public class A1 {
public static void main(String[] args) {
//下面的代码定义了一个try...catch...finally语句用于捕获异常
try {
int result=divide(4,0);//调用divide()方法
System.out.println(result);
}catch(Exception e) {//对捕获的异常进行处理
System.out.println("捕获的异常信息为:"+e.getMessage());
return;//结束整个方法
}finally {
System.out.println("进入finally代码块");
}
System.out.println("程序继续向下执行");
}
//下面的方法实现了两种整数相除
public static int divide(int x,int y){
int result=x/y;//定义变量result记录两个数相除的结果
return result;
}
}
运行结果:
三、thr ows关键字
Java中允许在方法的后面使用throws关键字对外声明该方法有可能发生的异常,这样调用者在谓用方法时,就明确地知道该方法有异常,井且必须在程序中对异常进行处理,否则编译无法通过。
throws关键字声明抛出异常的语法格式如下:
修饰符 返回值类型 方法名 ([参数1,参数2....])throws ExceptionTypel[,ExceptionType2.....]{
}
从上述语法格式中可以看出,throws关键字需要写在方法声明的后面,throws后面鸳要声明方法中发生异常的类型,通常将这种做法称为方法雨明抛出一个异常
package W;
public class A1 {
public static void main(String[] args) throws Exception{
//下面的代码定义了一个try...catch语句用于捕获异常
try {
int result=divide(4,2);//调用divide()方法
System.out.println(result);
}catch(Exception e) {//对捕获的异常进行处理
e.printStackTrace();//打印捕获的异常信息
}
}
//下面的方法实现了两种整数相除,并使用throws关键字声明抛出异常
public static int divide(int x,int y)throws Exception{
int result=x/y;//定义变量result记录两个数相除的结果
return result;
}
}
运行结果:
四、运行时异常和编译时异常
在实际开发中,经常会在程序编译时产生一些异常,而这些异常必须要进行处理,这种异常被称为编译时异常,也称为checked异常。另外还有一种异常是在程序运行时产生的,这种异常即使不编写异常处理代码,依然可以通过编译,因此被称为运行时异常,也称为unchecked异常。
1、偏译时异常
在Java中,Exception类中除了RuntimeExcurotion类及其子类都是编译时异常。编译时异常的特点是Java编译器会对其进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译。
处理编译时期的异常有两种方式:
使用try...catch语句对异常进行捕获
使用throws关键字声明抛出异常,调用者对其处理
2、运行时异常
RuntimeException类及其子类都是运行时异常。运行时异常的特点是Java编译不会对其进行检查,也就是说,当程序中出现这类异常时,即使没有使用trv..catch语句捕获或使用throws关键字声明抛出,程序也能编译通过。运行日异常一般是由程序中的逻辑错误引起的,在程序运行时无法恢复。比如通过组的角标访问数组的元素时,如果超过了数组的最大角标,就会发生运行时常
代码如下所示:
int[ ] arr=new int[5];
System.out.println(arr[6]);
上面代码中,由于数组arr的length为5,最大角标应为4,当使用arr[6]访问数中的元素就会发生数组角标越界的异常
五、自定义异常
DK中定义了大量的异常类,虽然这些异常类可以描述编程时出现的大部分异常情况,但是在程序开发中有时可能需要描述程序中特有的异常情况,例如文件4-38中在divide0方法中不允许被除数为负数。为了解决这个问题,在Java中允许用户自定义异常,但自定义的异常类必须继承自Exception或其子类
nt result=x/y;//定义变量result记录两个数相除的结果
return result;
}
}
package W;
public class Excption2 {
public static void main(String[] args) {
try {
int result=divide(4,-2);//调用divide()方法,传入一个负数作为被除数
System.out.println(result);
}catch (DivideByMinusExcption e) {//对捕获的异常进行处理
System.out.println(e.getMessage());//打印捕获的异常信息
}
}
//下面的方法实现了两种整数相除,使用throws关键字声明抛出异常
public static int divide(int x,int y)throws DivideByMinusExcption{
if (y<0) {
throw new DivideByMinusE
运行结果:
六、 访问控制
在Java中,针对类、成员方法和属性提供了四种访问级别,分别是private.default、protected和public。接下来通过一个图将这四种控制级别由小到大依次列出
上图中展示了Java中的四种访问控制级别,具体介绍如下:
private(类访问级别): 如果类的成员被private访问控制符来修饰,则这个成员只能被该类的其他成员访问,其他类无法直接访问。类的良好封装就是通过private关键字来实现的。
default(包访问级别): 如果一个类或者类的成员不使用任何访问控制符修饰,则称它为默认访问控制级别,这个类或者类的成员只能被本包中的其他类访问。
protected(子类访问级别): 如果一个类的成员被protected访问控制符修饰,那么这个成员晓能被同一包下的其他类访问,也能被不同包下该类的子类访问。
public(公共访问级别):这是一个最宽松的访问控制级别,如果一个类或者类的成员被public访问控制符修饰,那么这个类或者类的成员能被所有的类访问,不管访问类与被访问类是否在同一个包中。
接下来通过一个表将这四种访问级别更加直观的表示出来,如下表所示
第五章
类的初始化
API指的是应用程序,编程接口
在操作string类之前,首先需要对string类进行初始化,在JAVA中可以通过以下两种方式对string类
进行初始化
1、使用字符串常量直接初始化一个string对象
String str1="abc";
2、使用string的构造方法初始化,字符串对象string的构造方法
String() 创建一个内容为空的字符串
String(String value) 根据指定的字符串内容创建对象
String(char[ ] value) 根据指定的字符串数组创建对象
使用string的构造方法初始化,字符串对象string的构造方法
public class Test2 {
public static void main(String[]args) {
String str1="abc";
//字符串常量直接赋值
String str2=new String();
//String()空参数构造方法,创建一个String类对象,内容为空
String str3=new String("abcd");
//String(String s)创建一个String类对象,指定一个字符串内容
char[]charArray=new char[] {'E','F','G'};
String str4=new String(charArray);
System.out.println(str1);
System.out.println("a"+str2+"b");//ab
System.out.println(str3);
System.out.println(str4);
}
}
运行结果:
二、API_类的常见操作
5.1String类和SreingBuffer类
1、String类的常见操作
String类在实际开发中的应用非常广泛,因此灵活的使用String类是非常重要的
String类的常用方法
在程序中,需要对字符串进行一些基本操作,如获得字符串长度获得指定位置的字符等。
package W;
/*
* String类的基本操作
* 在程序中,需要对字符串进行一些基本操作,如获取字符串长度,获取指定位置的字符等
* public int length() 获取字符串的长度
* public char charAt(int index) 获取字符串中指定位置上的字符
* public int indexof(char ch) 获取指定字符在字符串中第一次出现的位置
* public int lastIndexof(char ch)获取指定字符在字符串中最后一次出现的位置
* public int indexof(String str)获取指定子串在字符串中第一次出现的位置
* public int lastIndexof(String str)获取指定子串在字符串中最后异常出现的位置
*/
public class Exampel {
public static void main(String[] args) {
//声明一个字符串
String s="abcabcdebca";
System.out.println("获取字符串的长度:"+s.length());
System.out.println("获取字符串中第一个字符:"+s.charAt(0));
System.out.println("获取字符c第一次出现的位置:"+s.indexOf('c'));
System.out.println("获取字符c最后一次出现的位置:"+s.lastIndexOf('c'));
System.out.println("获取子串ab第一次出现的位置:"+s.indexOf("ab"));
System.out.println("获取子串ab最后一次出现的位置:"+s.lastIndexOf("ab"));
}
}
运行结果:
程序开发中,经常需要对字符串进行转换操作,例如将字符串转换成数组的形式,将字符串中的字
符进行大小写转换等。
package W;
/*
* String类的转换操作
* 在程序开发中,经常需要对字符串进行转换操作,例如将字符串转换成数组的形式,将字符串的进行大小写转换等
* public char[]tochatArray()将此字符串转换成字符数组
* public static String valueof(int n)将指定int值转换成String类型
* public String touppercase() 将此字符串中的字符全部转换成大写字母,会返回一个新的字符串
*/
public class Exampe {
public static void main(String[] args) {
//声明一个字符串
String s="abcde";
//将此字符串转换成字符数组
char[] charArray=s.toCharArray();
for (int i=0;i<charArray.length;i++) {
//a,b,c,d,e
if(i==charArray.length-1) {
//数组最后一个元素,直接打印元素
System.out.println(charArray[i]);
}else {
//打印元素值与逗号
System.out.print(charArray[i]+",");
}
}
System.out.println("将指定int值转换成String类型后的结果"+String.valueOf(12));
System.out.println("将字符串转换成大写字母的结果:"+s.toUpperCase());
}
}
运行结果:
程序开发中,用户输入数据时经常会有一些错误和空格,这时可以使用String类的replace0和trim0方法,进行字符串的替换和去除空格操作
package W;
public class Example3 {
/*
* String类的替换与去除空格操作
* 程序开发中,用户输入数据时经常会有一些错误和空格,这时可以使用String类的replace()和trim()方法,进行字符串的替换和去除空格操作。
* public String replace(String oldStr, String newStr)
* 将原有字符串中o1dStr字符串内容用newStr字符串所替代,返回一个新的字符串
* public String trim() 返回一个新字符串,它去除了原有字符串的两端空格
*/
public static void main(String[] args) {
//声明一个字符串
String s="itcast";
String s2="i t c a s t ";
//者换操作
System.out.println("将it替换成cn.it之后的结果:"+ s.replace("it","cn.it"));
//去除空格操作
System.out.println("去除左右两边空格后的结果:"+ s2.trim());
System.out.println("去除全部空格后的结果:"+s2.replace(" ",""));
}
}
运行结果:
操作字符串时,经常需要对字符串进行一些判断,如判断字符串是否以指定的字符串开始、结束,是否包含指定的字符串,字符串是否为空等
//判断字符串是否以指定的字符串开始与结束,是否包含指定字符串是否为空等
package W;
/*
* string类的判断操作
* 操作字符串时,经常需要对字符串进行一些判断,如判断字符串是否以指定的字符串开始、结束,是否包含指定的字符串,字符串是否为空等。
* public boolean startsWith(String stx)判断字符串是否以给定字符串stx开头
* public boolean endswith(Stringstx)判断字符串是否以给定字符串stx结尾
* public boolean contains(String str)判断字符串是否包含给定的字符串stx
* public boolean isEmpty()判断字符串内容是否为空
* public boolean equals(String stx)判断字符串与给定字符串stx的内容是否相同
*/
public class Example4 {
public static void main(String[] args) {
//声明一个字符串
String s="String";
String s2 ="Str";
System.out.println("判断字符串是否以Str开头:"+s.startsWith("Str"));
System.out.println("判断字符串是否以ng结尾:"+s.endsWith("ng"));
System.out.println("判断字符串是否包含tri:"+ s.contains("tri"));
System.out.println("判断当前字符串内容是否为空:"+s.isEmpty());
System.out.println("判断两个字符串中的内容是否相同:"+ s.equals(s2));
}
}
运行结果:
在String类中针对字符串的截取和分割操作提供了两个方法,其中,substring0方法用于截取字符串的一部分,split0方法可以将字符串按照某个字符进行分割
//字符串的截取和分割操作
package W;
/*
* String类的截取与分割操作
* 在String类中针对字符串的截取和分割操作提供了两个方法
* 其中,substring()方法用于截取字符串的一部分
* split()方法可以将字符串按照某个字符进行分割
* public String substring(int start)返回一个新字符串,它从原有字符串指定位置开始截取,到字符串末尾结束
* public String substring(intstart, int end) 返回一个新字符串,它从原有字符串指定位置开始截取,到指定位置结束
* public String[] split(String regex)按照指定的字符串进行分割返回一个字符串数组
*
*/
public class Example5 {
private static int i;
public static void main(String[] args) {
//声明一个字符串
String s="羽毛球一篮球一乒乓球";
//截取操作
System.out.println("从第5个字符开始截取到末尾的结果:"+ s.substring(4));
System.out.println("从第5个字符开始截取到第6个字符结束的结果:"+s.substring(4,6));//不包含结尾位置的字符
//分割操作
System.out.println("打印分割后的每个字符串内容");
String[] strArray = s.split("-");
for (int i= 0; i< strArray.length; i++);{
// 羽毛球,篮球,乒乓球
if (i== strArray.length -1) {
//数组最后一个元素,直接打印数组元素值
System.out.println( strArray[i]);
}else {
//打印数组元素值与逗号
System.out.print( strArray[i] +",");
}
}
}
}
运行结果:
String字符串在获取某个字符时,会用到字符的索引,当访问字符串中的字符时,如果符的索引不存在,则会发生StringIndexOutOfBoundsException ( 字符串角标越界异常)
package W;
/*
* String类的异常演示
* String字符串在获取某个字符时,会用到字符的索引,当访问字符串中的字符时
* 如果字符的索引不存在,则会发生StringIndex0utOfBoundsException(字符串角标越界异常)
*/
public class Example6 {
public static void main(String[] args) {
//声明一个字符串
String s="abcde12345";
System.out.println( s.charAt(10) );
}
}
运行结果:
2、StringBuffer类
由于字符事是常量,因此一旦创建,其内容和长度是不可改变的。如果需要对一个字符串进行修改,则只能创建新的字符事。为了便于对字符串进行修改,在JDK中提供了一个StringBuffer类(也称字符事缓冲区),StringBuffer和String类最大的区别在于它的内容和长度都是可以改变的。StringBuffer类似一个字符容器,当在其中添加或副除字符时,并不会产生新的StringBuffcr对象
针对添加和删除字符的操作,StringBuffer类提供了一系列的方法,具体如下表所示
/*
* stringbuffer的构造方法
* public stringBuffer()空参数构造方法
* public stringBuffer(string data)创建带有内容的字符串缓冲区
*
* stringbuffer类的常用方法
* public stringBuffer append(string str)向字符串缓冲区的末尾添加数据,返回当前的stringBuffer对象自身
* public stringBuffer insert(int index,string str)向字符串缓冲区指定位置上,插入指定数据
* public stringBuffer delete(int start,int end)删除字符串缓冲区指定范围内的数据
* public stringBuffer deleteCharAt(int index)删除字符串缓冲区内指定位置上的数据
* public int length()获取字符串缓冲区的长度
* public stringBuffer replace(int start,int end,string str)替换字符串缓冲区指定范围内的字符串
* public stringBuffer setcharAt(int index,char ch)替换字符串缓冲区指定位置上的字符
* public stringBuffer reverse()字符串缓冲区数据翻转方法
*/
public class Test1{
public static void main(String[] args) {
System.out.println("1、添加----------------");
add();
System.out.println("2、删除----------------");
remove();
System.out.println("3、修改----------------");
alter();
}
public static void add() {
//定义一个字符串缓冲区
StringBuffer sb=new StringBuffer();
//向缓冲区的末尾添加指定字符串
sb.append("abcdefg");
System.out.println("append添加数据后的结果:"+sb);
//向缓冲区指定位置插入字符串
sb.insert(2, "123");
System.out.println("插入数据后的结果:"+sb);
}
public static void remove() {
//定义一个字符串缓冲区对象
StringBuffer sb=new StringBuffer("abcdefg");
//删除字符串缓冲区指定范围内的数据
sb.delete(1, 5);//不包含结尾位置元素
System.out.println("删除指定范围数据后的结果:"+sb);
//删除字符串缓冲区指定位置上的字符
sb.deleteCharAt(2);
System.out.println("删除指定位置数据后的结果:"+sb);
//清除字符串缓冲区
sb.delete(0, sb.length());
System.out.println("清除缓冲区数据后的结果:"+sb);
}
public static void alter() {
//定义一个字符串缓冲区对象
StringBuffer sb=new StringBuffer("abcdef");
//修改指定位置的字符
sb.setCharAt(1, 'p');
System.out.println("修改指定位置数据后的结果"+sb);
//修改指定范围内的数据
sb.replace(1, 3, "qq");
System.out.println("替换指定范围内字符串的结果"+sb);
//字符串缓冲区数据翻转
System.out.println("字符串缓冲区数据翻转后的结果"+sb.reverse());
}
}
运行结果:
案例
/*
* 记录一个子串在整串中出现的次数
* 思路:
* 1.定义一个整串,定义一个子串
* 2.获取子串在整串中出现的次数
*/
public class Test1{
public static void main(String[] args) {
//1.定义一个整串,定义一个子串
String str = "nbaernbatnbaynbauinbapnba";//整串
String key = "nba";//子串
//2.获取子串在整串中出现的次数
int count = getKeyStringCount(str,key);
System.out.println("count="+count);
}
//获取子串在整串中出现的次数
public static int getKeyStringCount(String str, String key) {
//定义计数器,用来记录出现的次数
int count = 0;
//如果整串中不包含子串,则直接返回count
if(!str.contains(key)) {
return count;
}
//定义变量,用来记录key出现的位置
int index = 0;
/*
* 1.查找子串在整串中出现的位置
* 2.将出现的位置记录在index变量中
*/
while((index = str.indexOf(key)) != -1) {
//子串出现次数累加
count++;
//截取整串,从子串出现的位置后面开始,到整串末尾
str = str.substring(index + key.length());
}
return count;
}
}
运行结果: