您的位置:首页 > 职场人生

黑马程序员————java基础--------IO输入输出之异常、File类和递归

2014-11-21 23:13 771 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

第一部分
异常


异常按照情况的严重性,可以分为Error和Exception。Error是比较严重的情况,比如内存溢出,不是写程序本身的情况。Exception则又按照其出现的时间,分为编译期异常和运行期异常。运行期异常是:RuntimeException,非RuntimeException的异常都属于编译期异常。

运行期异常是代码不够严谨。

如果程序出现了问题,我们没有做任何处理,最终JVM就会做出默认的处理。将异常的名称,原因及出现的问题等信息输出控制台。同时会结束程序。虽然JVM给出了我们提示信息,但是其同时也结束了程序运行。这就导致程序不能执行完,为了能够将一些无关紧要或者局部问题排除掉,并且程序继续执行,这个时候就需要自己处理,抛出异常。

处理异常两种方式:

(一)、try...catch....finally

(二)、throws 抛出

前者的处理格式为

try{

可能出现问题的代码;

}catch(异常名 变量){

针对问题的处理;

}finally{

释放资源;

}

注意:try里面的问题越少越好。因为这里的代码越多,需要处理的信息就会越多,JVM就要分配更多的资源来处理。

catch里面必须有内容,哪怕是给出一个简单的提示

第一种格式:

try{

...

}catch(异常类名 变量名){

...

}

try{

...

}catch(异常类名 变量名){

...

}

...

第二种格式:

try{

...

}catch(异常类名 变量名){

...

}catch(异常类名 变量名){

...

}

能明确的尽量明确异常类型,如果抛出Exception父类,父类就要再子类中逐一查询。降低了效率。

第三种:jdk1.7之后出现

try{

}catch(异常名1|异常名2|异常名3 变量){

...

}

这里需要注意的是异常名必须是平级关系。不能有父类如Exception。

编译期异常与运行期异常的区别:

运行期异常:只要程序足够严谨,就不会发生运行期异常。

编译期异常:必须处理,否则无法运行。

异常中的方法:

public String getMessags(); 返回该消息的详细信息字符串

public String toStrng():返回异常的简单信息描述

printStackTrace()

(二)、throws:定义功能方法时,需要把出现的问题暴露出来让调用者去处理。就是通过throws在方法上标示。

格式:throws 异常类名

这个格式必须跟在方法的括号后面。

当我们不想处理异常,或者没有能力去处理这个异常的时候,就可以在方法声明上将异常通过throws抛出。这样在调用该方法时,调用者会来处理这个异常。如果调用者也不处理这个异常,而是将这个异常抛给了main方法,结果main方法就给了虚拟机,这样就没有意义了。因为虚拟机会在遇到异常时,终止程序。最好能在被调用的时候将异常处理掉,避免在main方法上抛出异常。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("我要去黑马");
try {
method();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("去黑马有肉吃");
}
// 编译期异常的抛出
// 在方法声明上抛出,是为了告诉调用者,方法有问题
public static void method() throws ParseException {
String s = "2014-11-20";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = sdf.parse(s);
System.out.println(d);
}
}


上面的这个例子在main方法中调用method();但是method()方法是有异常抛出的,如果调用者直接在main方法上直接抛异常,就会导致程序在运行到method()时就停止了。但是如果通过try..catch..来处理这个异常,最终程序还可以走到"去黑马有肉吃"。

注意:在调用方法时,如果方法声明上有异常,调用者最好处理(编译期异常)。但是如果这种异常是运行期异常,我们就可以不处理。

关键字:throw与throws的区别:

throw:在功能方法内部出现某种情况,程序不能继续运行,需要进行跳转时,就用throw把异常对象抛出。只能抛出一个异常对象名,执行throw,则一定会抛出异常。throws用在方法声明后面,跟的是异常类名,可以跟多个异常类名,用逗号隔开,throws表示出现异常的一种可能性,并不一定会发生。

public static void method(){
int a=10;
int b=0;
if(b==0){
throw new ArithmeticException();
}else{
System.out.println(a/b);
}
}


finally:

被finally控制的语句体一定会执行。只要虚拟机不退出,就会执行。

public static void show(){
int a=10;
try{System.out.println(a/0);
a=20;
}catch{
a=30;
return a;//走到这一步return 30;//又走回来,return 30.
}finally{
a=40;//第二步此时a为40
}
return a;

}


第二部分File类

文件和目录路径名的抽象表示形式。

