🧑🎓 个人主页:花棉袄
📖 本章内容:【基础二:Java进阶】
✍🏻 版权: 本文由【花棉袄】原创💝在CSDN首发💝需要转载请联系博主

🌳 IO流介绍
流的本质是数据传输🌳 IO流的分类
🌳 IO流的使用场景
🌳 File类介绍
🌳 File类的构造方法

public class FileDemo01 {
public static void main(String[] args) {
//File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File f1 = new File("E:\\itcast\\java.txt");
System.out.println(f1);
//File(String parent, String child):从父路径名字符串和子路径名字符串创建新的File实例。
File f2 = new File("E:\\itcast", "java.txt");
System.out.println(f2);
//File(File parent, String child):从父抽象路径名和子路径名字符串创建新的 File实例。
File f3 = new File("E:\\itcast");
File f4 = new File(f3, "java.txt");
System.out.println(f4);
}
}
🌳 File类创建功能

public class FileDemo02 {
public static void main(String[] args) throws IOException {
//需求1:我要在E:\\itcast目录下创建一个文件java.txt
File f1 = new File("E:\\itcast\\java.txt");
System.out.println(f1.createNewFile());
System.out.println("--------");
//需求2:我要在E:\\itcast目录下创建一个目录JavaSE
File f2 = new File("E:\\itcast\\JavaSE");
System.out.println(f2.mkdir());
System.out.println("--------");
//需求3:我要在E:\\itcast目录下创建一个多级目录JavaWEB\\HTML
File f3 = new File("E:\\itcast\\JavaWEB\\HTML");
System.out.println(f3.mkdirs());
System.out.println("--------");
//需求4:我要在E:\\itcast目录下创建一个文件javase.txt
File f4 = new File("E:\\itcast\\javase.txt");
System.out.println(f4.createNewFile());
}
}
🌳 File类判断功能

public class FileDemo03 {
public static void main(String[] args) {
//创建一个File对象
File f = new File("E:\\itcast\\java.txt");
// public boolean isDirectory():测试此抽象路径名表示的File是否为目录
// public boolean isFile():测试此抽象路径名表示的File是否为文件
// public boolean exists():测试此抽象路径名表示的File是否存在
System.out.println(f.isDirectory());
System.out.println(f.isFile());
System.out.println(f.exists());
}
}
🌳 File类获取功能

public class FileDemo04 {
public static void main(String[] args) {
//创建一个File对象
File f = new File("E:\\itcast\\java.txt");
// public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
System.out.println(f.getAbsolutePath());
// public String getPath():将此抽象路径名转换为路径名字符串
System.out.println(f.getPath());
// public String getName():返回由此抽象路径名表示的文件或目录的名称
System.out.println(f.getName());
System.out.println("--------");
// public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
File f2 = new File("E:\\itcast");
String[] strArray = f2.list();
// public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
for (String str : strArray) {
System.out.println(str);
}
System.out.println("--------");
File[] fileArray = f2.listFiles();
for (File file : fileArray) {
if (file.isFile()) {
System.out.println(file.getName());
}
}
System.out.println("--------");
}
}
🌳 File类删除功能

public class FileDemo03 {
public static void main(String[] args) throws IOException {
//需求1:在当前模块目录下创建java.txt文件
File f1 = new File("myFile\\java.txt");
//需求2:删除当前模块目录下的java.txt文件
System.out.println(f1.delete());
System.out.println("--------");
//需求3:在当前模块目录下创建itcast目录
File f2 = new File("myFile\\itcast");
//需求4:删除当前模块目录下的itcast目录
System.out.println(f2.delete());
System.out.println("--------");
//需求5:在当前模块下创建一个目录itcast,然后在该目录下创建一个文件java.txt
File f3 = new File("myFile\\itcast");
File f4 = new File("myFile\\itcast\\java.txt");
//需求6:删除当前模块下的目录itcast
System.out.println(f4.delete());
System.out.println(f3.delete());
}
}
🌳 绝对路径和相对路径的区别
绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件–例如:E:\itcast\java.txt相对路径:必须使用取自其他路径名的信息进行解释–例如:myFile\java.txt🌳 字节流抽象基类
🌳 字节输出流
🌳 使用字节输出流写数据的步骤
创建字节输出流对象:(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)写数据方法释放资源:(关闭此文件输出流并释放与此流相关联的任何系统资源)public class FileOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("E:\\Code\\springcloud\\itcast\\java.txt");
fileOutputStream.write(99);
fileOutputStream.close();
}
}
🌳 字节流写数据的三种方式

