Java学习--异常、多线程和输入输出流

深入理解java:异常、多线程和输入流输出

1 异常:不断抛出异常,直到有一对try..catch..捕捉到异常

清晰区分了业务代码(正常情况下)和异常代码

  1. 基本语法
try{
   //<!-- 可能出异常的代码 -->
   //之后的代码不在执行
}catch(<!-- 异常类型 e -->){
    //<!-- 出异常时要执行的代码 -->
    e.printStackTrace();//显示出异常的逐层调用
    throw e;//在次抛出异常,多次捕获
    //throw new Exception();抛出新异常
    //throw new Exception("something",e);带上内部信息
}catch(/*<!-- 其他类型的异常 e -->*/){

}
  1. 要求明确的语法处理
//<!-- 函数throws自定义异常 -->
//<!-- 自定义异常类 -->
class OpenException extends Throwable{}
class ElseException extends Exception{}
//<!-- 抛出异常的函数 -->
void readFile() throws OpenException,其他类{
    throw new OpenException();//想主动抛出函数得加throws
}
//<!-- 想要调用readFile()就得做好try..catch.. -->
main{
    try{
        readFile();
    }catch(OpenException e){

    }catch(ElseException e){

    }
}


子类覆盖父类函数时:不能抛出比父类函数还多的异常(但可以不抛出或少)
原因:当使用向上造型构造子类时,编译器会以父类检查语法错误。
如果抛出了更多的异常,但是不用catch捕获(编译器通过),那么
在运行时会因为动态绑定而发生危险。
相似:向上造型时,调用覆盖父类的函数(jvm动态绑定),但不能调用
新增加的


子类函数(编译器认为语法错误)
构造函数throws exception:子类必须抛出父类构造所有的异常(可以更多)
原因:子类构造时一定会super(),所以就可能抛父类构造函数所有异常。

3. try-with-resource:语法糖,finally{.close()}
4. 断言:assert 表达式; 不成立时即抛出异常

main{
    //:"sss",带上出错的信息输出
    assert a==5:"计算错误";

}
  1. 测试驱动:JUnit框架
    项目-New-JUnit testcase
    RunAs JUnit..
  2. 程序调试:debug

2 多线程

1 基本概念
  1. 进程:一个活动程序及其相关资源表,进程独享了整个虚拟内存
  2. 线程:单个顺序的流控制,分享了CPU,共享内存。
  3. java从语言级别支持:object类中函数
  4. 线程体:重写run()来使线程执行特定内容
  5. 创建:
//extends class Thread,new a myThread as a thread 
class myThread extends Thread{
    @Override
    public void run(){
        //...
    }
}
//implements interface Runable 
class myTask implements Runnable{
    public void run(){
        //..
    }
}
//use Runnable instance to construct a Thread
Thread thread=new Thread(new mytask());
thread.start();
//匿名类new Thread{...}
//lambda表达式创建Runnable实例
  1. 什么时候使用多线程:两个任务单元明显的并发
    多线程是并发的处理,当一个程序需要同时做(同时画图)或者花
    费大量等待(下载多个文件)时,可以为每个单元建立线程对象(lambda表达式
    很方便)。
2 线程基本控制
  1. 线程状态:创建-start-调度(就绪,阻塞,运行)-中止
  2. 线程结束:默认线程执行完,无限循环时用控制变量break
  3. 设定优先级:setPriority()
  4. Daemon:setDaemon(true),随着普通退出而自动退出
3 同步:语言级别的控制,安全性+顺序性
  1. 对象互斥锁:每个对象上都有一个锁标记
//在线程的run里小心的使用临界资源
//得到该对象的锁,其他线程则得不到该锁了
synchronized(对象){
    //临界区
}
//将同一个类实例当参数构造线程时,线程们使用同一个this
//需要该类的方法为同步方法
public synchronized void push(char c){}
  1. 释放锁,对象.wait();//先释放锁,接着阻塞线程
  2. 通知,对象.notifyAll();//通知其他线程可以从阻塞转就绪,重新开始活动
  3. 当前线程主动wait阻塞自己,让其他线程重启自己(只是就绪不一定能获得锁)
  4. 死锁:相互等待
4 并发API:简化了线程控制,线程安全的类:java.util.concurrent
  1. AtomicInteger:cnt.getAndIncrement();//线程安全的++cnt
  2. 集合:ArrayList/HashMap不安全,Vector及Hashtable是安全的
    新增线程安全的类及它们的优化:
    CopyOnWriteArrayList,CopyOnWriteArraySet:
    ConcurrentHashMap:putIfAbsent(),remove(),replace()
    ArrayBlockingQueue:put(),take()//线程安全且实现了waitnotify
  3. 线程池:每一个线程任务都要new thread实例?
    Executors:用有限的thread执行更多的任务(runnable)