File类的常用操作及演示

构造方法:

public File(String pathname) 根据一个路径得到File对象

public File(String parent,String child)根据一个目录和一个子文件得到一个对象

public File(File parent,String child) 根据一个父File对象和一个子文件/目录得到File对象。

通过构造方法,我们可以建一个File类的对象,通过File类的对象,可调用其方法。

第一种File构造方法:

import java.io.File;
public class FileDemo{
public static void main(String [] args){
//创建一个对象file1,其指向e盘的itheima文件夹。
File file1=new File("e:\\itheima");
//在E盘创建一个文件夹,命名为itheima;
file1.mkdir();
}
}


第二种File构造方法

//创建一个对象file。

File file=new File("E:\\itheima","it.txt");

File file2=new File("e:\\itheima\\a.java");

//通过调用创建文件的方式创建文件。

file.createNewFile();

file2.createNewFile();

上面的第一种构造方法创建的对象,通过调用创建文件的方法,先是在E盘里创建了一个名为itheima的文件夹,然后又在该文件夹中创建了一个it.txt的文件。第二种构造方法创建的对象,调用createNewFile()方法时,在已经存在的itheima文件夹中又创建了一个a.java的文件。file2创建文件时,该目录必须已经存在,不然就会报出,“系统找不到指定路径”的异常。

创建功能

public boolean createNewFile()创建文件 抛异常的方法

public boolean mkdir()创建文件夹 不抛异常的方法

public boolean mkdirs())创建多层文件夹

如果要创建多层文件夹时,可以调用mkdirs()。

File file=new File("e\\it\\黑马\\安卓");

file.mkdirs();

系统将会在e盘创建这样一个多层文件夹。

如果在创建File对象时,没有写盘符,将会在当前文件夹中创建。

注意:

File file=new File("e\\黑马\\a.txt");

file.mkdirs();

这里将会在e盘创建一个黑马文件夹,并且在该文件夹的里面再创建一个名为“a.txt”的文件夹。

删除功能

public boolean delete()

例:File file=new File("e:\\heima");

file.delete();

file.delete()方法将会删除e盘中的heima文件夹。

重命名功能

public boolean renameTo(File dest)

File file =new File("e:\\andriod.txt");

file.createNewFile();

File file2=new File("d:\\heima.txt");

file.renameTo(file2);

如果两个路径相同,则是重命名如果两个路径不同,则是重命名并且剪切。上面这个例子,就是将E盘中的andriod.txt文件剪切到D盘根目录下,并且重命名为heima.txt。

判断功能:

public boolean isDirectory() 判断是否为目录

public boolean isFile()判断是否为文件

public boolean exists() 判断是否存在

public boolean canRead() 是否可读

public boolean canWrite() 是否可写

public boolean isHidden() 是否隐藏

获取功能:

public String getAbsolutePath() 获取绝对路径

public String getPath()获取相对路径

public String getName()获取文件名

public long length()获取文件长度

public long lastModified()获取最后一次修改毫秒值

高级获取功能

public String[] list() 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。

public File[] listFiles() 获取指定目录下的所有文件或者文件夹的File数组

public static void main(String [] args){
//将e盘目录封装成对象
File file=new File("e:\\");
//对象调用方法,并且返回给数组str;
String [] str=file.list();
for(String s:str){
//将会把E盘根目录下的文件及文件夹的名称都输出。
System.out.println(s);
}
}


导包运行上面的程序,我们就会发现其输出了e盘根目录下的所有内容,包括隐藏文件等。

另外还有一种方法也能达到这种效果

File [] array=file.listFiles();
for(File f:array){
//由于f为File类型,因此可以调用其方法getName()来获取文件名。
System.out.println(f.getName());
}


虽然上面两种方法输出结果一致,但是后者由于返回的是文件对象数据,因此其能够调用更多的方法,用途也更广泛。

注意:绝对路径和相对路径的区别,绝对路径是从盘符开始直到文件名,但是相对路径,则是在当前文件夹下的路径。也就是相对路径,加上当前文件夹的绝对路径,才是这个文件的绝对路径。

练习题:输出D盘根目录下后缀名为.txt的文件。

方法一:

import java.io.File;
class FileDemo{
public static void main(String [] args){
//将E盘根目录转为对象
File file=new File("e:\\");
File [] array=file.listFiles();
for(File f:fileArray){
//判断是否为文件
if(f.isFile()){
//如果是文件,那么它是不是以“.txt”结尾呢?
if(f.getName().endsWith(".txt"){
//满足上面的条件,就是我们需要输出的。
System.out.println(f.getName());
}
}
}
}
}


方法二:这个方法区别于上面的本质在于不是先获取所有元素,再判断,而是在获取的时候,已经是判断过后满足条件的啦。这里就要用文件过滤器,其方法如下:

public String [] list(FilenameFilter filter) 这个返回的是String数组

public File [] listFiles(FilenameFilter filter) 返回的是File数组

import java.io.File;
class FileDemo{
public static void main(String [] args){
//封装E盘目录
File file=new File("e:\\");
//通过文件过滤器的匿名实现类对象来创建对象
String [] str=file.list(new FilenameFilter(){
//重写方法
public boolean accept(File dir,String name){
//通过File的第三种构造方法,封装目录。
File file =new File(dir,name);
//判断该文件名是不是文件
boolean flag=file.isFile();
//判断该文件是不是以".txt"结尾
boolean flag2=name.endsWith(".txt");
return flag&&flag2;
}
});
for(String s:str){
System.out.println(s);
}
}
}


第三部分 递归

定义:方法定义中调用方法本身的现象。(自己调自己,而不是别人调)。

注意:递归一定要有出口,不然就是死递归

递归的次数不能太多,否则就内存溢出

构造方法不能递归使用

5!=5*4*3*2*1;

5!=5^*4!

递归解决问题的思想:

递归方法在加载到栈内存后,由于方法本身调用方法,第一个进栈的递归,将在最下面,他的上面,由于是在不停地调用方法本身,将会形成一种链式结构,直到方法的最终参数值,这是方法的分解。

当到达方法的最终值时,方法就开始运算,然后逐层消失,直到回到最高层的递归方法。

练习题:

输出斐波拉契数列:1,1,2,3,5,8,13.21,34,55

public class Test8 {
public static void main(String [] args){
for(int x=1;x<21;x++){
System.out.println(show(x));
}
System.out.println("*********");
System.out.println(array(20));
}
//数组实现
public static int array(int n){
int[] arr = new int
;
arr[0] = 1;
arr[1] = 1;
int s=2;
// arr[2] = arr[0] + arr[1];
// arr[3] = arr[1] + arr[2];
// ...
for (int x = 2; x < arr.length; x++) {
arr[x] = arr[x - 2] + arr[x - 1];
s=arr[x];
}
return s;
}
//递归方法。不是if...else连用,还需要在方法体外面实现返回。
public static int show(int n){
int s=2;
if(n==1||n==2){
return 1;
}

if(n>2){
s= (show(n-2)+show(n-1));
}
return s;
}
//递归方法。如果是if...else连用,就不用再在方法体外面return返回值了。
public static int fib(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return fib(n - 1) + fib(n - 2);
}
}
//for循环变量第一种
public static int ForDemo(int n){
if(n==1||n==2){
return 1;
}
int a=1;
int b=1;
int c=2;
for(int x=2;x<n;x++){
c=a+b;
a=b;
b=c;
}
return c;
}
//for循环变量第二种
public static int ForDemo1(int n){
if(n==1||n==2){
return 1;
}
int a=1;
int b=1;
for(int x=2;x<n;x++){
int temp=a;
a=b;
b=temp+b;

}
return b;
}

}


输出e盘下的所有.java文件的绝对路径。

public static void main(String [] args){
File file=new File("e:\\");
getAlljava(file);

}
public static void getAlljava(File file){
File [] fileArray=file.listFiles();
for(File file1:fileArray){
if(file1.isDirectory()){
getAlljava(file1);
}else{
if(file1.getName().endsWith(".java")){
System.out.println(file1.getAbsolutePath());
}
}

}

}


删除e盘下所有内容:

public static void main(String[] args) {
// 封装目录
File srcFolder = new File("demo");
// 递归实现
deleteFolder(srcFolder);
}
private static void deleteFolder(File srcFolder) {
// 获取该目录下的所有文件或者文件夹的File数组
File[] fileArray = srcFolder.listFiles();
if (fileArray != null) {
// 遍历该File数组,得到每一个File对象
for (File file : fileArray) {
// 判断该File对象是否是文件夹
if (file.isDirectory()) {
deleteFolder(file);
} else {
System.out.println(file.getName() + "---" + file.delete());
}
}
System.out.println(srcFolder.getName() + "---" + srcFolder.delete());
}
}


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