public class FileOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("E:\\Code\\springcloud\\itcast\\java.txt");
fileOutputStream.write(97);
String str = " -Hello world ";
// byte[] bys = {97, 98, 99, 100, 101};
//byte[] getBytes():返回字符串对应的字节数组
byte[] bys = "-abcde".getBytes();
byte[] bytes = str.getBytes();
fileOutputStream.write(bytes);
//void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
fileOutputStream.write(bys,1,3);
fileOutputStream.close();
}
}
🌳 字节流写数据如何实现换行
windows:\r\n 🧡 linux:\n 🧡 mac:\r🌳 字节流写数据如何实现追加写入
public FileOutputStream(String name,boolean append)public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("E:\\Code\\springcloud\\itcast\\java.txt", true);
String str = " -Hello world ";
// byte[] bys = {97, 98, 99, 100, 101};
//byte[] getBytes():返回字符串对应的字节数组
byte[] bys = "-abcde".getBytes();
byte[] bytes = str.getBytes();
fileOutputStream.write(bytes);
//void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
fileOutputStream.write(bys,1,3);
fileOutputStream.close();
}
}
🌳 字节流写数据加异常处理
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
public class FileOutputStreamDemo04 {
public static void main(String[] args) {
//加入finally来实现释放资源
FileOutputStream fos = null;
try {
fos = new FileOutputStream("myByteStream\\fos.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
🌳 字节流读数据:
一次读一个字节数据
🌳 字节输入流读取数据的步骤
public class FileInputStreamDemo01 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("E:\\Code\\springcloud\\itcast\\java.txt");;
int by;
/*
fis.read():读数据
by=fis.read():把读取到的数据赋值给by
by != -1:判断读取到的数据是否是-1
*/
while ((by=fileInputStream.read())!=-1) {
System.out.print((char)by);
}
//释放资源
fileInputStream.close();
}
}
🌳 字节流读数据:
一次读一个字节数组数据
public class FileInputStreamDemo02 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("E:\\Code\\springcloud\\itcast\\java.txt");
byte[] bytes = new byte[1024];
int len;
while ((len = fileInputStream.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
}
🌳 字节流复制图片
public class CopyJpgDemo {
public static void main(String[] args) throws IOException {
//根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream("C:\\Users\\miram\\Pictures\\IDEA\\1.png");
//根据目的地创建字节输出流对象
FileOutputStream fos = new FileOutputStream("E:\\Code\\springcloud\\itcast\\java\\cc\\aa.png");
//读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
//释放资源
fos.close();
fis.close();
}
}
🌳 构造方法

public class BufferStreamDemo {
public static void main(String[] args) throws IOException {
//字节缓冲输出流:BufferedOutputStream(OutputStream out)
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("E:\\Code\\springcloud\\itcast\\bos.txt"));
//写数据
bos.write("hello\r\n".getBytes());
bos.write("world\r\n".getBytes());
//释放资源
bos.close();
//字节缓冲输入流:BufferedInputStream(InputStream in)
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("E:\\Code\\springcloud\\itcast\\bos.txt"));
//一次读取一个字节数组数据
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
//释放资源
bis.close();
}
}
🌳 字节流复制视频
public class CopyAviDemo {
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) + "毫秒");
}
//字节缓冲流一次读写一个字节数组
public static void method4() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("E:\\itcast\\字节流复制图片.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("myByteStream\\字节流复制图片.avi"));
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
}
//字节缓冲流一次读写一个字节
public static void method3() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new
FileInputStream("E:\\itcast\\字节流复制图片.avi"));
BufferedOutputStream bos = new BufferedOutputStream(new
FileOutputStream("myByteStream\\字节流复制图片.avi"));
int by;
while ((by = bis.read()) != -1) {
bos.write(by);
}
bos.close();
bis.close();
}
//基本字节流一次读写一个字节数组
public static void method2() throws IOException {
//E:\\itcast\\字节流复制图片.avi
//模块目录下的 字节流复制图片.avi
FileInputStream fis = new FileInputStream("E:\\itcast\\字节流复制图片.avi");
FileOutputStream fos = new FileOutputStream("myByteStream\\字节流复制图 片.avi");
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fos.close();
fis.close();
}
//基本字节流一次读写一个字节
public static void method1() throws IOException {
//E:\\itcast\\字节流复制图片.avi
//模块目录下的 字节流复制图片.avi
FileInputStream fis = new FileInputStream("E:\\itcast\\字节流复制图片.avi");
FileOutputStream fos = new FileOutputStream("myByteStream\\字节流复制图 片.avi");
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}
🌳 字符流的介绍
🌳 字符串中的编码解码

public class StringDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
//定义一个字符串
String s = "中国";
//使用平台的默认字符集将该 String编码为一系列字节
byte[] bys = s.getBytes();
System.out.println("默认的字符集:" + Arrays.toString(bys));
byte[] bysUTF = s.getBytes("UTF-8");
System.out.println("UTF-8:" + Arrays.toString(bysUTF));
byte[] bysGBK = s.getBytes("GBK");
System.out.println("GBK:" + Arrays.toString(bysGBK));
String str = new String(bys);
System.out.println(str);
String strUTF = new String(bysUTF,"UTF-8");
System.out.println(strUTF);
String strGBK= new String(bysGBK, "GBK");
System.out.println(strGBK);
}
}
🌳 字符流中的编码解码
🌳 构造方法

public class ConversionStreamDemo {
public static void main(String[] args) throws IOException {
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myCharStream\\osw.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream("E:\\Code\\springcloud\\itcast\\java.txt"), "UTF-8");
osw.write("中国");
osw.close();
//InputStreamReader isr = new InputStreamReader(new FileInputStream("myCharStream\\osw.txt"));
InputStreamReader isr = new InputStreamReader(new
FileInputStream("E:\\Code\\springcloud\\itcast\\java.txt"), "UTF-8");
//一次读取一个字符数据
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
isr.close();
}
}
🌳 字符流写数据的5种方式

public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new
FileOutputStream("E:\\Code\\springcloud\\itcast\\java\\osw.txt"));
//void write ( int c):写一个字符
osw.write(97);
osw.write(98);
osw.write(99);
//void writ ( char[] cbuf):写入一个字符数组
char[] chs = {'a', 'b', 'c', 'd', 'e'};
osw.write(chs);
//void write ( char[] cbuf, int off, int len):写入字符数组的一部分
osw.write(chs, 0, chs.length);
osw.write(chs, 1, 3);
//void write (String str):写一个字符串
osw.write("abcde");
//void write (String str,int off, int len):写一个字符串的一部分
osw.write("abcde", 0, "abcde".length());
osw.write("abcde", 1, 3);
//释放资源
osw.close();
}
}
🌳 刷新和关闭的方法

🌳 字符流读数据

public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new
FileInputStream("E:\\Code\\springcloud\\itcast\\java\\osw.txt"));
//int read():一次读一个字符数据
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
System.out.println("------------------");
//int read(char[] cbuf):一次读一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
//释放资源
isr.close();
}
}
🌳 字符流复制Java文件
public class CopyJavaDemo02 {
public static void main(String[] args) throws IOException {
//根据数据源创建字符输入流对象
FileReader fr = new FileReader("E:\\Code\\springcloud\\src\\main\\java\\com\\BufferStreamDemo.java");
//根据目的地创建字符输出流对象
FileWriter fw = new FileWriter("E:\\Code\\springcloud\\src\\main\\java\\com\\test.java");
char[] chs = new char[1024];
int len;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
}
//释放资源
fw.close();
fr.close();
}
}

public class BufferedStreamDemo01 {
public static void main(String[] args) throws IOException {
//BufferedWriter(Writer out)
BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));
bw.write("hello\r\n");
bw.write("world\r\n");
bw.close();
//BufferedReader(Reader in)
BufferedReader br = new BufferedReader(new FileReader("myCharStream\\bw.txt"));
//一次读取一个字符数据
int ch;
while ((ch = br.read()) != -1) {
System.out.print((char) ch);
}
//一次读取一个字符数组数据
char[] chs = new char[1024];
int len;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
br.close();
}
}
🌳 字符缓冲流特有功能

