API(Application Programming Interface应用程序接口)是一些预先定义的接口。
声明
数据类型[] 数组名;
初始化
内存初始化
数据类型[] 数组名=new 数据类型[长度];
元素初始化
简写方式1:数据类型[] 数组名=new 数据类型[]{元素列表}
简写方式2:数据类型[] 数组名={元素列表}(但是只能在声明的时候使用)
数组元素的默认值
数组内存初始化的时候,数组的容器内的元素是**零值**
* 值类型中的数字类型零值是0
* 值类型中的boolean零值是false
* 引用类型的零值是null
数组元素的修改
数组名[下标]=数据;
数组某一个元素的查询(读取)
数组名[下标];
数组全部元素的查询(遍历)
循环下标
数组异常
数组下标超过数组的容量(下标越界)
* java.lang.ArrayIndexOutOfBoundsException
数组对象的属性
length:表示数组的长度
数组特点总结
* 数组长度固定
* 数组有下标
所有接口父类都是object,接口的extends没有继承概念,只是组合概念
数组的内存存储是连续的
基本程序开发思路
基本程序开发各个包之间的依赖关系
业务包依赖数据包
入口包依赖业务包
语法
//三点形参
public void fun3(int... a){
}
三点参数为变成参数,只能在参数上出现三点
三点参数的实参可以是数组类型,也可以是非数组类型(使用多个实参逗号隔开)
//可以是数组类型
int[] a3=new int[]{10,20,30,40};
myApp.demoServices.fun3(a3);
//单个非数组类型实参
int a2=2000;
myApp.demoServices.fun3(a2);
//多个非数组类型实参
int a2_1=2000;
int a2_2=3000;
int a2_3=4000;
myApp.demoServices.fun3(a2_1,a2_2,a2_3);
三点参数的形参与非三点参数一起定义的时候,只能放在后面
//todo 三点参数与非三点参数一起
public void fun4(int b,int... a){
}
三点参数的形参个数只能有一个
两两交换
冒泡排序是比较基础的排序算法之一,其思想是相邻的元素两两比较,较大的数下沉,较小的数冒起来,这样一趟比较下来,最大(小)值就会排列在一端。整个过程如同气泡冒起,因此被称作冒泡排序。
//todo 冒泡排序
public void maopao(int[] a) {
//因为两两比较因此要使用槽长(也就是总长-1),
int z=a.length - 1;
for (int i = 0; i <z ; i++) {
for (int j = 0; j < z-i; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
//体现两两交换
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
每个元素线性与其它元素依次比较
选择排序是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置,直到未排序元素个数为0。
//选择排序
public void line(int[] a){
int z=a.length;
for(int i=0;i<z;i++){
for(int j=i+1;j<z;j++){
if(a[i]>a[j]){
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}
冒泡排序和选择排序程序上的区别
//todo 二分查找
public int binarySearch(int number,int[] a) {
//二分查找数组先排序
//先冒泡排序
maopao(a);
//返回初始值
int result=-1;
//开始初始化三个指针
//头指针
int from=0;
//尾指针
int end=a.length-1;
//中指针
int mid=(from+end)/2;
//开始查询
while(from<=end){
//数据和中指针判断
if(number==a[mid]){
//相等情况
// 找到啦
result=mid;
//这里需要注意找到数据后
//需要退出循环,不然死循环,因为中指针不前进和不后退了
break;
}
else if(number>a[mid]){
//大于情况
//中指针前进
mid+=1;
//头指针等于中指针位置
from=mid;
//从新计算中指针
mid=(from+end)/2;
}
else {
//小于情况
//中指针后退
mid-=1;
//尾指针等于中指针位置
end=mid;
//从新计算中指针
mid=(from+end)/2;
}
}
//返回查询到的下标
return result;
}
Arrays数组工具类,提供一些静态的各种操作数组的方法
内存中有一个区域为字符串常量池,主要是为了优化字符串的
* 创建字符串的时候先搜索字符串常量池是否有字符串序列,如果没有则创建
* 字符串对象使用=运算符的时候实际上是指向字符串常量池
* java提供一个intern()方法类返回一个字符串常量池的引用
//字面量创建字符串
String str1="hzj";
* new关键字创建方法
* 任何时刻都会创建新对象
//使用new关键字创建字符串
String str2=new String("hzj");
该方法返回的字符串序列指向的是字符串常量池中的字符串
比较字符串序列是否相等,不关系内存地址
日期格式化的返回的是字符串
机器时间概念–毫秒数
LocalDate日期
LocalTime时间
LocalDateTime日期和时间
字段常量
数学API
提供了数学的支持
math提供的全部都是静态方法无需实例化
math常量PI
pow方法,求数的几次方
floor取整,ceil进位,round四舍五入(double类型)
随机数(生成小数)
Math.random() 大于等于0到小于1.0
Math.random()*26 0到25
大数字支持
BigDecimal类(小数)
提供基本的大数字构造
提供数字的四则运算方法
add方法加法,
BigInteger类(整数)
byte — Byte
short — Short
int — Integer
long — Long
char — Float
double — Double
boolean — Boolean
每个值类型后面都有一个引用类型支持,叫包装类(引用数据类型)
包装类在实例化的时候可以直接使用值类型(值类型转包装类(隐藏的))
值类型转包装类,目的是为获得包装类方法的支持
包装类的equals方法比较的是字面值
int a=10000;
int b=10000;
//值类型转换包装类,是隐藏手段(这里的隐藏指的是java语法)
Integer a1=10000;
Integer b1=10000;
//值类型比较内容是否相等使用==
System.out.println(a==b);
//引用类型比较内容是否相等不能使用==
System.out.println(a1.equals(b1));
//引用类型使用==比较的是地址
System.out.println(a1==b1);
装箱
值类型转换成包装类型
目的:使用包装类的方法,但只能使用equals比较内容,使用==比较内存地址
隐含:实际上是使用了包装类的静态方法valueOf()方法
拆箱
包装类型转换成值类型
目的:不使用包装类的方法,且可以使用==比较内容
隐含:对象方法xx.value() (例如整型拆箱使用intValue())进行拆箱
目的:节约创建对象的数量,优化的目的
如果使用new关键字那么必然会创建对象
装箱的时候(调用valueOf)具备优化条件
? 所有整数,创建了数组存了256个数作为缓存区间
? 小数没有缓存区间
? 布尔类型没有缓存区间
构造
添加
删除
修改
查询(按条件)
遍历(查询所有)
排序(JDK1.8支持)
面试:微服务主要五个框架,MySQL索引,hash表
基本的操作(但是太多try)
try {
//捕获(不一定以引发)
String str = null;
System.out.println(str.length());
}
catch (Exception e){
//处理
System.out.println("字符串是空的...");
}
try {
int a=10;
System.out.println(a/0);
}
catch (Exception e){
System.out.println("除数不能是0");
}
try {
int[] b= {1,2,3};
System.out.println(b[10]);
}
catch (Exception e){
System.out.println("数组超标啦");
}
System.out.println("今天还可以...........");
多路catch
try {
//捕获(不一定以引发)
String str = null;
System.out.println(str.length());
int a=10;
System.out.println(a/0);
int[] b= {1,2,3};
System.out.println(b[10]);
}
catch (NullPointerException e){
//处理空指针
System.out.println("字符串是空的...");
}
catch (ArithmeticException e){
//处理除0
System.out.println("不可除0");
}
catch (ArrayIndexOutOfBoundsException e){
//处理数组超标
System.out.println("数组超标");
}
catch (Exception e){
//处理(兜底)
System.out.println("反正报错了,也不知道什么错");
}
System.out.println("今天还可以...........");
finally
try {
String str = null;
System.out.println(str.length());
System.out.println("aaaaaaaaaaaaaaaaa");
//碰到exit中断,那么finally就不会执行
//System.exit(0);
//return关键字一定终止方法
return;
} catch (Exception e) {
System.out.println("字符串空啦");
} finally {
//一般在这里做一些关闭(EasyExcel)
System.out.println("我是扫尾");
}
System.out.println("开心呀");
什么时候用try
public static void main(String[] args) {
//输入接收变量
int i=0;
//避免JVM编译期认为while死循环,导致while后面代码没法执行
//boolean b=true;
//给三次输入机会
int js=1;
while (js<=3){
try {
//Scanner每次都需要一个新对象
Scanner scanner=new Scanner(System.in);
//如果目前没有办法使用if判断那么就使用异常捕获
i = scanner.nextInt();
break;
}
catch (Exception e){
System.out.println("请你输入整数");
js++;
}
}
System.out.println(i);
System.out.println("程序结束................");
}
throws关键字向上抛出异常
//如果引发异常,我的业务没办法处理
//向上抛出异常,由调用本方法的对象处理
//在方法声明最后使用关键字throws 然后加上异常类型
//throws可以跟多个异常类
//throws可以直接使用Exception完事,但是绝对不提倡
public int fun1() throws NullPointerException, ClassNotFoundException {
int length = 0;
String str = null;
//向上抛运行时异常NullPointerException
//这里也无法处理,因此向上抛
length = str.length();
//调用了向上抛一般异常ClassNotFoundException的forName方法
//这里也无法处理,因此继续向上抛
Class.forName("aaaaa");
return length;
}
//我们在看别人写的方法的时候一定要看是否向上抛了异常
//那么你作为方法的调用者,你需要考虑,是否继续向上抛,还是try处理
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
//自定义一个30岁异常
public class My30AgeException extends Exception {
//使用构造方法输入异常信息
public My30AgeException(String message) {
super(message);
}
}
//自定义一个21岁异常
public class My21AgeException extends Exception{
public My21AgeException(String message) {
super(message);
}
}
//业务类里面的一个方法
public void fun3(int age) throws My30AgeException, My21AgeException {
System.out.println("报名");
if (age >= 30) {
//构建了一个异常
throw new My30AgeException("30岁搞架构师");
}
else if(age <= 21){
throw new My21AgeException("21搞学历");
}
else{
System.out.println("上学");
}
}
//调用业务类的一个代码段
MyServices myServices = new MyServices();
try {
myServices.fun3(18);
} catch (My30AgeException e) {
e.printStackTrace();
System.out.println("进架构师班级");
} catch (My21AgeException e) {
e.printStackTrace();
System.out.println("进学历提升班级");
}
System.out.println("程序继续运行...................");
流 指文件内容
输入 input
输出 output
文件内容
文件可以存在硬盘上,那么流即文件的内容在硬盘上
单位
字节(二进制文件)基本单位
字符(文本文件)2字节
方向
源头—>目的地 输出
目的地---->源头 输入
功能
节点流(直接连接源头和目的地的)
过滤流(连接节点的)
JavaIO流的架构
File类代表硬盘中的?件或?件夹
File类直接使?new关键+?件路径实例化对象
File对象指的是?件的属性
File对象基本操作
创建?件或?件夹
删除?件或?件夹
判定?件或?件夹是否存在
使?listFiles?法返回??件或??件夹
通常使?递归来获取所有的?件或?件夹
?件内容
?件可以存在于硬盘上,那么流即?件的内容在硬盘上(流的源在硬盘上)
流的总量(字节数)是固定的
?件可以存在于?络上,那么流即?件的内容在?络上
流的总量(字节数)是不固定的(只有下载完毕后,才真正知道流的总量)
单位
字节(?进制?件)(byte)基本单位
InputStream、OutputStream
字符(?本?件)(char)(等于2字节)
Reader、Writer
?向【Java参照我们的程序】
源头(?件内容)->?的地(我们的程序)(输?)
InputStream、Reader
?的地(我们的程序)->源头(?件内容)(输出)
OutputStream、Writer
功能
节点流(直接连接(源头)和(?的地))
FileReader、FileInputStream、FileOutputStream、FileWriter
功能流(过滤)(连接节点的)
缓存功能
BufferedInputStream、BufferedReader、BufferedOutputStream、 BufferedWriter、
字节流转字符流
InputStreamReader、OutputStreamWriter
有关流的操作【?件的操作】
读取?件内容【字符】
//字符流读取流程
String path = "d:\\abc.txt";
FileReader fileReader = null;
try {
fileReader = new FileReader(path);
//舀水的杯子的大小
char[] chars = new char[1024 * 1024];
//read返回的结果如果是-1代表源读完了
int read = fileReader.read(chars, 0, chars.length);
//源还有没有流
//System.out.println("read="+read);
while (read != -1) {
String info = new String(chars, 0, read);
System.out.print(info);
read = fileReader.read(chars, 0, chars.length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
写??件内容【字符】
String path = "d:\\abc.txt";
String info = "(央视财经《经济信息联播》)一位老人清早在路边散步时,\n" +
"因为突然受到一声气喇叭的惊吓而倒地身亡。家属认为按喇叭的司机存在重大过错,\n
"随即将相关人员告上了法庭,索赔34万余元。";
FileWriter fileWriter = null;
try {
//第二参数代表是否覆盖,默认覆盖,给true代表追加
fileWriter = new FileWriter(path, true);
fileWriter.write(info);
//输出需要flush()刷新缓存
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
?件拷?
//拷贝都是用字节流操作
//源
String path1 = "d:\\stu.xls";
//目标
String path2 = "d:\\stucopy.xls";
File file1 = new File(path1);
//文件先创建
File file2 = new File(path2);
if (!file2.exists()) {
//开始创建
try {
boolean newFile = file2.createNewFile();
if (!newFile) {
System.out.println("你没空间了");
return;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//开始拷贝
//d:\\stu.xls
FileInputStream fileInputStream = null;
//"d:\\stucopy.xls";
FileOutputStream fileOutputStream = null;
try {
//字节输入流创建
fileInputStream = new FileInputStream(path1);
//获得流的总量
//fileInputStream.available();
//字节输出流创建
fileOutputStream = new FileOutputStream(path2, false);
//水瓢,水瓢越循环次数越少
byte[] bytes = new byte[1024];
//读取d:\stu.xls的内容到我们程序的水瓢里面(bytes)
int read = fileInputStream.read(bytes, 0, bytes.length);
//read返回的不是-1代表没有读完
while (read != -1) {
//拷贝,就是这里不System.out.println();
//把我们程序的水瓢里面(bytes)数据,输出到d:\\stucopy.xls里面
fileOutputStream.write(bytes, 0, read);
System.out.println("正在拷贝..................");
//继续读取d:\stu.xls的内容到我们程序的水瓢里面(bytes)
read = fileInputStream.read(bytes, 0, bytes.length);
}
//输出有缓存支持,所以输出一定要清空缓存
fileOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
缓存功能流【BufferedReader 】
String path = "d:\\abc.txt";
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
fileReader = new FileReader(path);
//功能流的特点
//字符缓存读取功能流,就使用它的读一行功能
bufferedReader = new BufferedReader(fileReader);
//读一行功能
String s = bufferedReader.readLine();
while(s!=null){
System.out.println(s);
s = bufferedReader.readLine();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
缓存功能流【BufferedWriter】
String path = "d:\\hzj.txt";
String info = "企业微信-企业在线协同办公文档-免费使用-在线文档";
FileWriter fileWriter = null;
BufferedWriter bufferedWriter = null;
try {
//fileWriter有缓存,但不能改
fileWriter = new FileWriter(path, false);
//可以自定义缓存
bufferedWriter = new BufferedWriter(fileWriter, 1024 * 100);
bufferedWriter.write(info);
//新功能newLine()
bufferedWriter.newLine();
bufferedWriter.write(info);
//清空缓存
bufferedWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
字节转字符功能流
public class MyApp12 {
public InputStream fun1() throws IOException {
String path = "d:\\abc.txt";
FileInputStream fileInputStream = new FileInputStream(path);
return fileInputStream;
}
public static void main(String[] args) {
MyApp12 myApp12 = new MyApp12();
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
inputStream = myApp12.fun1();
//功能流
//字节转字符
inputStreamReader = new InputStreamReader(inputStream);
//功能流读行再来
bufferedReader = new BufferedReader(inputStreamReader);
String str = bufferedReader.readLine();
while (str != null) {
System.out.println(str);
str = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
?件拷?(带缓存功能流)
String path = "d:\\YunJing_ins.exe";
String pathCopy = "d:\\YunJing_insCopy.exe";
File file = new File(pathCopy);
if (file.exists()) {
System.out.println("文件存在..............");
return;
}
try {
boolean newFile = file.createNewFile();
if (!newFile) {
System.out.println("创建新文件失败..............");
return;
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("创建新文件异常..............");
return;
}
//把字节转换成字符
//InputStreamReader inputStreamReader=new InputStreamReader();
//public InputStream fun1(); public Reader fun1();
//InputStreamReader inputStreamReader=new InputStreamReader();
FileInputStream fileInputStream = null;
BufferedInputStream bufferedInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
fileInputStream = new FileInputStream(path);
bufferedInputStream = new BufferedInputStream(fileInputStream, 1024 * 10
fileOutputStream = new FileOutputStream(pathCopy);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream, 1024 *
byte[] bytes = new byte[1024];
int read = bufferedInputStream.read(bytes, 0, bytes.length);
while (read != -1) {
bufferedOutputStream.write(bytes, 0, read);
System.out.println("正在拷贝...................");
read = bufferedInputStream.read(bytes, 0, bytes.length);
}
bufferedOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
有关流的操作【对象的操作】【序列化】
把对象的属性值存成?件
? 只有字节
? DataOutputStream、DataInputStream这两个类都是单纯的读取或者获取对象的属性
? ObjectOutputStream、ObjectInputStream这两个是对象整体的读取或获取
? 对象的整体的读取或者获取叫序列化
? 序列化就是把对象(?个)存成?件,然后利?反序列化再吧对象拿出来
DataOutputStream操作
public class Stu {
int id;
String name;
int age;
LocalDate localDate;
public Stu(int id, String name, int age, LocalDate localDate) {
this.id = id;
this.name = name;
this.age = age;
this.localDate = localDate;
}
public Stu() {
}
@Override
public String toString() {
return "Stu{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", localDate=" + localDate +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 LocalDate getLocalDate() {
return localDate;
}
public void setLocalDate(LocalDate localDate) {
this.localDate = localDate;
}
}
public class MyApp {
public static void main(String[] args) {
Stu stu1 = new Stu();
stu1.setId(1);
stu1.setName("hzj");
stu1.setAge(18);
stu1.setLocalDate(LocalDate.of(2022, 8, 9));
System.out.println(stu1);
String path = "d:\\mystu1.hzj";
//节点流
FileOutputStream fileOutputStream = null;
//功能流
DataOutputStream dataOutputStream = null;
try {
fileOutputStream = new FileOutputStream(path, false);
dataOutputStream = new DataOutputStream(fileOutputStream);
//dataOutputStream提供数据类型的写
//注意这里的顺序
dataOutputStream.writeInt(stu1.getId());
dataOutputStream.writeUTF(stu1.getName());
dataOutputStream.writeInt(stu1.getAge());
dataOutputStream.writeUTF(stu1.getLocalDate()
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
dataOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dataOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
DataInputStream操作
public class MyApp2 {
public static void main(String[] args) {
String path = "d:\\mystu1.hzj";
FileInputStream fileInputStream = null;
DataInputStream dataInputStream = null;
try {
fileInputStream = new FileInputStream(path);
dataInputStream = new DataInputStream(fileInputStream);
//怎么进的,就怎么出
int id = dataInputStream.readInt();
String name = dataInputStream.readUTF();
int age = dataInputStream.readInt();
String localdate = dataInputStream.readUTF();
Stu stu2 = new Stu();
stu2.setId(id);
stu2.setName(name);
stu2.setAge(age);
stu2.setLocalDate(LocalDate.parse(localdate));
System.out.println(stu2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
dataInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ClassRoom类实现序列化标记,并且编写序列化版本
//Serializable接口是一个标记,代表可以让系统序列化该类
public class ClassRoom implements Serializable {
//序列化是有版本的
private static final long serialVersionUID = 100;
//transient禁止序列化修饰符,
//transient int id; 这样的化id属性就无法序列化了,也不会反序列
int id;
String name;
public ClassRoom(int id, String name) {
this.id = id;
this.name = name;
}
public ClassRoom() {
}
@Override
public String toString() {
return "ClassRoom{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ObjectOutputStream操作
public class MyApp3 {
public static void main(String[] args) {
ClassRoom classRoom1 = new ClassRoom();
classRoom1.setId(1001);
classRoom1.setName("2109");
String path = "d:\\classroom.hzj";
FileOutputStream fileOutputStream = null;
ObjectOutputStream objectOutputStream = null;
try {
fileOutputStream = new FileOutputStream(path, false);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
//writeObject新功能
//序列化【把对象存起来】
//java.io.NotSerializableException
//被序列化的类必须要实现一个接口Serializable
//序列化是有版本号的,如果不写会默认有一个,但是这里是强调要写。
//private static final long serialVersionUID = 100;
objectOutputStream.writeObject(classRoom1);
objectOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ObjectInputStream操作
public class MyApp4 {
public static void main(String[] args) {
String path = "d:\\classroom.hzj";
FileInputStream fileInputStream = null;
ObjectInputStream objectInputStream = null;
try {
fileInputStream = new FileInputStream(path);
objectInputStream = new ObjectInputStream(fileInputStream);
//反序列化
Object o = objectInputStream.readObject();
ClassRoom classRoom = (ClassRoom) o;
System.out.println(classRoom);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Java中?Class类代表类的结构
Class类的?个对象就是反射对象
Class类的?个对象就是某?个类的结构描述
Class类如何构造
静态?法forName
类.class
象.getClass()
只能访问修饰符允许访问的范围getxxx();
可以访问任意修饰符范围的getDeclaredxxx();
类的结构?般分为以下?种
Field字段类
getDeclaredFields()获取所有字段
Method?法类
Parameter?法形参类
Constructor构造?法类
Annotation注解类
public class MyApp {
//Class对象是什么反射对象(Class对象是什么某个类定义的结构)
public static void main(String[] args) {
//反射创建对象
//任何一个类都有一个反射类Class
//创建一个反射类的对象,即创建一个Class类的对象
//反射类对象的构造,使用静态方法
try {
String classSrc = "com.bjpowernode.beans.Stu";
Class stuClass = Class.forName(classSrc);
//返回类中字段信息
//stuClass.getxxx();只能访问修饰符允许访问的范围
//stuClass.getDeclaredxxx();可以访问任意修饰符范围的
//Field[] fields = stuClass.getFields();
//查看所有字段
Field[] fields = stuClass.getDeclaredFields();
for (Field temp : fields) {
//设置访问权限
//temp.setAccessible(true);
System.out.println(temp.getName());
}
System.out.println("********************************************
//查看所有方法
Method[]declaredMethods = stuClass.getDeclaredMethods();
for (Method temp : declaredMethods) {
//temp.getReturnType()返回方法的返回类型的反射形
Class returnType = temp.getReturnType();
System.out.println("返回类型:" + returnType.getName());
System.out.println("方法名:" + temp.getName());
System.out.println("参数列表:");
//返回参数列表
Parameter[] parameters = temp.getParameters();
for (Parameter temp2 : parameters) {
//参数类型
System.out.println("参数返回类型:" + temp2.getType().getN
//参数名称【JVM中是不需要知道参数名称的】
System.out.println("参数名称:" + temp2.getName());
}
System.out.println("*****************************");
}
System.out.println("*************构造方法****************");
//查看所有构造方法
Constructor[] declaredConstructors = stuClass.getDeclaredConstru
for (Constructor temp : declaredConstructors) {
//temp.getReturnType()返回方法的返回类型的反射形
System.out.println("方法名:" + temp.getName());
System.out.println("参数列表:");
//返回参数列表
Parameter[] parameters = temp.getParameters();
for (Parameter temp2 : parameters) {
//参数类型
System.out.println("参数返回类型:" + temp2.getType().getN
//参数名称【JVM中是不需要知道参数名称的】
System.out.println("参数名称:" + temp2.getName());
}
System.out.println("*****************************");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
构造类
执?类属性
执?类?法
注解是使?特定的符号和属性来完成特定的功能
注解的?命周期
活在源代码(给?看,相当于注释)
RetentionPolicy.SOURCE
活在字节码(class字节码可以解析,相当于给字节码程序员当注释,字节码程序员可以利 ?该注解完成某些功能)
RetentionPolicy.CLASS
活在运?时(JVM)(JVM需要执?的,对功能有影响)
RetentionPolicy.RUNTIME
注解可以?在哪?(Java源码)
注解可以写的地?由ElementType枚举类定义的地?
看注解的定义
看注解的功能
自定义操作
注解的声明(?定义注解)
注解是?个接?,但是需要在接?前?使?@符号
//Override是注解名称
//@interface是注解,所以区别于interface接口,但是注解就是接口
public @interface Override
注解?命周期定义(?在注解上?的注解叫元注解)
使用@Retention
具体的什么周期使用RetentionPolicy枚举
注解能?在什么地?
使用@Target
具体的位置使用ElementType枚举
注解能?的地?可以是多个(也就是说@Target可以声明出多个地?)
注解结构
属性(不带默认值的属性、带默认值的属性)
//生命周期
@Retention(RetentionPolicy.SOURCE)
//能写在哪里(一般都会只定义写在一个地方,很少定义同时写到多个地方)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotaion {
//注解属性
//不带默认值 数据类型 属性名()
//带默认值的 数据类型 属性名() default 值
String name() default "hzj";
//如果该属性没有默认值,则使用注解的时候必须填
int age();
int[] arrayAH();
//属性的数据类型,只能基本属性类型、字符串型、Class类型,其它的自定义类型等不可以
//容器可以是数组(但是只能是一维),但是不能是集合
//ArrayList cl();
}
进程就是程序的?命周期,应?程序开始,进程开始,应?程序结束,进程结束
程序运?在操作系统上,进程是程序的单位
进程由线程组成,?个进程的启动,?少要有?个线程
Java程序中,主启动?法(???法)为main?法启动后?即产?了?个main线程(主线程)
进程拥有?命周期
线程是进程的组成单位
线程拥有?命周期
线程由?法体语句组成
在?个类class??会可以存在抽象?法,但是必须是native?法
native?法是指调?本地?法(该本地?法指的是C或C++语法的?法)
native?法意味着该?法并不是Java语法实现的,因此需要采?JNI技术来调?C或C++?法
?般来说涉及到了操作系统的底层或者直接要与硬件通信,通常会使?C语?处理,?Java采?navtic修饰符修饰?身的抽象?法,代表调?C语?的?法。
Thread类
thread代表线程
获取当前线程
静态?法:currentThread() 获取线程名称
对象?法:getName()
线程的创建
语法层?(都会使?实现runnable接?的?法来创建线程)
继承Thread类(如果直接继承Thread类,那么就?法继承其他类)
实现Runnable接?
MyThreadB myThreadB=new MyThreadB();
//与Thread建立关联
Thread thread=new Thread(myThreadB);
thread.setName("MyThreadB线程");
thread.start();
使?Thread对象的start?法启动线程
内存层?
创建?个线程就是创建了?个栈
异步:就在不同栈中执??法,就是异步执?
堆是数据存储的,堆??的对象是线程共享的
栈是线程私有
线程处理共享数据的问题
多个线程处理共享数据(?如对象,?如静态资源),会造成线程安全问题。
我们会采?同步策略解决问题
常??法
public class MyApp6 {
public static void main(String[] args) {
//线程想休眠3小时24分17秒88毫秒
//一般方案
try {
Thread.sleep(12257088L);
} catch (InterruptedException e) {
e.printStackTrace();
}
//线程想休眠3小时24分17秒88毫秒
//优雅方案
try {
TimeUnit.HOURS.sleep(3);
TimeUnit.MINUTES.sleep(24);
TimeUnit.SECONDS.sleep(17);
TimeUnit.MILLISECONDS.sleep(88);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
setName/getName
设置线程名称,底层是?个char数组(猜想:因为c没有字符串,c的字符串是char数 组)
sAlive()
查询线程是否启动并没终?状态
getId()
线程唯?ID,底层是?个简单的?增的整数
yield()
?法的作?是放弃当前的CPU资源(不确定)
setPriority()
设置线程优先级(不确定)
setDaemon()
设置后台线程
后台线程不可单独运?(如果全是后台线程,则?即??消亡)
package com.bjpowernode.thread;
//测试后台线程,进程中只有后台线程,那么后台线程立即死亡
public class MyT4 implements Runnable{
@Override
public void run() {
while (true){
System.out.println("okokokko");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT4;
public class MyApp4 {
public static void main(String[] args) {
MyT4 myT4=new MyT4();
Thread thread=new Thread(myT4,"myT4");
//这里设置一个后台线程,并且该线程是死循环
thread.setDaemon(true);
//开启线程,然后什么都不会打印,线程就死掉了
thread.start();
}
}
中断可以中断的?法有
sleep
join
中断有三个?法
线程对象中断操作
interrupt()【如果没有遇到需要唤醒的线程,则保留标记位为true,唤醒后则标记位为 false】
该?法可以让Thread.sleep唤醒(也就是中断Thread的sleep让其提前唤醒
线程类静态判断中断(使?后会修改标记位,并修改为false)
interrupted()【该?法属于静态?法Thread.interrupted()】
判断中断?法是否使?过,采?的标记位?法
如果interrupt()?法没有中断(也就是没有踢掉sleep)则interrupted返回true
如果interrupt()?法有中断(也就是有踢掉sleep)则interrupted返回false
若没有interrupt()?法,则interrupted的标记位false
interrupted()?法执?过后会修改标记位为false
线程对象判断中断(该?法属于对象?法Thread.currentThread().isInterrupted())
判断中断?法是否使?过,采?的标记位?法
如果interrupt()?法没有中断(也就是没有踢掉sleep)则interrupted返回true
如果interrupt()?法有中断(也就是有踢掉sleep)则interrupted返回false
若没有interrupt()?法,则interrupted的标记位false
isInterrupted()?法执?过后不会修改标记位
interrupt()中断sleep
package com.bjpowernode.thread;
//interrupt()中断sleep
public class MyT2 implements Runnable{
@Override
public void run() {
//执行中断开始设计标记位为true,
//碰到sleep将会立即中断sleep线程将其唤醒
Thread.currentThread().interrupt();
try {
//开始sleep
//interrupt()可以将其唤醒
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("被踢了");
}
//判断中断标记位【这里使用的是Thread.interrupted()】
//判断后会修改标记位为false
System.out.println(Thread.interrupted());
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT2;
//interrupt()中断sleep
public class MyApp2 {
public static void main(String[] args) {
MyT2 myT2=new MyT2();
Thread thread=new Thread(myT2,"myT2");
thread.start();
}
}
main线程中中断thread线程
package com.bjpowernode.thread;
//在外界使用interrupt()方法中断本线程
public class MyT1 implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println(i);
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("MyT1的被踢醒");
}
}
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT1;
public class MyApp {
public static void main(String[] args) {
MyT1 myT1=new MyT1();
Thread thread=new Thread(myT1,"线程1");
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//使用main线程中断thread线程【也就是不在thread自己里面中断自己】
thread.interrupt();
}
}
Thread.currentThread().isInterrupted()调?后不会修改标记位
package com.bjpowernode.thread;
//测试Thread.currentThread().isInterrupted()判断标记位后,不会改变标记位
public class MyT5 implements Runnable{
@Override
public void run() {
//调用中断
Thread.currentThread().interrupt();
//打印中断标记位,这里为true,并且不会改变标记位
System.out.println(Thread.currentThread().isInterrupted());
//打印中断标记位,这里为true,并且不会改变标记位
System.out.println(Thread.currentThread().isInterrupted());
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT5;
//测试Thread.currentThread().isInterrupted()判断标记位后,不会改变标记位
public class MyApp5 {
public static void main(String[] args) {
MyT5 myT5 =new MyT5();
Thread thread1=new Thread(myT5,"xxx");
thread1.start();
}
}
Thread.interrupted()调?后会修改标记位为false
package com.bjpowernode.thread;
//测试Thread.interrupted()判断标记位后,会改变标记位为false
public class MyT3 implements Runnable {
@Override
public void run() {
//调用中断
Thread.currentThread().interrupt();
//打印中断标记位,这里为true,并且会改变标记位为false
System.out.println(Thread.interrupted());
//打印中断标记位,这里为false,因为被上面的Thread.interrupted()修改了
System.out.println(Thread.interrupted());
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT3;
//测试Thread.interrupted()判断标记位后,会改变标记位为false
public class MyApp3 {
public static void main(String[] args) {
MyT3 myT3 =new MyT3();
Thread thread1=new Thread(myT3,"xxx");
thread1.start();
}
}
join
线程A在线程B中执?了A.join(),则B进?等待,直到线程A结束?命周期,或者到达给定的 时间,那么B线程继续执?
join?法会使当前线程永远地等待下去,直到期间被另外的线程中断,或者join的线程执? 结束
状态
线程的状态由Thread.State枚举常量标识:
NEW——线程还没有开始执?。
RUNNABLE——线程正在JVM中执?
BLOCKED——线程被阻塞并等待?个监听锁
WAITING——线程?限期地等待另外?条线程执?特定的操作
TIMED_WAITING——线程在特定的时间内等待另外?条线程执?某种操作。
TERMINATED——线程?经退出
判断线程状态的?些?法
package com.bjpowernode.thread;
//线程状态查看
public class MyT7 implements Runnable {
@Override
public void run() {
//RUNNABLE状态
//thread线程开始执行状态
System.out.println("RUNNABLE-1状态测试:"+Thread.currentThread().getSt
System.out.println("ok");
try {
//thread线程开始休眠
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
//RUNNABLE状态
//thread线程休眠被中断,开始执行
System.out.println("RUNNABLE-3状态测试(唤醒):"+Thread.currentThr
}
//RUNNABLE状态
//thread线程继续执行
System.out.println("RUNNABLE-2状态测试:"+Thread.currentThread().getSt
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT7;
//获取线程的当前状态
//尝试自己写出打印语句,并且正好是thread对象所处的某种状态
public class MyApp7 {
public static void main(String[] args) {
MyT7 myT7=new MyT7();
Thread thread=new Thread(myT7,"myT7");
//NEW状态
//thread线程刚刚新建
System.out.println("NEW状态测试:"+thread.getState());
//thread线程刚刚开始
thread.start();
//这里main线程休眠500,目的是为了让thread线程抢到CPU进入休眠
//为下面打印thread线程休眠状态提供支持
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//TIMED_WAITING状态
//thread线程开始休眠
System.out.println("TIMED_WAITING状态测试:"+thread.getState());
//唤醒thread
//thread线程休眠被唤醒
thread.interrupt();
//这里main线程休眠3000,目的是为了让thread线程抢到CPU,并执行完毕
//为下面打印thread线程结束状态提供支持
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//TERMINATED状态
//thread已经执行结束(这里利用时间差预判thread已经执行结束)
System.out.println("TERMINATED状态测试:"+thread.getState());
}
}
?命周期
线程从?到死的状态变化
执?各种线程?法后,线程的状态变化
线程关闭【thread.stop();已经被废除】
正常关闭,线程执?完毕即关闭
捕获中断信号关闭线程【这?不推荐使?该?法来设计线程关闭】
println(Thread.interrupted());
//打印中断标记位,这里为false,因为被上面的Thread.interrupted()修改了
System.out.println(Thread.interrupted());
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT3;
//测试Thread.interrupted()判断标记位后,会改变标记位为false
public class MyApp3 {
public static void main(String[] args) {
MyT3 myT3 =new MyT3();
Thread thread1=new Thread(myT3,“xxx”);
thread1.start();
}
}
join
- 线程A在线程B中执?了A.join(),则B进?等待,直到线程A结束?命周期,或者到达给定的 时间,那么B线程继续执?
- join?法会使当前线程永远地等待下去,直到期间被另外的线程中断,或者join的线程执? 结束
状态
- 线程的状态由Thread.State枚举常量标识:
- NEW——线程还没有开始执?。
- RUNNABLE——线程正在JVM中执?
- BLOCKED——线程被阻塞并等待?个监听锁
- WAITING——线程?限期地等待另外?条线程执?特定的操作
- TIMED_WAITING——线程在特定的时间内等待另外?条线程执?某种操作。
- TERMINATED——线程?经退出
- 判断线程状态的?些?法
- isAlive()检查线程是否已经启动且还没有结束状态
- getState()?法直接获取线程对象的状态
package com.bjpowernode.thread;
//线程状态查看
public class MyT7 implements Runnable {
@Override
public void run() {
//RUNNABLE状态
//thread线程开始执行状态
System.out.println(“RUNNABLE-1状态测试:”+Thread.currentThread().getSt
System.out.println(“ok”);
try {
//thread线程开始休眠
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
//RUNNABLE状态
//thread线程休眠被中断,开始执行
System.out.println(“RUNNABLE-3状态测试(唤醒):”+Thread.currentThr
}
//RUNNABLE状态
//thread线程继续执行
System.out.println(“RUNNABLE-2状态测试:”+Thread.currentThread().getSt
}
}
package com.bjpowernode.app;
import com.bjpowernode.thread.MyT7;
//获取线程的当前状态
//尝试自己写出打印语句,并且正好是thread对象所处的某种状态
public class MyApp7 {
public static void main(String[] args) {
MyT7 myT7=new MyT7();
Thread thread=new Thread(myT7,“myT7”);
//NEW状态
//thread线程刚刚新建
System.out.println(“NEW状态测试:”+thread.getState());
//thread线程刚刚开始
thread.start();
//这里main线程休眠500,目的是为了让thread线程抢到CPU进入休眠
//为下面打印thread线程休眠状态提供支持
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//TIMED_WAITING状态
//thread线程开始休眠
System.out.println(“TIMED_WAITING状态测试:”+thread.getState());
//唤醒thread
//thread线程休眠被唤醒
thread.interrupt();
//这里main线程休眠3000,目的是为了让thread线程抢到CPU,并执行完毕
//为下面打印thread线程结束状态提供支持
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//TERMINATED状态
//thread已经执行结束(这里利用时间差预判thread已经执行结束)
System.out.println(“TERMINATED状态测试:”+thread.getState());
}
}
?命周期
- 线程从?到死的状态变化
- 执?各种线程?法后,线程的状态变化
线程关闭【thread.stop();已经被废除】
- 正常关闭,线程执?完毕即关闭
- 捕获中断信号关闭线程【这?不推荐使?该?法来设计线程关闭】
- 使?标记控制【最好使? volatile修饰 】