class myTask implements Runnable{}
ExecutorService pool=Executors.newCachedThreadPool();
myTask t1 =new myTask();
myTask t2 =new myTask();
myTask t3 =new myTask();//runnable instance
pool.execute(t1);//execute(Runnable r)==thread.start();
pool.execute(t2);
pool.execute(t3);
pool.shutdown();//关闭线程池
5Timer:java.util.Timer,java.swing.Timer
  1. 底层线程实现:
    Timer–Thread
    TimerTask-Runnable
    Timer.schedule(TimerTask,1000,1000)–Thread.start()
  2. swing.timer:
timer=new Timer(1000,(e)->{setTitle(new java.util.Date().toString())});
  1. 在线程中更新界面draw()会带来不同步?
    交给主线程统一处理,SwingUitlites.invokeLater(lambda);
6stream:对容器collection函数式风格的操作
//并行处理的底层实现
//链式编写:函数式风格filter sorted limit map,执行后还是流
//末端操作:max min count forEach findAny,执行后不再是流
List<Integer> a=new List<>;
//Arrays.stream(a)//数组流化
//a.stream()//普通流
a.parallelStream()//并行流
.filter(i->i>20)
.map(i->i*i)
sorted()
.distinct()
.limit(10)
.max();

3 流,不同类型的输入输出的抽象,所有对流的操作都要try..catch

1 字节流:只能按字节(二进制)处理,标准流/文件流
//标准输入字节流InputStream 
byte[] buffer= new byte[1024];
//标准输入流读字节到buffer.按字节计算长度
int len=System.in.read(buffer);
//注意String是按照字符数计算长度 
String =new String(buffer,0,len);
//read();
//mark();
//reset();

//文件字节流,内存字节内容-->二进制文件
FileOutputStream out =new FileOutputStream("a.dat");
out.write(buffer);
2 过滤器:包装字节流对象,使之能够处理基本数据类型
//写
//基本类型内容-->二进制文件
DataOutputStream out =new DataOutputStream(
            new BufferOutputStream(
                new FileOutputStream("a.dat")));
int i=12313;                
out.writeInt(i);//输出文件仍是i的16进制形式
//读
//二进制文件-->基本类型
DataInputStream in =new DataInputStream(
            new BufferInputStream(
                new FileOutInStream("a.dat")));
int j=in.readInt();
3 文本数据的字符流:Reader/Writer

read()是阻塞的,所以读网页(等待时间很长时)用线程方式并发

//可适应不同编码
//写
//内存-->字符流-->文本文件
PrintWriter out = new PrintWriter(
            new BufferedWriter(
                new OutPutStreamWriter(
                    new FileOutputStream("a.txt"))));
int i=123321;
out.println(i);//文件里就是123321
//读
//文本文件-->字符流 -->内存
BufferedReader=new BufferedReader(
                new InPutStreamReader(//字节流转成reader,指定解码方式
                    new FileInputStream("a.txt"),"utf8")));

String line;
while((line=in.readLine()!=null)){
    System.out.println(line);
    //getLineNumber();
}
//格式化输出
//format()
System.out.printf()
//在reader或者InputStream上建立Scanner,方便读入数据
Scanner in= new Scanner(System.in);
in.nextInt();
4 总结:

二进制读写->字节流
字符的读写—> 文本处理->Reader包装
|-> 数据处理->Scanner包装

5 对象串行化
//Serializable只是个接口标记,什么都不用实现
class student implements Serializable{}

main{
    student s1=new student();
    //输出文件里是二进制
    ObjectOutputStream out =new ObjectOutputStream(
            new FileOutputStream("obj.dat")) ;
    out.writeObject(s1)
    out.close();
    ObjectInputStream in =new ObjectInputStream(
            new FileInputStream("obj.dat"));
    student s2=(student) in.readObject();
    in.close();
    //s2是新创建的对象(s1,s2引用的实体不同,内容相同)
}
6 举个例子:背单词(jase项目)
  1. 界面:JFrame,init()放置标签资源,start()开始执行
  2. 读:线程,Reader读文件到List使用字符串处理函数处理文本
  3. 容器:存储内容
  4. 显示:Timer控制显示到标签
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值