public class BufferedStreamDemo02 {
public static void main(String[] args) throws IOException {
//创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new
FileWriter("myCharStream\\bw.txt"));
//写数据
for (int i = 0; i < 10; i++) {
bw.write("hello" + i);
//bw.write("\r\n");
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
//创建字符缓冲输入流
BufferedReader br = new BufferedReader(new
FileReader("myCharStream\\bw.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
🌳 字节流

🌳 字节流

🌳 点名器
public class CallNameDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("E:\\Code\\springcloud\\itcast\\java\\bw.txt"));
//创建ArrayList集合对象
ArrayList<String> array = new ArrayList<String>();
//调用字符缓冲输入流对象的方法读数据
String line;
while ((line = br.readLine()) != null) {
//把读取到的字符串数据存储到集合中
array.add(line);
}
//释放资源
br.close();
//使用Random产生一个随机数,随机数的范围在:[0,集合的长度)
Random r = new Random();
int index = r.nextInt(array.size());
//把第6步产生的随机数作为索引到ArrayList集合中获取值
String name = array.get(index);
//把第7步得到的数据输出在控制台
System.out.println("幸运者是:" + name);
}
}
🌳 集合到文件
@AllArgsConstructor
@Data
@NoArgsConstructor
public class Student {
private String sid;
private String name;
private int age;
private String address;
}
public class ArrayListToFileDemo {
public static void main(String[] args) throws IOException {
//创建ArrayList集合
ArrayList<Student> array = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("itheima001", "林青霞", 30, "西安");
Student s2 = new Student("itheima002", "张曼玉", 35, "武汉");
Student s3 = new Student("itheima003", "王祖贤", 33, "郑州");
//把学生对象添加到集合中
array.add(s1);
array.add(s2);
array.add(s3);
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new
FileWriter("E:\\Code\\springcloud\\itcast\\java\\students.txt"));
//遍历集合,得到每一个学生对象
for (Student s : array) {
//把学生对象的数据拼接成指定格式的字符串
StringBuilder sb = new StringBuilder();
sb.append(s.getSid()).append(",").append(s.getName()).append(",").append(s.getAge()).append(",").append(s.getAddress());
//调用字符缓冲输出流对象的方法写数据
bw.write(sb.toString());
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
🌳 文件到集合
public class FileToArrayListDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new
FileReader("E:\\Code\\springcloud\\itcast\\java\\students.txt"));
//创建ArrayList集合对象
ArrayList<Student> array = new ArrayList<Student>();
//调用字符缓冲输入流对象的方法读数据
String line;
while ((line = br.readLine()) != null) {
//把读取到的字符串数据用split()进行分割,得到一个字符串数组
String[] strArray = line.split(",");
//创建学生对象
Student s = new Student();
//把字符串数组中的每一个元素取出来对应的赋值给学生对象的成员变量值
//itheima001,林青霞,30,西安
s.setSid(strArray[0]);
s.setName(strArray[1]);
s.setAge(Integer.parseInt(strArray[2]));
s.setAddress(strArray[3]);
//把学生对象添加到集合
array.add(s);
}
//释放资源
br.close();
//遍历集合
for (Student s : array) {
System.out.println(s.getSid() + "," + s.getName() + "," +
s.getAge() + "," + s.getAddress());
}
}
}
🌳 递归的介绍
🌳 递归的注意事项
内存溢出🌳 不死神兔
public class DiGuiDemo1 {
public static void main(String[] args) {
int[] ints = new int[20];
ints[0] = 1;
ints[1] = 1;
for (int i = 2; i < ints.length; i++) {
ints[i] = ints[i - 1] + ints[i - 2];
}
System.out.println(ints[19]);
System.out.println(f(20));
}
public static int f(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return f(n - 1) + f(n - 2);
}
}
}
🌳 递归求阶乘
public class DiGuiDemo2 {
public static void main(String[] args) {
System.out.println(cheng(5));
}
public static int cheng(int n) {
if (n == 1) {
return 1;
} else {
return n * cheng(n - 1);
}
}
}
🌳 递归遍历目录
public class DiGuiDemo3 {
public static void main(String[] args) throws IOException {
File file1 = new File("E:\\Code\\springcloud\\itcast");
file1.mkdirs();
File file2 = new File("E:\\Code\\springcloud\\itcast\\java.txt");
file2.createNewFile();
File file3 = new File("E:\\Code\\springcloud\\itcast\\java");
boolean mkdir = file3.mkdir();
show(new File("E:\\Code\\springcloud\\itcast"));
}
public static void show(File srcFile) {
File[] fileArray = srcFile.listFiles();
if (fileArray != null) {
for (File listFile : srcFile.listFiles()) {
//判断该File对象是否是目录
if (listFile.isDirectory()) {
//是:递归调用
show(listFile);
} else {
//不是:获取绝对路径输出在控制台
System.out.println(listFile.getAbsolutePath());
}
}
}
}
}
🌳 进程:是正在运行的程序
资源分配和调用的独立单位🌳 线程:是进程中的单个顺序控制流,是一条执行路径
单线程:一个进程如果只有一条执行路径,则称为单线程程序多线程:一个进程如果有多条执行路径,则称为多线程程序🌳 实现多线程-继承Thread类
🌳 run()方法和start()方法的区别

🌳 设置和获取线程名称

public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
myThread.start();
myThread1.start();
System.out.println(myThread.currentThread());
}
}
public class MyThreadDemo {
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.setName("高铁");
myThread2.setName("飞机");
myThread1.start();
myThread2.start();
System.out.println(Thread.currentThread().getName());
}
}
🌳 实现多线程-实现Runnable接口
创建Thread类的对象,把MyRunnable对象作为构造方法的参数
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int i=0; i<100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
public class MyRunnableDemo {
public static void main(String[] args) {
//创建MyRunnable类的对象
MyRunnable my = new MyRunnable();
//创建Thread类的对象,把MyRunnable对象作为构造方法的参数
//Thread(Runnable target)
// Thread t1 = new Thread(my);
// Thread t2 = new Thread(my);
//Thread(Runnable target, String name)
Thread t1 = new Thread(my, "高铁");
Thread t2 = new Thread(my, "飞机");
//启动线程
t1.start();
t2.start();
}
}
🌳 多线程的实现方案
🌳 相比继承Thread类,实现Runnable接口的好处
🌳实现多线程-实现Callable接口
🌳实现多线程-使用线程池
🌳 两种调度方式
分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些🌳 优先级相关方法


