《Java自学180天笔记》
异常分类
package demo3;/*java.lang.Throwable:类是Java语言中所有错误或异常的超类。 Exception:编译期异常,进行编译(写代码)java程序出现的问题 RuntimeException:运行期异常,java程序运行过程中出现的问题 异常就相当于程序得了一个小毛病,把异常处理掉,程序可以继续执行 Error:错误 错误就相当于程序得了一个无法治愈的毛病,必须修改源代码,程序才能继续执行 */public class DemoException { public static void main(String[] args) { }}
异常的产生过程解析
throw关键字
package demo3;/*throw关键字作用: 可以使用throw关键字在指定的方法中抛出指定的异常使用格式: throw new xxxException("异常产生的原因");注意: 1.throw关键字必须写在方法的内部 2.throw关键字后边new的对象必须是Exception或者Exception的子类对象 3.throw关键字抛出指定异常对象,我们就必须处理这个异常对象 throw关键字后面创建的是RuntimeException或者RuntimeException的子类对象,我们可以不处理, 默认交给JVM处理(打印异常对象,中断程序) throw关键字后面创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws, 要么try...catch */public class DemoThrow { public static void main(String[] args) { }}
throws关键字_异常处理的第一种方式,交给别人处理
package demo3;import java.io.FileNotFoundException;import java.io.IOException;/*throws关键字:异常处理的第一种方式,交给别人处理作用: 当方法内部抛出异常对象的时候,那么我们就必须处理这个异常对象 可以使用throws关键字处理异常对象,会把异常对象声明抛出给方法的调用者处理 (自己不处理,给别人处理),最终交给JVM处理-->中断处理使用格式:在方法声明时使用 修饰符 返回值类型 方法名(参数列表)throws AAAException,BBBException...{ throw new AAAException("产生原因") throw new BBBException("产生原因") ... }注意: 1.throws关键字必须写在方法声明处 2.throws关键字后边声明的异常必须是Exception或者Exception的子类 3.方法内部如果抛出了多个异常对象,那么throws后边必须也声明多个异常 如果抛出多个异常对象有父子关系,那么 直接声明父类异常即可 4.调用一个声明抛出异常的方法,我们就必须的处理声明的异常 要么继续使用throws声明抛出,交给方法的调用者算是,最终交给JVM 要么try...catch自己处理异常 */public class DemoThrows { /* FileNotFoundException extends IOException extends Exception 如果抛出的多个异常对象有父子类关系,那么直接声明父类异常即可。 */ public static void main(String[] args) throws FileNotFoundException,IOException { readFile("c:\\a.txt"); } /* 定义一个谅,对传递的方便路径进行合法性判断 如果路径不是"c:\\a.txt",那么我们就抛出文件找不到异常对象,告知方法的调用者 注意: FileNotFoundException是编译异常,抛出了编译异常,就必须处理这个异常 可以使用throws继续声明抛出FileNotFoundException这个异常对象,让方法的调用者处理 */ public static void readFile(String fileName) throws FileNotFoundException,IOException { if(!fileName.equals("c:\\a.txt")){ throw new IOException("文件的后缀名不对"); } /* 如果传递的路径,不是.txt结尾 那么 我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对 */ if(!fileName.endsWith(".txt")){ throw new FileNotFoundException("传递的文件路径不是c:\\a.txt"); } System.out.println("路径没有问题,读取文件"); }}
throws关键字_异常处理的第一种方式,自己处理异常
package demo3;/*try...catch:异常处理的第二种方式,自己处理异常格式: try{ 可能产生异常的代码 }catch(定义一个异常的变量,用来接收try中抛出的异常对象){ 异常处理逻辑,异常对象之后,怎么处理异常对象 一般在工作中,会把异常的信息记录在一个日志中 } ... catch(异常类名 变量名){ }注意: 1.try中可能会抛出多个异常对象,那么就可以使用多个catch来处理这些异常对象 2.如果try中产生了异常,那么就会执行catch中异常处理逻辑,执行完毕catch中处理逻辑, 继续执行try...catch之后的代码 如果try中没有产生异常,那么就不会执行catch中异常的处理逻辑,执行完try中的代码,继续执行try...catch之后的代码 */public class DemoTryCatch {}
多异常的捕获处理
package demo3;import java.util.List;/*多个异常使用捕获又该如何处理呢?1.多个异常分别处理。2.多个异常一次捕获,多次处理。3.多个异常一次捕获,一次处理。*/public class Demo01Exception {}
自定义异常类
package demo4;/*自定义异常类: java提供的异常类,不够我们使用,需要自己定义一些异常类格式: public class xxxException extends Exception | RuntimeException{ 添加一个空参数构造方法 添加一个带异常信息的构造方法 }注意: 1.自定义异常类一般都是以Exeption结尾,说明该类是一个异常类 2.自定义异常类,必须的继承Exception或者RuntimeException 继承Exception:那么自定义的异常类就是一个编译期异常,如果方法内部抛出了编译期异常, 就必须处理这个异常,要么throws,要么try...catch 继承RuntimeException:那么自定义的异常类就是一个运行期异常,无需处理,交给虚拟机处理(中断处理) */public class RegisterException extends Exception { //添加一个空参数构造方法 public RegisterException(){ super(); } /*添加一个带异常信息的构造方法查看源码发现,所有的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理这个异常信息 */ public RegisterException(String message){ super(message); }}
自定义异常类练习
package demo4;import java.util.Scanner;/*要求:我们模拟注册操作,如果用户名已存在,则抛出异常并提示:亲,该用户名已被注册分析: 1.使用数组保存已注册过的用户名(数据库) 2.使用Scanner获取用户输入的注册用户名(前端,页面) 3.定义一个方法,对用户输入的注册名进行判断 遍历存储已注册过的用户名数组,获取每一个用户名 使用获取到的用户名和用户输入的用户名比较 true: 用户名已存在,抛出RegisterException异常,告知用户“亲,该用户名已被注册”; false: 继续遍历比较 如果循环线束了,还没有找到重复的用户名,提示用户“恭喜您,注册成功”; */public class DemoRegisterException { //1.使用数组保存已注册过的用户名(数据库) static String[] usernames = {"聂卫平","古力","常昊"}; public static void main(String[] args) throws RegisterException { //2.使用Scanner获取用户输入的注册用户名(前端,页面) Scanner sc = new Scanner(System.in); System.out.println("请输入您要注册的用户名"); String username = sc.next(); checkUsername(username); } //3.定义一个方法,对用户输入的注册名进行判断 public static void checkUsername(String username) throws RegisterException { //遍历存储已注册过的用户名数组,获取每一个用户名 for(String name:usernames){ //使用获取到的用户名和用户输入的用户名比较 if(name.equals(username)){ //true:用户名已存在,抛出RegisterException异常,告知用户“亲,该用户名已被注册”; throw new RegisterException("亲,该用户名已被注册"); } } System.out.println("恭喜您,注册成功"); }}
并发与并行
进程概念
线程概念
线程是进程中的一个执行单元,负责当前进行中程序的执行,一个进行中至少有一个线程。一个进程中是可以有多个线程,这个应用程序也可以称之为多线程程序。
线程调度
分时调度
所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间
抢占式调度
优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。
主线程
package demo4;/*主线程:执行主(main)方法的线程单线程程序:java程序中只有一个线程执行从main方法开始,从上到下依次执行 */public class DemoMainThread { public static void main(String[] args) { Person p1 = new Person("小强"); p1.run(); Person p2 = new Person("旺财"); p2.run(); }}
创建多线程程序的第一种方式
package demo4;/*创建多线程程序的第一种方式:创建Thread类的子类java.lang.Thread类:是描述线程的类,我们想要实现多线程程序,就必须继承Thread类实现步骤: 1.创建一个Thread类的子类 2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?) 3.创建Thread类的子类对象 4.调用Thread类中的方法,开启新的线程,执行run方法 void start() 使该线程开始执行;Java虚拟机调用该线程的run方法。 结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其run方法) 多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。java程序属于抢占式调度,哪个线程优先级高,哪个线程优先执行;同一个优先级,随机选择一个执行 */public class Demo01Thread { public static void main(String[] args) { //3.创建Thread类的子类对象 MyThread mt = new MyThread(); //4.调用Thread类中的方法,开启新的线程,执行run方法 mt.start(); for (int i = 0; i < 20; i++) { System.out.println("main:"+i); } }}
package demo4;//1.创建一个Thread类的子类public class MyThread extends Thread { //2.在Thread类的子类中重写Thread类中的run方法,设置线程任务(开启线程要做什么?) @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("run:"+i); } }}