异常+文件+I/O流+设计模式
每日一句:越来越发现,自信对一个人来说是多么的重要,而自信毫无疑问是不断练习获得的。
practice makes perfact
一:异常
这是一个数学运算的异常,除数不能为0.
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("start");
int a = 10;
int b = 0;
System.out.println(a/b);
System.out.println("end");
}
}
1:异常:就是程序出现的不正常的情况。
异常的分类:
(1)错误:这是非常严重的问题,一般我们处理不了。
(2)异常:A:编译时期异常 开始就必须要处理的,如果不处理,后面就走不了。B:运行时期异常 开始可以不用处理。这种问题一旦发生,就是我们的程序问题,需要我们修改程序。
2:我们是如何处理异常,保证各个部分不影响的呢?
两种方案:
A:try…catch…finally
B:throws
try…catch…finally:
try{
可能出现异常的代码
}catch(异常类名 变量名) {
针对异常的代码处理
}finally {
释放资源的地方
}
我们简化一下第一个:
try{
可能出现异常的代码
}catch(异常类名 变量名) {
针对异常的代码处理
}
3:多个异常发生时应该注意的地方?
如果说代码中存在多个catch块,那么如果有一个catch块中的异常类是Exception,那么这个catch块必须放到最后,如果你放到最前面的话,所有的异常全部都会被Exception,的处理逻辑所处理,后面的所有catch块将不再会被访问。
4:编译时期异常和运行时期异常的区别?
编译时期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译。
运行时期异常:无需显示处理,也可以和编译时异常一样处理。
事实上我们不希望发生异常,但是对比俩者更不希望运行异常的发生,因为它不能够让我们及时修改代码。
5: final,finally的区别?
(1)final:最终的意思。可以修饰类,方法,变量。
修饰类,类不能被继承
修饰方法,方法不能被重写
修饰变量,变量是常量
(2)finally:异常处理的一部分。被finally控制的代码一定会执行。特殊情况:在执行到finally之前,jvm退出 。
6:try…catch和throws的区别?
try…catch 是直接进行了处理, 而throws则是把异常处理的事情交给了调用者。
7:throw和throws的区别?
(1)throws:
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
(2) throw:
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常?
8:注意
(1):子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
(2):如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
(3):如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只能try,不能throws
上述仅仅针对编译时期异常
与运行时期异常无关。
二:文件
1:什么是文件?
File:文件和目录(文件夹)路径名的抽象表示形式。
2: File的构造方法?
File(String pathname):把一个路径名称封装成File对象
File(String parent, String child):把一个父路径和一个子路径封装成一个File对象
File(File parent, String child):把一个父路径File对象和一个子路径封装成一个File对象
3:file的方法
创建功能,删除功能,判断功能,获取功能。如果使用这些方法可以通过查看API来掌握。
三:IO流<重点>
1:I/O的分类
2:字节流写方法举个例子进行步骤分析
需求:请用字节流往一个文本文件中写一句话:”helloworld”
package com.study_01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
// 需求:请用字节流往一个文本文件中写一句话:"helloworld"。
public class OutStreamDemo {
public static void main(String[] args) throws IOException {
//1:创建输出流对象
FileOutputStream fos=new FileOutputStream("a.txt");
//2:调用它的写方法
byte []bys="helloworld".getBytes();
fos.write(bys);
//3:释放资源
fos.close();
}
}
运行结果即为在同一包下创建了一个a.txt文件,里边并有一句话“helloworld”
3:字节流读方法举个例子进行分析具体步骤
package com.study_01;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//A:把a.txt的内容复制到b.txt中
public class InputStreamDemo {
public static void main(String[] args) throws IOException {
//1:封装数据源和目的地
FileInputStream fis=new FileInputStream("a.txt");
FileOutputStream fos=new FileOutputStream("b.txt");
//2:调用方法将a.txt的内容写到b.txt中
int by;
while((by=fis.read())!=-1){
fos.write(by);
}
//3:释放资源
fis.close();
fos.close();
}
}
运行结果就是:把a.txt的内容复制到了b.txt中。
4:字节缓冲区流(也叫高效流)
BufferedInputStream(read() 一次读取一个字节, public int read(byte[] b):返回实际读取长度,数据被读取到数组中。)
BufferedOutputStream(write(byte[] b))
5:我们可以举一个案例来测试字节基本流和字节高效流分别读取一个字节和一个字节数组时间的快慢。
这里写package com.study_02;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字节流复制文件(视频文件,并测试所用时间):
* A:基本字节流一次读写一个字节 //总耗时:6828
* B:基本字节流一次读写一个字节数组 //总耗时:16
* C:高效字节流一次读写一个字节 //总耗时:188
* D:高效字节流一次读写一个字节数组 //总耗时:15
*/
public class Test {
public static void main(String[] args) throws IOException {
long startTime=System.currentTimeMillis();
method1();
/*method2();
method3();
method4();*/
long endTime=System.currentTimeMillis();
System.out.println("总耗时"+(endTime-startTime));
}
private static void method1() throws IOException {
// 基本字节流一次读写一个字节
//1:封装数据源和目的地
FileInputStream fis=new FileInputStream("e:\\b.mp4");
FileOutputStream fos=new FileOutputStream("a.mp4");
//2:调用读写方法
int ch;
while((ch=fis.read())!=-1){
fos.write(ch);
}
//3:关流,释放资源
fis.close();
fos.close();
}
// private static void method2() throws IOException {
// //基本字节流一次读写一个字节数组
// //1:创建数据源和目的地
// FileInputStream fis=new FileInputStream("e:\\b.mp4");
// FileOutputStream fos=new FileOutputStream("a.mp4");
// //2:调用读写方法
// int len;
// byte[] bys=new byte[1024];
// while((len=fis.read(bys))!=-1){
// fos.write(bys, 0, len);
//
// }
// //3:关流
// fis.close();
// fos.close();
// }
//
// private static void method3() throws IOException {
// //高效字节流一次读写一个字节
// //1:创建数据源和目的地
// BufferedInputStream bis=new BufferedInputStream(new FileInputStream("e:\\b.mp4"));
// BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("a.mp4"));
// //2:调用读写方法
// int ch;
// while((ch=bis.read())!=-1){
// bos.write(ch);
// }
// //3:关流,释放资源
// bis.close();
// bos.close();
// }
//
// private static void method4() throws IOException {
//高效字节流一次读写一个字节数组
//1:创建数据源和目的地
// BufferedInputStream bis=new BufferedInputStream(new FileInputStream("e:\\b.mp4"));
// BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("a.mp4"));
// //2:调用读写方法
// int len;
// byte[] bys=new byte[1024];
// while((len=bis.read(bys))!=-1){
// bos.write(bys, 0, len);
//
// }
// //3:关流
// bis.close();
// bos.close();
// }
}
//
通过观察时间,得出结论。
6:String中的编码和解码问题。(发电报很形象说明这个问题)
编码:把我们能够看懂的字符转换为看不懂的数据
解码:把我们看不懂的数据转换为看得懂的字符
注意:(用什么编码(gbk,utf-8)就应用什么解码)
7:IO流中的编码和解码问题
OutputStreamWriter:把字节输出流转换为字符输出流
InputStreamReader:把字节输入流转换为字符输入流
注意:字符流输入输出流复制的文件是有要求的,简单来 说只要是记事本打开文件的内容你能够看得懂,
就可以用字符流来进行复制,否则不行
具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,因为一个字符等于两个字节。
8: flush()和close()的区别?
A:flush 刷新缓冲区,流对象可以继续
B:close 先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。
9:为什么要引进字符高效流?
答:为了调用newline()方法,来保证它的可移植性。
10:举个例子说明高效流的用处.
package com.study_03;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
//需求:向文件中写入十个中国好,每写一个换一行(高效流输出流特性实现)
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//1:创建高效输出对象
BufferedWriter bw=new BufferedWriter(new FileWriter("d.txt"));
/*2:写操作
* a:写一行
* b:换行
* c:刷新
*/
for(int i=0;i<10;i++){
bw.write("中国好");
bw.newLine();
bw.flush();
}//3:关流
bw.close();
}
}
10:我们也可以举一个案例来测试字符基本流和字符高效流分别读取一个字节和一个字节数组时间的快慢。
这个案例与上面写的那个基本相同,这里不再书写了。
11:I/O综合练习
需求:键盘录入数据并存储
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
分析:
A:定义学生类
B:创建集合,采用TreeSet集合,并按照比较器排序
C:键盘录入5个学生信息并存入集合
D:遍历集合,并把数据写到文本文件
学生类:
package com.study_05;
public class Student {
private String name;
private int math;
private int english;
private int chinese;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public Student(String name, int math, int english, int chinese) {
super();
this.name = name;
this.math = math;
this.english = english;
this.chinese = chinese;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public int sum(){
return math+english+chinese;
}
}
测试类:
package com.study_05;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
/*
* 需求:键盘录入数据并存储
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
分析:
A:定义学生类
B:创建集合,采用TreeSet集合,并按照比较器排序
C:键盘录入5个学生信息并存入集合
D:遍历集合,并把数据写到文本文件
*/
public class Test {
public static void main(String[] args) throws IOException {
//创建一个集合,并写一个比较器
TreeSet<Student> ts=new TreeSet<Student>(new Comparator<Student>(){
@Override
public int compare(Student s1, Student s2) {
int num=s1.sum()-s2.sum();
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});
//键盘录入五个学生信息
for(int i=0;i<5;i++){
Scanner sc=new Scanner(System.in);
System.out.println("请输入学生姓名:");
String name =sc.nextLine();
System.out.println("请输入数学成绩:");
int math=sc.nextInt();
System.out.println("请输入英语成绩:");
int english=sc.nextInt();
System.out.println("请输入语文成绩:");
int chinese=sc.nextInt();
//封装成学生对象,存储到集合
Student s=new Student(name,math,english,chinese);
ts.add(s);
}
System.out.println("数据录入完毕");
//存储到文件
BufferedWriter bw=new BufferedWriter(new FileWriter("score.txt"));
for(Student s:ts){
//把学生信息拼接为字符串
String info=s.getName()+" "+s.getMath()+" "+s.getEnglish()+" "+s.getChinese()+" "+s.sum();
bw.write(info);
bw.newLine();
bw.flush();
}bw.close();
}
}
运行结果:在score中输出学生的成绩信息,并按总成绩排序。
四:设计模式
(1):设计模式概述
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性以及代码的结构更加清晰.
(2):设计模式分类
创建型模式(创建对象的): 单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
行为型模式(对象的功能): 适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
结构型模式(对象的组成): 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、
解释器模式、状态模式、策略模式、职责链模式、访问者模式。
单例设计模式(掌握)
A:单例设计思想
保证类在内存中只有一个对象
B:如何实现类在内存中只有一个对象呢?
构造私有
本身提供一个对象
通过公共的方法让外界访问
C:案例演示: 单例模式之饿汉式
public class SingleInstanceDemo {
/**
* 饿汉式:当这个类一被加载,就在内存中创建了一个对象
*
* 1.保证内存中只有一个对象(构造私有)
* 2.在本类中创建一个该类的对象
* 3.创建一个公共的访问方式给外界获取该对象
*/
private SingleInstanceDemo(){}
private static SingleInstanceDemo instance = new SingleInstanceDemo();
public static SingleInstanceDemo getInstance(){
return instance;
}
}
D:懒汉式
package com.edu_10;
public class SingleInstanceDemo2 {
/**
* 单例设计模式之懒汉式:
* 需要的时候才去创建对象,不需要的时候不创建
*/
private SingleInstanceDemo2(){}
private static SingleInstanceDemo2 instance = null;
public static SingleInstanceDemo2 getInstance(){
if (instance==null) {
instance = new SingleInstanceDemo2();
}
return instance;
}
}