🌳 sleep演示
public class ThreadSleep extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadSleepDemo {
public static void main(String[] args) {
ThreadSleep ts1 = new ThreadSleep();
ThreadSleep ts2 = new ThreadSleep();
ThreadSleep ts3 = new ThreadSleep();
ts1.setName("曹操");
ts2.setName("刘备");
ts3.setName("孙权");
ts1.start();
ts2.start();
ts3.start();
}
}
🌳 Join演示
public class ThreadJoin extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class ThreadJoinDemo {
public static void main(String[] args) {
ThreadJoin tj1 = new ThreadJoin();
ThreadJoin tj2 = new ThreadJoin();
ThreadJoin tj3 = new ThreadJoin();
tj1.setName("康熙");
tj2.setName("四阿哥");
tj3.setName("八阿哥");
tj1.start();
try {
tj1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
tj2.start();
tj3.start();
}
}
🌳 Daemon演示
public class ThreadDaemon extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ":" + i);
}
}
}
public class ThreadDaemonDemo {
public static void main(String[] args) {
ThreadDaemon td1 = new ThreadDaemon();
ThreadDaemon td2 = new ThreadDaemon();
td1.setName("关羽");
td2.setName("张飞");
//设置主线程为刘备
Thread.currentThread().setName("刘备");
//设置守护线程
td1.setDaemon(true);
td2.setDaemon(true);
td1.start();
td2.start();
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
线程一共有五种状态,线程在各种状态之间转换
线程安全🌳 安全问题出现的条件
🌳 如何解决多线程安全问题呢?
🌳 怎么实现呢?
把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可public class SellTicket implements Runnable {
private int tickets = 100;
//在SellTicket类中重写run()方法实现卖票,代码步骤如下
@Override
public void run() {
while (true) {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "正在出售第" +
tickets + "张票");
tickets--;
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
//创建SellTicket类的对象
SellTicket st = new SellTicket();
//创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
//启动线程
t1.start();
t2.start();
t3.start();
}
}

卖票出现了问题
相同的票出现了多次
出现了负数的票
问题产生原因
线程执行的随机性导致的
1️⃣ 同步代码块解决数据安全
🌳 同步代码块格式
synchronized(任意对象):就相当于给代码加锁了好处:解决了多线程的数据安全问题弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率synchronized(任意对象) {
多条语句操作共享数据的代码
}
public class SellTicket implements Runnable {
private int tickets = 100;
private Object obj = new Object();
@Override
public void run() {
while (true) {
//tickets = 100;
//t1,t2,t3
//假设t1抢到了CPU的执行权
//假设t2抢到了CPU的执行权
synchronized (obj) {
//t1进来后,就会把这段代码给锁起来
if (tickets > 0) {
try {
//t1休息100毫秒
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//窗口1正在出售第100张票
System.out.println(Thread.currentThread().getName() + "正在出售 第" + tickets + " 张票");
tickets--; //tickets = 99;
}
}
//t1出来了,这段代码的锁就被释放了
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
t1.start();
t2.start();
t3.start();
}
}
2️⃣ 同步方法解决数据安全
🌳 同步方法的格式
同步方法:就是把synchronized关键字加到方法上修饰符 synchronized 返回值类型 方法名(方法参数) {
方法体;
}
💮 同步方法的锁对象是什么呢?
💮 this
同步静态方法:就是把synchronized关键字加到静态方法上修饰符 static synchronized 返回值类型 方法名(方法参数) {
方法体;
}
💮 同步静态方法的锁对象是什么呢?
💮 类名.class
public class SellTicket implements Runnable {
private static int tickets = 100;
private int x = 0;
@Override
public void run() {
while (true) {
sellTicket();
}
}
// 同步方法
/* private synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" +
tickets + "张票");
tickets--;
}
}*/
// 静态同步方法
private static synchronized void sellTicket() {
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
tickets--;
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
t1.start();
t2.start();
t3.start();
}
}
3️⃣ Look锁
🌳 ReentrantLock构造方法

🌳 加锁解锁方法

public class SellTicket implements Runnable {
private int tickets = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售 第" + tickets + " 张票");
tickets--;
}
} finally {
lock.unlock();
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st = new SellTicket();
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
t1.start();
t2.start();
t3.start();
}
}
🌳 StringBuffer
StringBuilder 替代🌳 Vector
如果不需要线程安全的实现,建议使用ArrayList代替Vector🌳 Hashtable
如果不需要线程安全的实现,建议使用HashMap代替Hashtable🌳 生产者和消费者模式概述
一类是生产者线程用于生产数据一类是消费者线程用于消费数据
🌳 Object类的等待和唤醒方法

🌳 生产者和消费者案例
public class Box {
//定义一个成员变量,表示第x瓶奶
private int milk;
//定义一个成员变量,表示奶箱的状态
private boolean state = false;
public synchronized void put(int milk) {
//如果有牛奶,等待消费
if(state) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有牛奶,就生产牛奶
this.milk = milk;
System.out.println("送奶工将第" + this.milk + "瓶奶放入奶箱");
//生产完毕之后,修改奶箱状态
state = true;
//唤醒其他等待的线程
notifyAll();
}
public synchronized void get() {
//如果没有牛奶,等待生产
if (!state) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有牛奶,就消费牛奶
System.out.println("用户拿到第" + this.milk + "瓶奶");
//消费完毕之后,修改奶箱状态
state = false;
//唤醒其他等待的线程
notifyAll();
}
}
public class Producer implements Runnable {
private Box b;
public Producer(Box b) {
this.b = b;
}
@Override
public void run() {
for (int i = 1; i <= 30; i++) {
b.put(i);
}
}
}
public class Customer implements Runnable {
private Box b;
public Customer(Box b) {
this.b = b;
}
@Override
public void run() {
while (true) {
b.get();
}
}
}
public class Customer implements Runnable {
private Box b;
public Customer(Box b) {
this.b = b;
}
@Override
public void run() {
while (true) {
b.get();
}
}
}
🌳 计算机网络
🌳 网络编程
🌳 网络编程三要素
IP地址:而IP地址就是这个标识号–设备的标识端口:端口号就可以唯一标识设备中的应用程序了–应用程序的标识协议:通信双方必须同时遵守才能完成数据交换–常见的协议有UDP协议和TCP协议🌳 IP地址
IPv4:是给每个连接在网络上的主机分配一个32bit地址IPv6:为了扩大地址空间,通过IPv6重新定义地址空间,采用128位地址长度🌳 InetAddress

package com.itcast.thread;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
//InetAddress address = InetAddress.getByName("itheima");
InetAddress address = InetAddress.getByName("192.168.1.6");
//public String getHostName():获取此IP地址的主机名
String name = address.getHostName();
//public String getHostAddress():返回文本显示中的IP地址字符串
String ip = address.getHostAddress();
System.out.println("主机名:" + name);
System.out.println("IP地址:" + ip);
}
}
🌳 UDP协议:
用户数据报协议(User Datagram Protocol)
无连接通信协议:即在数据传输时,数据的发送端和接收端不建立逻辑连接🌳 UDP通信原理
🌳 UDP发送数据
🌳 构造方法

