目录
(2)Objects中的requireNonNull()方法判断传递的参数是否为null
a)第一种方式:通过throws抛出异常(异常后面的代码不会被执行)
b)第二种方式:通过 try...catch 捕获异常(异常后面的代码会继续执行)
(7)finally代码块中尽量避免出现return语句,因为会永远返回finally中的结果
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
(2)创建多线程程序第二种方法:实现Runnable接口(常用方法)
a)创建一个Runnable接口的实现类,重写Runnable接口中的run方法,设置线程任务
b)创建Runnable接口的实现类对象,并创建Thread类对象,将实现类对象作为参数传递给Thread类对象
(4)使用Lambda表达式的方式创建线程(最简单方法 JDK8特有)
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
(6)使用Thread类中的静态方法currentThread()方法返回正在执行的线程,再使用getName()方法返回线程的名称
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
b)创建Thread类的子类对象,设置线程的名称,再用子类对象调用start()方法,开启新的线程
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
b)创建Thread类的子类对象,设置线程的名称,再用子类对象调用start()方法,开启新的线程
(9)使用sleep()方法使当前正在执行的线程暂停指定的毫秒数(模拟秒表)
1、Exception
(1)throw 关键字,自定义抛出异常的内容
package com.itheima.demo01Exception;
/*
throw关键字:作用:在指定的方法中抛出指定的异常
使用格式:throw new xxxException("异常产生的原因");
注意事项:
1.throw关键字必须写在方法的内部
2.throw关键字后边new的对象必须是Exception或者Exception的子类对象
3.throw关键字抛出指定的异常对象,我们就必须处理这个异常对象
throw关键字后边创建的是RuntimeException或者是RuntimeException的子类对象,我们可以不用处理,默认交给JVM处理(打印)
throw关键字后边创建的是编译异常(写代码的时候报错),我们就必须处理这个异常,要么throws,要么try...catch
* */
public class Demo02Throw {
public static void main(String[] args) {
// int[] arr = null;
// System.out.println(getElement(arr, 0));
int[] arr1 = {1, 2, 3};
System.out.println(getElement(arr1, 3));
}
/*
定义一个方法,获取数组指定索引处的元素
以后(工作中)我们必须首先对方法传递过来的参数进行合法性校验
如果参数不合法,那么我们就必须使用抛出异常的方式,告知方法的调用者,传递的参数有问题
* */
public static int getElement(int[] arr, int index) {
if (arr == null) {//对传递过来的数组进行合法性校验
throw new NullPointerException("传递的数组的值是null");
}
if (index < 0 || index > arr.length - 1) {//对传递过来的索引进行合法性校验
throw new ArrayIndexOutOfBoundsException("传递的索引超出了数组的使用范围");
}
return arr[index];
}
}
(2)Objects中的requireNonNull()方法判断传递的参数是否为null
package com.itheima.demo01Exception;
import java.util.Objects;
public class Demo03Objects {
public static void main(String[] args) {
method(null);
}
public static void method(Object obj){
//对传递过来的参数进行合法性判断,判断是否为null
//自己写判断语句
/*if (obj==null){
throw new NullPointerException("传递的对象的值是null");
}*/
//使用Objects中的requireNonNull()方法判断
//Objects.requireNonNull(obj);
//使用Objects中的requireNonNull()方法判断并打印指定内容
Objects.requireNonNull(obj,"传递的对象的值是null");
}
}
(3)处理异常的方式
a)第一种方式:通过throws抛出异常(异常后面的代码不会被执行)
package com.itheima.demo01Exception;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo04Throws {
public static void main(String[] args) throws IOException {
readFile("c:\\a.txt");
}
//定义一个方法,对传递的文件路径进行合法性判断
public static void readFile(String fileName) throws IOException {
//如果路径不是"c:\\a.txt",那么我们就抛出文件找不到异常,告知方法的调用者
if (!fileName.equals("c:\\a.txt")) {
throw new FileNotFoundException("传递的文件路径不是c:\\a.txt");
}
//如果传递的路径不是.txt结尾,那么我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
if (!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对!");
}
System.out.println("路径没有问题,读取文件!");
}
}
b)第二种方式:通过 try...catch 捕获异常(异常后面的代码会继续执行)
package com.itheima.demo01Exception;
import java.io.IOException;
public class Demo05TryCatch {
public static void main(String[] args) {
try {
//可能产生异常的代码
//readFile("c:\\a.tx");
readFile("c:\\a.txt");
} catch (IOException e) {//try中抛出什么异常对象,catch中就定义什么异常变量,用来接收这个异常对象
//异常的处理逻辑
System.out.println("传递的文件的后缀名不是.txt");
}
System.out.println("后续代码...");
}
public static void readFile(String fileName) throws IOException {
//如果传递的路径不是.txt结尾,那么我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
if (!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对!");
}
System.out.println("路径没有问题,读取文件!");
}
}
(4)Throwable类中3个异常处理的方法
package com.itheima.demo01Exception;
import java.io.IOException;
public class Demo05TryCatch {
public static void main(String[] args) {
try {
//可能产生异常的代码
readFile("c:\\a.tx");
} catch (IOException e) {//try中抛出什么异常对象,catch中就定义什么异常变量,用来接收这个异常对象
//异常的处理逻辑
//System.out.println("传递的文件的后缀名不是.txt");
//System.out.println(e.getMessage());//文件的后缀名不对!
//System.out.println(e);//java.io.IOException: 文件的后缀名不对!
//System.out.println(e.toString());//java.io.IOException: 文件的后缀名不对!
e.printStackTrace();//打印的异常信息最全面
}
System.out.println("后续代码...");
}
public static void readFile(String fileName) throws IOException {
//如果传递的路径不是.txt结尾,那么我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
if (!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对!");
}
System.out.println("路径没有问题,读取文件!");
}
}
(5)finally代码块
格式:
try{
//可能产生异常的代码
}catch {
//异常的处理逻辑
}finally {
//无论是否出现异常,都会执行
}
package com.itheima.demo01Exception;
import java.io.IOException;
public class Demo06TryCatchFinally {
public static void main(String[] args) {
try {
readFile("c:\\a.tx");
} catch (IOException e) {
e.printStackTrace();
}finally {
//无论是否出现异常,都会执行
System.out.println("资源释放");
}
}
public static void readFile(String fileName) throws IOException {
//如果传递的路径不是.txt结尾,那么我们就抛出IO异常对象,告知方法的调用者,文件的后缀名不对
if (!fileName.endsWith(".txt")){
throw new IOException("文件的后缀名不对!");
}
System.out.println("路径没有问题,读取文件!");
}
}
(6)多个异常如果处理?
a)多个异常分别处理
package com.itheima.demo01Exception;
import java.util.List;
public class Demo07SomeException {
public static void main(String[] args) {
try {
int[] arr = null;
System.out.println(arr[0]);//NullPointerException
} catch (NullPointerException e) {
System.out.println(e);
}
try {
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));//ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("后续代码会继续执行...");
}
}
打印结果:
java.lang.NullPointerException
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
后续代码会继续执行...
b)多个异常一次捕获,多次处理
package com.itheima.demo01Exception;
import java.util.List;
//一个try多个catch注意事项:
//catch里边定义的异常变量如果有子父类关系,那么子类的异常变量必须写在上面,否则会报错
public class Demo07SomeException {
public static void main(String[] args) {
try {
int[] arr = null;
System.out.println(arr[0]);//NullPointerException
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));//ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
} catch (NullPointerException e) {
System.out.println(e);
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println(e);
}
System.out.println("后续代码会继续执行...");
}
}
打印结果:
java.lang.NullPointerException
后续代码会继续执行...
c)多个异常一次捕获,一次处理
package com.itheima.demo01Exception;
import java.util.List;
public class Demo07SomeException {
public static void main(String[] args) {
//多个异常,一次捕获,一次处理
try {
int[] arr = null;
System.out.println(arr[0]);//java.lang.NullPointerException
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));//java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
} catch (Exception e) {
System.out.println(e);
}
System.out.println("后续代码会继续执行...");
}
}
打印结果:
java.lang.NullPointerException
后续代码会继续执行...
(7)finally代码块中尽量避免出现return语句,因为会永远返回finally中的结果
package com.itheima.demo01Exception;
//如果finally中有return语句,永远返回finally中的结果,应避免该情况
public class Demo08ReturnInFinally {
public static void main(String[] args) {
System.out.println(getA());
}
//定义一个方法,返回变量a的值
public static int getA() {
int a = 10;
try {
return a;
} catch (Exception e) {
System.out.println(e);
} finally {
//一定会执行的代码
a = 100;
return a;
}
}
}
打印结果:
100
(8)子父类异常
package com.itheima.demo01Exception;
/*
子父类的异常:
-如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者是父类异常的子类或者不抛出异常
-父类方法没有抛出异常,子类重写父类该方法时也不可以抛出异常,此时子类产生该异常,只能捕获处理,不能声明抛出
注意:
父类异常是什么样,子类异常就是什么样
* */
public class Fu {
public void show01() throws NullPointerException, ClassCastException {}
public void show02() throws IndexOutOfBoundsException {}
public void show03() throws IndexOutOfBoundsException {}
public void show04() {}
}
class Zi extends Fu {
//子类重写父类方法时,抛出和父类相同的异常
public void show01() throws NullPointerException, ClassCastException {}
//子类重写父类方法时,抛出父类异常的子类
public void show02() throws ArrayIndexOutOfBoundsException {}
//子类重写父类方法时,不抛出异常
public void show03() {}
//父类方法没有抛出异常,子类重写父类该方法时也不可以抛出异常
// public void show04() throws Exception{}//错误写法,不能抛出异常
// 此时子类产生该异常,只能捕获处理,不能声明抛出
public void show04() {
try {
throw new Exception("编译期异常");
} catch (Exception e) {
e.printStackTrace();
}
}
}
(9)自定义异常类
package com.itheima.demo02MyException;
/*
自定义异常类:
格式:
public class XXXException extends Exception | RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
注意:
1.自定义异常类一般都是以Exception结尾,说明该类是一个异常类
2.自定义异常类,必须得继承Exception或者RuntimeException
继承Exception:那么自定义的异常类就是一个编译器异常类,如果方法内部抛出了编译器异常,就必须处理这个异常,要么throws,要么try...catch
继承RuntimeException:那么自定义的异常类就是一个运行期异常类,无需处理,交给JVM处理(中断处理)
* */
public class RegisterException extends Exception {
//添加一个空参数的构造方法
public RegisterException() {
super();
}
//添加一个带异常信息的构造方法
public RegisterException(String message) {
super(message);
}
}
2、Thread(线程)
(1)创建多线程程序第一种方法:创建Thread类的子类
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
package com.itheima.demo03Thread;
//1.创建一个Thread类的子类
public class MyThread extends Thread {
//2.在Thread类的子类中重写Thread类中的run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("run:" + i);
}
}
}
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
package com.itheima.demo03Thread;
public class Demo01Thread {
public static void main(String[] args) {
//创建Thread类的子类对象
MyThread thread = new MyThread();
//调用Thread类中的start()方法,开启新的线程,执行run方法
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println("main:"+i);
}
}
}
打印结果:
run:0
run:1
main:0
run:2
main:1
run:3
main:2
main:3
main:4
main:5
main:6
main:7
main:8
run:4
main:9
run:5
run:6
run:7
run:8
run:9
(2)创建多线程程序第二种方法:实现Runnable接口(常用方法)
实现Runnable接口创建多线程的好处:
①避免了单继承的局限性:
Ⅰ一个类只能继承一个类(一个人只能有一个爹),类继承了Thread类就不能继承其他的类
Ⅱ实现了Runnable接口,还可以继承其他的类,实现其他接口
②增强了程序的扩展性,降低了程序的耦合性
实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
实现类中,重写了run方法:用来设置线程任务
创建Thread类对象,调用start方法:用来开启新线程
a)创建一个Runnable接口的实现类,重写Runnable接口中的run方法,设置线程任务
package com.itheima.demo03Thread;
//创建一个Runnable接口的实现类
public class RunnableImpl implements Runnable {
//在实现类中重写Runnable接口的run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
b)创建Runnable接口的实现类对象,并创建Thread类对象,将实现类对象作为参数传递给Thread类对象
package com.itheima.demo03Thread;
public class Demo05Runnable {
public static void main(String[] args) {
//创建一个Runnable接口的实现类对象
RunnableImpl runnable = new RunnableImpl();
//创建Thread类对象,构造方法中传递Runnable接口的实现了对象
Thread thread = new Thread(runnable);
//调用Thread类中的start方法,开启新的线程执行run方法
thread.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
打印结果:
Thread-0:0
main:0
Thread-0:1
main:1
Thread-0:2
main:2
main:3
main:4
main:5
main:6
main:7
main:8
Thread-0:3
main:9
Thread-0:4
Thread-0:5
Thread-0:6
Thread-0:7
Thread-0:8
Thread-0:9
(3)使用匿名内部类的方式创建线程(常用简单方法)
匿名内部类作用:简化代码
①把子类继承父类、重写父类的方法、创建子类对象合成一步完成
②把实现类、实现类接口、重写接口中的方法、创建实现类对象合成一步完成
③匿名内部类的最终产物:子类/实现类对象,而这个类没有名字
package com.itheima.demo03Thread;
public class Demo06InnerClassThread {
public static void main(String[] args) {
//线程的父类是Thread
new Thread(){
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()+"小强");
}
}
}.start();
//线程的接口Runnable
Runnable runnable = new Runnable() {
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "旺财");
}
}
};
new Thread(runnable).start();
//简化接口的方式
new Thread(new Runnable() {
//重写run方法,设置线程任务
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + "笨笨");
}
}
}).start();
}
}
打印结果:
Thread-1旺财
Thread-1旺财
Thread-0小强
Thread-1旺财
Thread-2笨笨
Thread-2笨笨
Thread-2笨笨
Thread-0小强
Thread-0小强
(4)使用Lambda表达式的方式创建线程(最简单方法 JDK8特有)
package com.itheima.demo03Lambda;
/*
Lambda表达式的标准格式:
由三部分组成:
a.一些参数
b.一个箭头
c.一段代码
格式:
(参数列表) -> {一些重写方法的代码};
解释说明格式:
():接口中抽象方法的参数列表,没有参数,就空着;有参数就写出参数,多个参数使用逗号分隔
->:传递的意思,把参数传递给方法体{}
{}:重写接口的抽象方法的方法体
*/
public class Demo02Lambda {
public static void main(String[] args) {
//使用匿名内部类的方式,实现多线程
new Thread(new Runnable(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 新线程创建了");
}
}).start();
//使用Lambda表达式,实现多线程
new Thread(()->{
System.out.println(Thread.currentThread().getName()+" 新线程创建了");
}
).start();
//优化省略Lambda
new Thread(()->System.out.println(Thread.currentThread().getName()+" 新线程创建了")).start();
}
}
(5)使用getName()方法返回线程的名称
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
package com.itheima.demo03Thread;
//定义一个Thread类的子类
public class GetThreadName extends Thread {
//重写Thread类中的run方法,设置线程任务
@Override
public void run() {
//获取线程名称
String name = getName();
System.out.println(name);
}
}
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
package com.itheima.demo03Thread;
//线程的名称:主线程:main
// 新线程:Thread-0,Thread-1,Thread-2...
public class Demo02GetThreadName {
public static void main(String[] args) {
//创建Thread类的子类对象
GetThreadName name = new GetThreadName();
//调用start方法,开启新线程,执行run方法
name.start();
new GetThreadName().start();
new GetThreadName().start();
}
}
打印结果:
Thread-1
Thread-0
Thread-2
(6)使用Thread类中的静态方法currentThread()方法返回正在执行的线程,再使用getName()方法返回线程的名称
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
package com.itheima.demo03Thread;
//定义一个Thread类的子类
public class GetThreadName extends Thread {
//重写Thread类中的run方法,设置线程任务
@Override
public void run() {
//获取当前正在执行的线程
Thread thread = Thread.currentThread();
//System.out.println(thread);//Thread[Thread-0,5,main]
//获取正在执行的线程的名称
String name = thread.getName();
System.out.println(name);//Thread-0
//简洁方式(链式编程)
System.out.println(Thread.currentThread().getName());
}
}
b)创建Thread类的子类对象,用子类对象调用start()方法,开启新的线程
package com.itheima.demo03Thread;
//线程的名称:主线程:main
// 新线程:Thread-0,Thread-1,Thread-2...
public class Demo02GetThreadName {
public static void main(String[] args) {
//创建Thread类的子类对象
GetThreadName name = new GetThreadName();
//调用start方法,开启新线程,执行run方法
name.start();
new GetThreadName().start();
new GetThreadName().start();
//获取主线程的名称
System.out.println(Thread.currentThread().getName());
}
}
打印结果:
Thread-0
Thread-2
Thread-1
main
(7)使用setName()方法设置线程的名称
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
package com.itheima.demo03Thread;
public class SetThreadName extends Thread {
@Override
public void run() {
//获取线程的名称
System.out.println(Thread.currentThread().getName());
}
}
b)创建Thread类的子类对象,设置线程的名称,再用子类对象调用start()方法,开启新的线程
package com.itheima.demo03Thread;
public class Demo03SetThreadName {
public static void main(String[] args) {
//开启多线程
SetThreadName setName = new SetThreadName();
//给线程起一个名称
setName.setName("小强");
setName.start();
}
}
打印结果:
小强
(8)使用带参数的构造方法设置线程的名称
a)首先定义一个Thread类的子类,重写Thread类中的run方法,设置线程任务
package com.itheima.demo03Thread;
public class SetThreadName extends Thread {
//使用带参数的构造方法
public SetThreadName(){}
public SetThreadName(String name){
super(name);//把线程名称传递给父类,让父类(Thread)给子线程起一个名字
}
@Override
public void run() {
//获取线程的名称
System.out.println(Thread.currentThread().getName());
}
}
b)创建Thread类的子类对象,设置线程的名称,再用子类对象调用start()方法,开启新的线程
package com.itheima.demo03Thread;
public class Demo03SetThreadName {
public static void main(String[] args) {
new SetThreadName("旺财").start();
}
}
打印结果:
旺财
(9)使用sleep()方法使当前正在执行的线程暂停指定的毫秒数(模拟秒表)
package com.itheima.demo03Thread;
public class Demo04Sleep {
public static void main(String[] args) {
//模拟秒表
for (int i = 1; i <= 60; i++) {
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
打印结果:
1
2
3
...