一.异常类
1.Throwable的两个子类:Error和Exception
2.Exception类的分类:
1).编译时期异常:只要不是RuntimeException中的异常都属于编译时期异常,比如:IOException(IO流中的),ParseException(解析异常)
2)运行时期异常:RuntimeException:可能由于我们代码的逻辑不够严谨导致的,例如:NullPointerException:空指针异常!(对对象进行非空判断可以防止该异常的出现)ArrayIndexOutOfBoundsException:数组越界;ArithmeticException:算数异常,;NumberFormatException:当将字符串转换成数字时,字符串必须是数字的字符串,否则会报异常。
3.异常处理的两种方式:
1)标准格式:try...catch...finally:捕获异常
三种变形格式:try...catch ; try...catch...catch ; try...finally...(多线程的时候:Lock锁)
2)throws 抛出异常
4.try...catch格式
1)单个异常:
try{
//可能出现问题的代码
}catch(异常类名 变量名){
//输出语句处理
}
2)多个异常:多个异常一块进行处理时,只要try语句中的代码和catch语句中的代码所描述的异常类的信息一致,直接执行到catch里面的代码,try...catch语句即结束。
try{
//可能会出现问题的多个语句
}catch(异常类名1 变量名){
输出语句处理
}catch(异常类名2 变量名){
输出语句处理
}
特点:多个异常进行处理时,第一个异常如果是大异常,则后面的异常可以不用给出
针对多个异常的处理,JDK7以后又一种新的处理方式:
try{
//可能会出现问题的代码
//...
}catch(异常类名1 | 异常类名2 ....变量名){
处理异常...
处理异常...
}
注意:
1)针对多个异常类名之间是一种平级关系
2)虽然有多个异常,但是针对具体的异常给出具体的处理
package day_17_11_19.exception;
public class ExceptionDemo {
public static void main(String[] args) {
method1();
method2();
method3();
method4();
method5();
}
//多个异常处理,大异常在后小异常之前
private static void method5() {
int a = 20;
int b = 0;
int [] array = {0,1,4,5};
try{
System.out.println(a/b);
System.out.println(array[4]);
}catch(ArithmeticException e){
System.out.println("除数不能玩为0"); //第一个try...catch...语句描述的相一致,即刻结束
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("您访问了数组中不存在的索引");
}catch(Exception e){
System.out.println("程序可能出现问题了");
}
System.out.println("------");
}
//多个异常:分别try{...}catch{...}
private static void method4() {
int a = 20;
int b = 0;
int [] array = {0,1,4,5};
try{
System.out.println(a/b);
}catch(ArithmeticException e){
System.out.println("除零错误");
}
try{
System.out.println(array[4]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界");
}
System.out.println("------");
}
//多个异常,jdk7以后的新特性
private static void method3() {
int a = 20;
int b = 0;
int [] array = {0,1,4,5};
try{
System.out.println(a/b);
System.out.println(array[4]);
}catch(ArithmeticException | ArrayIndexOutOfBoundsException e){
System.out.println("除零错误");
System.out.println("数组越界");
}
System.out.println("--------");
}
//单个异常
private static void method2() {
int [] arry ={12,34,14,17,25};
try{
System.out.println(arry[5]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("数组越界");
}
System.out.println("--------");
}
//单个异常
private static void method1() {
int a = 10;
int b = 0;
try{
System.out.println(a/b);
}catch(ArithmeticException e){
System.out.println("除零错误");
}
System.out.println("--------");
}
}
5.编译时期异常:必须给予处理,否则编译是不能通过的
package day_17_11_19.exception;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo2 {
public static void main(String[] args) {
int a = 2;
int b = 0;
if(b!=0){
System.out.println(a/b);
}
System.out.println("今天天气很好");
method();
}
private static void method() {
// String日期“文本”格式---->Date格式:解析
String s = "2017-7-23";
//创建SimpleDataFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//调用parse()方法
Date d;
try{
d = sdf.parse(s);
System.out.println("d:"+d);
}catch (ParseException e) {
// e.printStackTrace();//异常中的方法
System.out.println("解析出问题了...");
}
}
}
6.异常常用的方法:
try里面的代码一旦出现问题了,JVM 就会针对这个问题抛出一个异常,然后和catch里面所描述的异常是否匹配,如果一致就会产生一个异常对象,然后去处理这个异常对象,就会调用异常中的一些方法
常用的方法:
public String getMessage() 消息字符串
public String toString()
描述字符串:
1)当前类的全路径名称(指的是当前异常类名所在的包的全路径名称)
2)": "(冒号和一个空格)
public void printStackTrace():
该方法是里面包含了消息字符串以及当前出现错误的异常的时候所描述哪个包下以及代码中具体的错误出现第几行,返回值是void,也就直接在控制台输出
package day_17_11_19.exception;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo3 {
public static void main(String[] args) {
// 解析日期的文本格式
String str = "2017-7-23";
//创建SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh") ;
try{
Date date = sdf.parse(str) ;//这里面的代码一旦有问题,JVM就会抛出一个异常,和catch里面进行匹配,如果一致
System.out.println(date);
}catch (ParseException e){
e.printStackTrace();
System.out.println(e.getMessage()); //Unparseable date: "2017-7-23"
System.out.println(e.toString()); //java.text.ParseException: Unparseable date: "2017-7-23"
}
}
}
7.异常处理的第二种方式:
throws:抛出异常,在方法声明上抛出异常,由于,编译时期异常,调用者必须要处理,实际开发中,要尽量避免在main()方法抛出异常,在子方法中可以抛出异常。
面试题:throws和throw的区别?
throws:抛出异常,后面跟的异常类名,可以跟多个异常类名,中间用逗号隔开,throws在方法声明上抛出,表示异常的一种可能性,由调用者去处理
throw:抛出异常:后面跟的异常对象(匿名对象),只能跟具体的一个异常对象,throw在方法中的语句中抛出,表示异常的绝对性
实际开发中:throws要比throw用的比较多,而try...catch...又比throws用的比较多!
package day_17_11_19.exception;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo4 {
public static void main(String[] args) throws ParseException {
method();
try{
method2();
}catch(Exception e){
e.printStackTrace();
//System.out.println("程序出错了");
}
}
//throw
private static void method2() {
int a = 10 ;
int b = 0 ;
if(b==0){
System.out.println(a/b);
throw new ArithmeticException() ;
}else{
System.out.println("不会出现问题");
}
}
private static void method() throws ParseException {
String str = "2017-7-23";
//创建SimpleDateFormat对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//解析
Date d = sdf.parse(str);
System.out.println(d);
}
}
8.捕获异常的标准格式:
try...catch...finally
finally常用在数据库或者IO流中,用来释放资源的,finally中的代码一定会执行,不执行的情况只可能是JVM退出,即system.exit(0)
注意:如果catch里面有return语句,finally中的语句还会执行的,并且在return前执行。
package day_17_11_19.exception;
public class FinallyDemo {
public static int a;
public static void main(String[] args) {
System.out.println("返回值:"+method());
}
private static int method() {
try{
int a = 10;
System.out.println(a/0);
a = 20;
//System.out.println("a1:"+a);
}catch(ArithmeticException e){
int a = 30;
System.out.println("a2:"+a);
//代码执行到这会先执行finnally中的代码再执行return
return a;
}finally{
int a = 40;
System.out.println("a3:"+a);
}
return a;
}
}
面试题:final,finalize,finally的区别
1)final:最终的,终态的。修饰类:不能被继承;修饰成员方法:不能被重写;修饰成员变量:一个常量
2)finalize:通过gc垃圾回收器回收不用的对象或者变量,system.gc():实质:调用Object类中的finalize()方法,表示回收没有更多引用对象或者变量等等。
3)finally:不能单独使用,和try...catch...finally中一块使用,(异常、IO、数据库中使用),释放资源,finally中的代码一定会被执行。
9.自定义异常类:在开发中经常可鞥会用到自己定义一个异常类
必须继承自Exception或者继承自RuntimeException
package day_17_11_19.exception;
public class MyException extends Exception{
public MyException() {
}
public MyException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
package day_17_11_19.exception;
public class Teacher {
public void check(int score) throws MyException{
//针对分数进行判断
if(score>100 || score<0){
throw new MyException("分数不在0-100之间");
}else{
System.out.println("分数的值为:"+score);
}
}
}
package day_17_11_19.exception;
import java.util.Scanner;
public class StudentDemo {
public static void main(String[] args) {
// 创建键盘录入对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入分数:");
int score = sc.nextInt();
//创建Teacher对象
Teacher t = new Teacher();
try{
t.check(score);
}catch(MyException e){
e.printStackTrace();
}
}
}
异常类的注意事项:
1.父类方法异常,子类抛出异常不能比父类大(最起码保持一致)(通俗讲父亲坏了,孩子不能更坏)。
2.父类方法没有异常,那么在子类中重写该方法,则只能捕获,不能抛出异常。
二.File类
用来描述文件或者目录(文件夹)的路径的抽象表现形式
1.常用的构造方法:
public File(String pathname):
public File(String parent,String child)
public File(File parent,String child)
2.成员方法
public boolean mkdir():创建此抽象路径名指定的目录(文件夹)
public boolean creatNewFile():创建文件,若文件存在,不创建,会throws IOException
public boolean mkdirs():创建文件夹,文件夹不存在,才开始创建(嵌套的文件夹)
注意:创建文件之前,确保文件夹存在;没有带盘符的创建文件在当前项目下。
3.删除功能:
public boolean delete():只能逐层删除
package day_17_11_19.fle;
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) throws IOException {
//创建文件夹
File f1 = new File("E:\\demo");
System.out.println("mkdire1:"+f1.mkdir());
//创建文件
//方式1:
File f2 = new File("E:\\demo\\my.txt");
System.out.println("creatNewFile2:"+f2.createNewFile());
//方式2:
File f4 = new File("E:\\demo","my.txt");
System.out.println("creatNewFile4:"+f4.createNewFile());
//方式2:
File f5 = new File("E:\\demo");
File f6 = new File(f5,"my.txt");
System.out.println("creatNewFile6:"+f6.createNewFile());
//在文件夹不存在时创建嵌套的文件夹
File f3 = new File("e:\\aa\\bb\\cc");
System.out.println("mkdirs:"+f3.mkdirs());
System.out.println(f3.delete()); //文件夹cc被删除
}
}
4.重命名功能
public boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。
特点:1)当两个抽象路径一致,那么只是重命名
2)当这两个抽象路径不一致,有剪切并且改名了
5.判断功能:
public boolean isDirectory():判断是否是文件夹
public boolean isFile():判断是否是一个标准文件
public boolean canRead():判断是否可读
public boolean canWriter():判断是否可写
public boolean isHidden():判断是否是隐藏文件
public boolean isAbsolute():判断次路径名是否是绝对路径
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) throws IOException {
//创建文件夹
File f = new File("E:\\text");
f.mkdir();
//创建文件
File f1 = new File("E:\\text\\a.txt");
f1.createNewFile();
//修改文件夹名称
File f2 = new File("e:\\text\\newA.txt");
f1.renameTo(f2); //E:\\text\\a.txt文件被重命名为newA.txt;
//对f2进行判断
/**
* public boolean isDirectory():判断是否是文件夹 经常用到
* public boolean isFile():判断是否是一个标准文件 经常用到
* public boolean isHidden():判断是否是隐藏文件
* public boolean isAbsolute():判断次路径名是否是绝对路径
* */
System.out.println(f2.isAbsolute()); //true
System.out.println(f2.isDirectory()); //false
System.out.println(f2.isFile()); //true
System.out.println(f2.isHidden()); //false
//获取功能
System.out.println(f2.length());
System.out.println(f2.lastModified());
}
}
6.获取功能:
public File getAbsolutePath():获取当前文件或者文件夹绝对路径
public String getPath():获取相对路径
public long length()返回由此抽象路径名表示的文件的长度
public long lastModified()返回此抽象路径名表示的文件最后一次被修改的时间
public String getName():获取名称
7.高级获取功能:
public String[] list():返回对象是一个字符串数组,当前那个盘符下所有的文件以及文件夹的字符串名称数组
public File[] listFiles():返回对象是一个File数组,当前那个盘下的所有的文件以及文件夹的File数组
练习:判断E盘目录下是否有后缀名为.java的文件,如果有,就输出此文件名称
import java.io.File;
public class FileDemo3 {
public static void main(String[] args) {
//获取e盘下的所有文件
File f = new File("e:\\");
//方式一:
String[] strArray = f.list();
//对文件进行遍历
if(strArray!=null){
for(String s : strArray)
System.out.println(s);
}
System.out.println("------");
//方式二:
File[] fileArry = f.listFiles();
//对文件进行遍历
if(fileArry!=null){
for(File file : fileArry ){
//判断是否有文件
if(file.isFile()){
//判断是否以".java"结尾
if(file.getName().endsWith(".java")){
System.out.println(file.getName());
}
}
}
}
}
}
方法二:
package day_17_11_19.fle;
import java.io.File;
import java.io.FilenameFilter;
public class FileTest {
public static void main(String[] args) {
//1)封装e盘
File file = new File("e:\\") ;
//2)public String[] list(FilenameFilter filter)
String[] strArray = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
//return false;
//该逻辑是需要根据需求来判断的
//该方法中的返回值是需要我们自己判断的,根据需求做逻辑判断
File file = new File(dir, name) ;
//判断File是否是文件
boolean flag1 = file.isFile() ;
//如果是文件,还要判断是否以".jpg"结尾
boolean flag2 = name.endsWith(".jpg") ;
return flag1 && flag2 ;
//return new File(dir,name).isFile() && name.endsWith(".java") ;
}
});
//遍历字符串数组
for(String s : strArray){
System.out.println(s);
}
}
}
8.文件名称过滤器
public String[] list(FilenameFilter filter)
public File[] listFiles(FileFilter filter)
参数是一个接口(开发中使用接口的匿名内部类方式)
实现的方法:boolean accept(File dir, String name):这个方法的返回值是true(就是表示要将当前文件夹或者文件的名称在添加数组中),false(表示不添加数组中)
三.IO流:设备之间数据的传输(硬盘和内存之间的数据传输)
1.IO流的分类:
按流的方向分:输入流:读数据 输出流:写数据
按数据类型分:字节流、字符流
字节输入流:InputStream
字节输出流:OutputStream ,该类是抽象类,不能实例化,FileOutputStream是OutputStream的子类
字符输入流:Reader
字符输出流:Writer
package day_17_11_19.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author Luna
*需求:输出一个文本文件,给文本文件中写一句话:travel around the world!
*分析:若提到文本文件,就用字符流,
*开发步骤:
* 1)创建文件输出流对象
* 2)写数据
* 3)关闭资源
*2017年11月23日
*/
public class IODemo {
public static void main(String[] args) throws IOException {
// 创建输出对象
FileOutputStream fos = new FileOutputStream("E:\\demo\\my.txt") ;
//写数据,String类中的getBytes()
fos.write("travel around the world!".getBytes()) ;
//释放流资源
fos.close();
//fos.write("高圆圆".getBytes()) ;//流资源关闭后就不能向其中写数据了,否则会报java.io.IOException: Stream Closed
}
}
2.输出流中写数据的方法:
public abstract void write(int b):将指定的字节写入到输出流中
public void write(byte[] b):将指定的字节数组写入到输出流中
public void write(byte[] b, int off,int len):将字节数组的一部分写入到输出流中
package day_17_11_19.io;
import java.io.FileOutputStream;
import java.io.IOException;
public class IODemo2 {
public static void main(String[] args) throws IOException {
//创建一个文件输出流对象
FileOutputStream fos = new FileOutputStream("E:\\demo\\my.txt") ;
//写数据:
//方式1:public abstract void write(int b):将指定的字节写入到输出流中
fos.write(97) ;
fos.write(55) ;
fos.write(57) ;
fos.write(65) ;
//方式2:public void write(byte[] b):将指定的字节数组写入到输出流中
byte[] bys = {97,98,99,100,101} ;
fos.write(bys) ;
//方式3:public void write(byte[] b, int off,int len):实际开发中:该方法和读数据一块使用
fos.write(bys, 1, 3) ;
//关闭资源
fos.close();
}
}
注意:上例中写入的数据和数据之间没有换行“a79Aabcdebcd”,要想换行必须写入换行符号,每一个系统他们对应IO这块换行符号是不一样的
对于windows操作系统来说:换行符号:\r\n
对于Linux操操作系统来说:\n
对于Mac操作系统来说:\r
3.在文件中追加数据:
public FileOutputStream(File file,boolean append):第二个参数设置为true,表示写入文件的末尾处
package day_17_11_19.io;
import java.io.FileOutputStream;
import java.io.IOException;
public class IODemo3 {
public static void main(String[] args) throws IOException {
//创建一个输出流对象
FileOutputStream fos = new FileOutputStream("E:\\demo\\my.txt") ;
//写数据
for(int x = 0 ; x <10 ; x ++){
fos.write(("helo"+x).getBytes()) ;
//写入一个换行符号
fos.write("\r\n".getBytes());
}
//关闭资源
fos.close() ;
}
}