🌳 相关方法

public class SendDemo {
public static void main(String[] args) throws IOException {
//创建发送端的Socket对象(DatagramSocket)
// DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
DatagramSocket ds = new DatagramSocket();
//创建数据,并把数据打包
//DatagramPacket(byte[] buf, int length, InetAddress address, int port)
//构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
byte[] bys = "hello,udp,我来了".getBytes();
DatagramPacket dp = new
DatagramPacket(bys, bys.length, InetAddress.getByName("192.168.1.66"), 10086);
//调用DatagramSocket对象的方法发送数据
//void send(DatagramPacket p) 从此套接字发送数据报包
ds.send(dp);
//关闭发送端
//void close() 关闭此数据报套接字
ds.close();
}
}
🌳 UDP接收数据
🌳 构造方法

🌳 相关方法

public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//创建接收端的Socket对象(DatagramSocket)
DatagramSocket datagramSocket = new DatagramSocket(10086);
while (true) {
//创建一个数据包,用于接收数据
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
//调用DatagramSocket对象的方法接收数据
datagramSocket.receive(datagramPacket);
//解析数据包,并把数据在控制台显示
System.out.println("数据是:" + new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
}
}
}
🌳 TCP协议:传输控制协议 (Transmission Control Protocol)
面向连接的通信协议:即传输数据之前,在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输🌳 Java中的TCP通信
💮 Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
💮 Java为客户端提供了Socket类,为服务器端提供了ServerSocket类
🌳 TCP发送数据
🌳 构造方法
🌳 相关方法


public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
Socket s = new Socket("192.168.1.6", 10000);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流
OutputStream os = s.getOutputStream();
os.write("hello,tcp,我来了".getBytes());
//释放资源
s.close();
}
}
🌳 TCP接收数据
🌳 构造方法

🌳 相关方法

public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字
ServerSocket serverSocket = new ServerSocket(10000);
//Socket accept() 监听要连接到此套接字并接收它
Socket socket = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = socket.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys, 0, len);
System.out.println("数据是:" + data);
//释放资源
socket.close();
serverSocket.close();
}
}
🌳 案例需求
💮 客户端:发送数据,接受服务器反馈
💮 服务器:收到消息后给出反馈
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的Socket对象(Socket)
Socket socket = new Socket("192.168.1.6", 10000);
//获取输出流,写数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,tcp,我来了".getBytes());
//接收服务器反馈
InputStream inputStream = socket.getInputStream();
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
String data = new String(bys, 0, len);
System.out.println("服务器:" + data);
//释放资源
socket.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10000);
//监听客户端连接,返回一个Socket对象
Socket socket = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream inputStream = socket.getInputStream();
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
String data = new String(bys, 0, len);
System.out.println("客户端:" + data);
//给出反馈
OutputStream outputStream = socket.getOutputStream();
outputStream.write("数据我已经收到".getBytes());
//释放资源
serverSocket.close();
}
}
🌳 案例需求
💮 客户端:数据来自于键盘录入, 直到输入的数据是886,发送数据结束
💮 服务端:接收到数据在控制台输出
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端Socket对象
Socket socket = new Socket("192.168.1.6", 10000);
//数据来自于键盘录入,直到输入的数据是886,发送数据结束
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
if ("886".equals(line)) {
break;
}
//获取输出流对象
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
socket.close();
}
}
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务器Socket对象
ServerSocket ss = new ServerSocket(10000);
//监听客户端的连接,返回一个对应的Socket对象
Socket socket = ss.accept();
//获取输入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
ss.close();
}
}
🌳 Lambda示例
public class LambdaDemo {
public static void main(String[] args) {
new Thread(() -> {
System.out.println("多线程程序启动了");
}).start();
}
}
🌳 Lambda表达式的标准格式
形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可->:由英文中画线和大于符号组成,固定写法。代表指向动作代码块:是我们具体要做的事情,也就是以前我们写的方法体内容🌳 Lambda表达式的使用前提
🌳 无参无返回值抽象方法的练习
public interface Eatable {
void eat();
}
public class EatableImpl implements Eatable{
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
}
public class EatableDemo {
public static void main(String[] args) {
Eatable eatable = new EatableImpl();
useEatable(eatable);
useEatable(new Eatable() {
@Override
public void eat() {
System.out.println("一天两个果子");
}
});
useEatable(()->{
System.out.println("一天一个果");
});
}
public static void useEatable(Eatable eatable) {
eatable.eat();
}
}
🌳 有参无返回值抽象方法的练习
public interface Flyable {
void fly(String s);
}
public class FlyableDemo {
public static void main(String[] args) {
//匿名内部类
useFlyable(new Flyable() {
@Override
public void fly(String s) {
System.out.println(s);
System.out.println("飞机自驾游");
}
});
System.out.println("--------");
//Lambda
useFlyable((String s) -> {
System.out.println(s);
System.out.println("飞机自驾游");
});
}
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
}
🌳 有参有返回值抽象方法的练习
public interface Addable {
int add(int x, int y);
}
public class AddableDemo {
public static void main(String[] args) {
//在主方法中调用useAddable方法
useAddable((int x, int y) -> {
return x + y;
});
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}
}
🌳 省略的规则
💮 参数类型可以省略
💮 有多个参数的情况下,不能只省略一个
💮 如果参数有且仅有一个,那么小括号可以省略
💮如果代码块的语句只有一条,可以省略大括号和分号,和return关键字
💮 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
💮 必须有上下文环境,才能推导出Lambda对应的接口
💮 根据局部变量的赋值得知Lambda对应的接口
💮 根据调用方法的参数得知Lambda对应的接口
🌳 所需类型不同
🌳 使用限制不同
🌳 实现原理不同
🌳
::该符号为引用运算符,而它所在的表达式被称为方法引用
public interface Printable {
void printString(String s);
}
public class PrintableDemo {
public static void main(String[] args) {
//在主方法中调用usePrintable方法
usePrintable((String s) -> {
System.out.println(s);
});
//Lambda简化写法
usePrintable(s -> System.out.println(s));
//方法引用
usePrintable(System.out::println);
}
private static void usePrintable(Printable p) {
p.printString("爱生活爱Java");
}
}
🌳 引用类方法
💮 引用:类的静态方法
💮 格式:类名::静态方法
public interface Converter {
int convert(String s);
}
public class ConverterDemo {
public static void main(String[] args) {
//Lambda写法
useConverter(s -> Integer.parseInt(s));
//引用类方法
useConverter(Integer::parseInt);
}
private static void useConverter(Converter c) {
int number = c.convert("123456");
System.out.println(number);
}
}
Lambda表达式被类方法替代的时候,它的形式参数全部传递给静态方法作为参数🌳 引用对象的实例方法
💮 引用:类中的成员方法
💮 格式:对象::成员方法
public class PrintString {
//把字符串参数变成大写的数据,然后在控制台输出
public void printUpper(String s) {
String result = s.toUpperCase();
System.out.println(result);
}
}
public interface Printer {
void printUpperCase(String s);
}
public class PrinterDemo {
public static void main(String[] args) {
//Lambda简化写法
usePrinter(s -> System.out.println(s.toUpperCase()));
//引用对象的实例方法
PrintString ps = new PrintString();
usePrinter(ps::printUpper);
}
private static void usePrinter(Printer p) {
p.printUpperCase("HelloWorld");
}
}
Lambda表达式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数🌳 引用类的实例方法
💮 引用:类中的成员方法
💮 格式:类名::成员方法
public interface MyString {
String mySubString(String s,int x,int y);
}
public class MyStringDemo {
public static void main(String[] args) {
//Lambda简化写法
useMyString((s, x, y) -> s.substring(x, y));
//引用类的实例方法
useMyString(String::substring);
}
private static void useMyString(MyString my) {
String s = my.mySubString("HelloWorld", 2, 5);
System.out.println(s);
}
}
Lambda表达式被类的实例方法替代的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数💟 引用构造器
💮 引用:引用构造方法
💮 格式:类名::new
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public interface StudentBuilder {
Student build(String name,int age);
}
public class StudentDemo {
public static void main(String[] args) {
//Lambda简化写法
useStudentBuilder((name, age) -> new Student(name, age));
//引用构造器
useStudentBuilder(Student::new);
}
private static void useStudentBuilder(StudentBuilder sb) {
Student s = sb.build("林青霞", 30);
System.out.println(s.getName() + "," + s.getAge());
}
}
Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数💟 函数式接口概念
💮 有且仅有一个抽象方法的接口
💮 @FunctionalInterface放在接口定义的上方检测一个接口是不是函数式接口
💮 如果接口是函数式接口,编译通过;如果不是,编译失败
💟 定义一个类(RunnableDemo),在类中提供两个方法
💟 一个方法是:startThread(Runnable r) 方法参数Runnable是一个函数式接口
💟 一个方法是主方法,在主方法中调用startThread方法
public class RunnableDemo {
public static void main(String[] args) {
//在主方法中调用startThread方法
//匿名内部类的方式
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动了");
}
});
//Lambda方式
startThread(() -> System.out.println(Thread.currentThread().getName() + "线 程启动了"));
}
private static void startThread(Runnable r) {
new Thread(r).start();
}
}
💟 定义一个类(ComparatorDemo),在类中提供两个方法
💟 一个方法是:Comparator getComparator() 方法返回值Comparator是一个函数式接口
💟 一个方法是主方法,在主方法中调用getComparator方法
public class ComparatorDemo {
public static void main(String[] args) {
//定义集合,存储字符串元素
ArrayList<String> array = new ArrayList<String>();
array.add("cccc");
array.add("aa");
array.add("b");
array.add("ddd");
System.out.println("排序前:" + array);
Collections.sort(array, getComparator());
System.out.println("排序后:" + array);
}
private static Comparator<String> getComparator() {
//匿名内部类的方式实现
// return new Comparator() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length()-s2.length();
// }
// };
//Lambda方式实现
return (s1, s2) -> s1.length() - s2.length();
}
}
💟 Supplier接口也被称为生产型接口
💟 如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供我们使用
public class SupplierDemo {
public static void main(String[] args) {
String s = getString(() -> "林青霞");
System.out.println(s);
Integer i = getInteger(() -> 30);
System.out.println(i);
}
//定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier<Integer> sup) {
return sup.get();
}
//定义一个方法,返回一个字符串数据
private static String getString(Supplier<String> sup) {
return sup.get();
}
}
💟 Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定
public class ConsumerDemo {
public static void main(String[] args) {
//操作一
operatorString("林青霞", s -> System.out.println(s));
//操作二
operatorString("林青霞", s -> System.out.println(new
StringBuilder(s).reverse().toString()));
System.out.println("--------");
//传入两个操作使用andThen完成
operatorString("林青霞", s -> System.out.println(s), s ->
System.out.println(new StringBuilder(s).reverse().toString()));
}
//定义一个方法,用不同的方式消费同一个字符串数据两次
private static void operatorString(String name, Consumer<String> con1, Consumer<String> con2) {
con1.andThen(con2).accept(name);
}
//定义一个方法,消费一个字符串数据
private static void operatorString(String name, Consumer<String> con) {
con.accept(name);
}
}
💟 Predicate接口通常用于判断参数是否满足指定的条件
public class PredicateDemo02 {
public static void main(String[] args) {
boolean b1 = checkString("hello", s -> s.length() > 8);
System.out.println(b1);
boolean b2 = checkString("helloworld", s -> s.length() > 8);
System.out.println(b2);
boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length() < 15);
System.out.println(b3);
boolean b4 = checkString("helloworld", s -> s.length() > 8, s -> s.length() < 15);
System.out.println(b4);
}
//同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
private static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
return pre1.or(pre2).test(s);
}
//判断给定的字符串是否满足要求
private static boolean checkString(String s, Predicate<String> pre) {
return pre.test(s);
}
}
public class PredicateTest {
public static void main(String[] args) {
String[] strArray = {"林青霞,30", "柳岩,34", "张曼玉,35", "貂蝉,33", "王祖贤,31"};
ArrayList<String> array = myFilter(strArray,
s -> s.split(",")[0].length() > 2,
s -> Integer.parseInt(s.split(",")[1]) > 30);
for (String str : array) {
System.out.println(str);
}
}
//通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中
private static ArrayList<String> myFilter(String[] strArray, Predicate<String> pre1, Predicate<String> pre2) {
//定义一个集合
ArrayList<String> array = new ArrayList<String>();
//遍历数组
for (String str : strArray) {
if (pre1.and(pre2).test(str)) {
array.add(str);
}
}
return array;
}
}
💟 Function
接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
public class FunctionDemo {
public static void main(String[] args) {
//操作一
convert("100", s -> Integer.parseInt(s));
//操作二
convert(100, i -> String.valueOf(i + 566));
//使用andThen的方式连续执行两个操作
convert("100", s -> Integer.parseInt(s), i -> String.valueOf(i + 566));
}
//定义一个方法,把一个字符串转换int类型,在控制台输出
private static void convert(String s, Function<String, Integer> fun) {
// Integer i = fun.apply(s);
int i = fun.apply(s);
System.out.println(i);
}
//定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
private static void convert(int i, Function<Integer, String> fun) {
String s = fun.apply(i);
System.out.println(s);
}
//定义一个方法,把一个字符串转换int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
private static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
}
💟 Stream流的好处
💮 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印
💮Stream流把真正的函数式编程风格引入到Java中

public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//Stream流来改进
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
💟 Collection体系集合
💮 使用默认方法stream()生成流, default Stream stream()
💟 Map体系集合
💮 把Map转成Set集合,间接的生成流
💟 数组
💮 通过Stream接口的静态方法of(T… values)生成流
public class StreamDemo {
public static void main(String[] args) {
//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream();
//Map体系的集合间接的生成流
Map<String, Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();
//数组可以通过Stream接口的静态方法of(T... values)生成流
String[] strArray = {"hello", "world", "java"};
Stream<String> strArrayStream = Stream.of(strArray);
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
}
}
💟 中间操作:执行完此方法之后,Stream流依然可以继续执行其他操作

💟 filter代码演示
💮filter:对元素进行过滤
public class StreamDemo01 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("------------");
//需求2:把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("------------");
//需求3:把list集合中以张开头的,长度为3的元素在控制台输出
list.stream().filter(s -> s.length() == 3).filter(s -> s.startsWith("张")).forEach(System.out::println);
}
}
💟 limit&skip代码演示
💮limit:返回此流中的元素组成的流,截取前指定参数个数的数据
💮skip:跳过指定参数个数的数据,返回由该流的剩余元素组成的流
💟
public class StreamDemo02 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:取前3个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------");
//需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------");
//需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}
💟 concat&distinct代码演示
💮concat:合并a和b两个流为一个流
💮distinct:返回由该流的不同元素(根据Object.equals(Object) )组成的流
public class StreamDemo03 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
//需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出
//Stream.concat(s1,s2).forEach(System.out::println);
//需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::println);
}
}
💟 sorted代码演示
💮sorted():返回由此流的元素组成的流,根据自然顺序排序
💮sorted(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序
public class StreamDemo04 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("linqingxia");
list.add("zhangmanyu");
list.add("wangzuxian");
list.add("liuyan");
list.add("zhangmin");
list.add("zhangwuji");
//需求1:按照字母顺序把数据在控制台输出
list.stream().sorted().forEach(System.out::println);
System.out.println("------------");
//需求2:按照字符串长度把数据在控制台输出
list.stream().sorted((s1, s2) -> {
int num = s1.length() - s2.length();
int num2 = num == 0 ? s1.compareTo(s2) : num;
return num2;
}).forEach(System.out::println);
}
}
💟 map&mapToInt代码演示
💮map:返回由给定函数应用于此流的元素的结果组成的流
💮mapToInt:返回一个IntStream其中包含将给定函数应用于此流的元素的结果
public class StreamDemo05 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("10");
list.add("20");
list.add("30");
list.add("40");
list.add("50");
//需求:将集合中的字符串数据转换为整数之后在控制台输出
list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
list.stream().map(Integer::parseInt).forEach(System.out::println);
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
System.out.println("------------");
//int sum() 返回此流中元素的总和
int result = list.stream().mapToInt(Integer::parseInt).sum();
System.out.println(result);
}
}
💟 终结操作:执行完此方法之后,Stream流将不能再执行其他操作

public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:把集合中的元素在控制台输出
list.stream().forEach(System.out::println);
//需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count);
}
}
💟 对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中


public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
//需求1:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
//需求2:把使用Stream流操作完毕的数据收集到List集合中并遍历
List<String> names = listStream.collect(Collectors.toList());
for (String name : names) {
System.out.println(name);
}
//创建Set集合对象
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(20);
set.add(30);
set.add(33);
set.add(35);
//需求3:得到年龄大于25的流
Stream<Integer> setStream = set.stream().filter(age -> age > 25);
//需求4:把使用Stream流操作完毕的数据收集到Set集合中并遍历
Set<Integer> ages = setStream.collect(Collectors.toSet());
for (Integer age : ages) {
System.out.println(age);
}
//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};
//需求5:得到字符串中年龄数据大于28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s ->
Integer.parseInt(s.split(",")[1]) > 28);
//需求6:把使用Stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s ->
s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "," + value);
}
}
}
🌳 类的加载
🌳 类的连接
🌳 类的初始化
🌳 类的初始化步骤
💮 假如类还未被加载和连接,则程序先加载并连接该类
💮 假如该类的直接父类还未被初始化,则先初始化其直接父类
💮 假如类中有初始化语句,则系统依次执行这些初始化语句
💮 注意:在执行第2个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3
🌳 类的初始化时机
💮 创建类的实例
💮 调用类的类方法
💮 访问类或者接口的类变量,或者为该类变量赋值
💮 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
💮 初始化某个类的子类
💮 直接使用java.exe命令来运行某个主类
🌳 类加载器的作用
🌳 JVM的类加载机制
🌳 Java中的内置类加载器
🌳 ClassLoader中的两个方法

public class ClassLoaderDemo {
public static void main(String[] args) {
//static ClassLoader getSystemClassLoader():返回用于委派的系统类加载器
ClassLoader c = ClassLoader.getSystemClassLoader();
System.out.println(c); //AppClassLoader
//ClassLoader getParent():返回父类加载器进行委派
ClassLoader c2 = c.getParent();
System.out.println(c2); //PlatformClassLoader
ClassLoader c3 = c2.getParent();
System.out.println(c3); //null
}
}

1️⃣ 类名.class属性
2️⃣ 对象名.getClass()方法
3️⃣ Class.forName(全类名)方法
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> studentClass1 = Student.class;
System.out.println(studentClass1);
//使用类的class属性来获取该类对应的Class对象
Class<Student> studentClass2 = Student.class;
System.out.println(studentClass2);
System.out.println(studentClass1 == studentClass2);
System.out.println("--------");
//调用对象的getClass()方法,返回该对象所属类对应的Class对象
Student student = new Student();
Class<? extends Student> aClass = student.getClass();
System.out.println(aClass);
System.out.println(aClass == studentClass1);
System.out.println("--------");
//使用Class类中的静态方法forName(String className)
Class<?> aClass1 = Class.forName("com.itcast.lambda.Student");
System.out.println(aClass1);
System.out.println(aClass1 == studentClass1);
}
}
🌳 反射获取构造方法

🌳 Constructor类用于创建对象的方法

public class Student {
//成员变量:一个私有,一个默认,一个公共
private String name;
int age;
public String address;
//构造方法:一个私有,一个默认,两个公共
public Student() {
}
private Student(String name) {
this.name = name;
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//成员方法:一个私有,四个公共
private void function() {
System.out.println("function");
}
public void method1() {
System.out.println("method");
}
public void method2(String s) {
System.out.println("method:" + s);
}
public String method3(String s, int i) {
return s + "," + i;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
}
public class ReflectDemo02 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
Constructor<?> con = aClass.getConstructor(String.class, int.class, String.class);
System.out.println(con);
//基本数据类型也可以通过.class得到对应的Class类型
//T newInstance(Object... initargs)
Object obj = con.newInstance("林青霞", 30, "西安");
System.out.println(obj);
}
}
public class ReflectDemo03 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
//private Student(String name)
//Constructor getDeclaredConstructor(Class>... parameterTypes)
Constructor<?> con = aClass.getDeclaredConstructor(String.class);
//暴力反射
//public void setAccessible(boolean flag):值为true,取消访问检查
con.setAccessible(true);
Object obj = con.newInstance("林青霞");
System.out.println(obj);
}
}
🌳 Class类获取成员变量对象的方法

public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
//获取Class对象
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
Field[] field = aClass.getDeclaredFields();
for (Field f : field) {
System.out.println(f);
}
System.out.println("---------");
Field addressField = aClass.getField("address");
System.out.println(addressField);
System.out.println("---------");
//获取无参构造方法创建对象
Constructor<?> con = aClass.getConstructor();
Object obj = con.newInstance();
//给obj的成员变量addressField赋值为西安
addressField.set(obj, "西安");
System.out.println(obj);
}
}
🌳 Field类用于给成员变量赋值

public class ReflectDemo05 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
Constructor<?> constructor = aClass.getConstructor();
Object obj = constructor.newInstance();
//s.name = "林青霞";
Field nameField= aClass.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj,"林青霞");
System.out.println(obj);
//s.age = 30;
Field ageField = aClass.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj,30);
System.out.println(obj);
//s.address = "西安";
Field addressField = aClass.getDeclaredField("address");
addressField.setAccessible(true);
addressField.set(obj,"西安");
System.out.println(obj);
}
}
🌳 Class类获取成员方法对象的方法

public class ReflectDemo06 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
Method[] declaredMethods = aClass.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("--------");
Method m = aClass.getMethod("method1");
//获取无参构造方法创建对象
Constructor<?> con = aClass.getConstructor();
Object obj = con.newInstance();
//Object invoke(Object obj, Object... args) 在具有指定参数的指定对象上调用此方法对象表示的基础方法
//Object:返回值类型
//obj:调用方法的对象
//args:方法需要的参数
//执行obj的method1方法
m.invoke(obj);
}
}
🌳 Method类用于执行方法的方法

public class ReflectDemo07 {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.itcast.lambda.Student");
//Student s = new Student();
Constructor<?> con = aClass.getConstructor();
Object obj = con.newInstance();
//s.method1();
Method m1 = aClass.getMethod("method1");
m1.invoke(obj);
//s.method2("林青霞");
Method m2 = aClass.getMethod("method2", String.class);
m2.invoke(obj,"林青霞");
// String ss = s.method3("林青霞",30);
Method m3 = aClass.getMethod("method3", String.class, int.class);
Object o = m3.invoke(obj, "林青霞", 30);
System.out.println(o);
Method function = aClass.getDeclaredMethod("function");
function.setAccessible(true);
function.invoke(obj);
}
}
通过反射技术,向一个泛型为Integer的集合中添加一些字符串数据public class ReflectTest01 {
public static void main(String[] args) throws Exception {
//创建集合
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add(10);
// array.add(20);
// array.add("hello");
Class<? extends ArrayList> c = array.getClass();
Method add = c.getMethod("add", Object.class);
add.invoke(array, "hello");
add.invoke(array, "world");
add.invoke(array, "java");
System.out.println(array);
}
}
通过反射运行配置文件中指定类的指定方法在这里插入代码片
🏅 全栈小狐狸的逆袭之路:📢💨 Java学习路线
🏅 基础:📢💨JAVA基础
🏅 基础:📢💨JAVA进阶