常用 API 总结
1.Math
1.1类名.方法调用
方法 | 效果 |
---|---|
public static int abs(inta) | 返回绝对值 |
public static double ceil(double a) | 向上取整(记忆方法 ceil 四个字母依次增加) |
public static double floor(double a) | 向下取整 |
public static int round(float a) | 四舍五入 |
public static int max(int a,int b) | 返回最大值 |
public static int min(int a,int b) | 返回最小值 |
public static double pow (double a,double b) | a的b次幂 |
public static double random() | 产生[0.0 , 1.0)的随机数 |
2. System
2.1 类名.方法调用
方法 | 效果 |
---|---|
public static void exit(int status) | status 为 0 时正常退出,不为 0 时异常退出 |
public static long currentTimeMillis() | 返回 1970 年至今的毫秒数,一般用两个返回值相减得到运行时间 |
System.arrayCopy() | 五个参数 拷贝原数组,开始索引数,目标数组,开始索引数,拷贝数量 |
3.Object
方法 | 效果 |
---|---|
s1.toString | 打印对象时输出对象的属性值(需要在对象类中重写 toString 方法) |
s1.equals(s2) | 比较两个对象的属性值(需要在对象类中重写 equals 方法) |
public static boolean equals(s1,s2) ,Objects.equals | 与上一个方法相似,但是可以避免空指针异常 |
4.BigDecimal
4.1构造方法
BigDecimal(double val);
BigDecimal(String val);
通常传入 String,计算更精确
4.2 四则运算
加:public BigDecimal add (另一个 BigDecimal对象)
减:public BigDecimal subtract (另一个 BigDecimal对象)
乘:public BigDecimal multiply (另一个 BigDecimal对象)
除:public BigDecimal divide (另一个 BigDecimal对象)
精确除法:public BigDecimal divide(另一个对象,精确位数,舍入模式)
舍入模式
BigDecimal.round_up -------->ROUNDINGMode.UP进一法
BigDecimal.floor ------------->ROUNDINGMode.FlOOR去尾法
BigDecimal.half_up----------->RoundingMode.HALF_四舍五入
BigDecimal 和int的转换
1.BigDecimal -> int
int intValue ()
BigDecimal bd1 = new BigDecimal("3.2");
BigDecimal i1 = bd1.divide(new BigDecimal("0.3"), 3, RoundingMode.UP);
int i2 = i1.intValue();
- int -> BigDecimal
int i = 3;
BigDecimal bd = BigDecimal.valueOf(i1);
5.Date类
方法 | 效果 |
---|---|
构造方法 public Date() | 默认格式的系统当前时间 |
构造方法public Date( long Date) | 从初始时间开始过了参数毫秒值后的时间(需要考虑时差) |
成员方法public long getTimg() | 获得初试时间至今的毫秒值 |
public void setTimg(long timr) | 设置时间,单位是毫秒值 |
6.simpleDateFormat类(一个日期格式方面的类)
方法 | 说明 |
---|---|
public SimpleDateFormat() | 创建一个对象.使用默认格式 |
public SimpleDateFormat(String pattern) | 构造一个对象,使用给定的模式 |
public final String format(Date date) | 将日期格式化为给定模式 |
public Date parse(String source) | 将给定日期分析为给定模板的对象 |
public static void main(String[] args) {
Date d = new Date();//Tue May 25 21:02:00 CST 2021
SimpleDateFormat sdf = new SimpleDateFormat();
String format = sdf.format(d);
System.out.println(format);//2021/5/25 下午8:24
//从Date到String
String format1 = new SimpleDateFormat("yy-MM-dd HH:mm:ss").format(d);
System.out.println(format1);//21-05-25 20:25:41
//从String到Date
String s = "2033-2-3 03:03:03";
SimpleDateFormat sdf2 = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
Date parse = sdf2.parse(s);
System.out.println(parse);//Thu Feb 03 03:03:03 CST 2033
Date parse1 = sdf.parse(s);//该语句会报错,因为sdf的格式与s的格式不同
System.out.println(parse1);
}
7.JDK8时间日期类
两个静态方法:返回值是LocalDateTime对象
方法 | 说明 |
---|---|
public static LocalDateTime now() | 获取当前系统时间 |
public static LocalDateTime of() | 使用指定年月日时分秒初始化时间 |
get获取时间
pluse增加时间
with修改时间
常用于:
public static void main(String[] args){
LocalDateTime now = LocalDateTime.now();//2021-05-25T21:05:02.034492
LocalDateTime dateTime = LocalDateTime.of(2222, 3, 4, 5, 6, 7);//2222-03-04T05:06:07
//默认的LocalDateTime时间格式化成字符串
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = now.format(dtf);
System.out.println(s);//2021-05-25 21:15:12
//将字符串时间转换成LocalDateTime
String time = "2999-05-25 21:15:12";
LocalDateTime sometime = LocalDateTime.parse(time, dtf);
System.out.println(sometime);//2999-05-25T21:15:12
}
Period,Duration用于计算时间间隔
8.异常
编译时异常都是Exception及其子类,运行时异常都是RuntimeException
8.1处理方式:
1.JVM默认:将异常名,错误原因输出到控制台,并结束程序.
2.Throws: 方法名小括号后大括号前使用
Throws + 异常类名,之后谁到用方法谁处理该异常(甩锅)
3.Throw:用在方法体内,方法体内判断是否会发生异常,如果发生异常手动抛出
4.try catch方法:
try{
可能出现问题的代码;
}
catch(异常类名 变量名){
处理异常的代码;
} catch(){}
...
8.2注意事项:
1.try中没有出现问题时: catch不会执行
2.try中出现问题: 直接跳转到相应的catch语句,try中的余下的内容不会执行,catch中的语句执行结束后 try catch体系结束.
3.try中出现的方法没有被捕捉: 由JVM默认处理.
4.同时出现多个异常时:多写几个catch依次处理,但是要注意异常的父类与子类的关系.父类在上时,子类不会执行.
8.3自定义异常
public class AgeOutOfBoundsException extends RuntimeException {
public AgeOutOfBoundsException() {
}
public AgeOutOfBoundsException(String message) {
super(message);
}
}
定义一个有参构造和一个无参构造
throw 抛出时创建定义的错误对象
public void setAge(int age) {
if (age >= 16 && age <= 28) {
this.age = age;
} else {
throw new AgeOutOfBoundsException();
//可以是有参数的可以是无参数的
}
}
8.4异常的处理顺序:
(1) 运行时异常:
a.如果没有处理异常,会交给JVM会默认处理,创建异常对象,打印到控制台,结束程序
b.如果有throw,没有try…catch或catch没有捕捉到异常,则执行throw创建的对象
c.如果有throw,但是catch也捕捉到的异常,则执行catch方法体内的处理方法
(2)编译时异常:
通过try…catch或throws处理,throws用在方法名后,表示调用该方法可能会产生异常
9.集合
集合的学习从上至下,先学习父类公用的方法,在学习子类具体的不同方法.
所有集合存储类型只能是引用型,String Integer等,或对象
9.1 Collection集合
collection集合是单列集合的顶层接口,实现类是ArrayList和LinkedList
9.1.1collection集合的方法
方法名 | 效果 |
---|---|
boolean add (E e) | 添加元素,返回布尔值 |
boolean remove(Object o) | 移除元素,返回布尔值 |
boolean removeIf(Object o) | 根据判断条件移除元素,返回布尔值 |
void clear | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在该元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 返回实际保存的元素个数 |
//removeIf的lambda用法,最常用,底层原理是C++编写的迭代器,过滤数组中返回值为true的元素
private static void removeIf() {
Collection<String> collection = new ArrayList<>();
collection.add("a");
collection.add("b");
collection.add("c");
boolean c = collection.removeIf(s -> "c".equals(s));
System.out.println(c);
System.out.println(collection);
}
//也可以调用Predicate方法
private static void removeIf() {
Collection<String> collection = new ArrayList<>();
collection.add("a");
collection.add("b");
collection.add("c");
boolean c = collection.removeIf(Predicate.isEqual("c"));
System.out.println(c);
System.out.println(collection);
}
注意事项
1.不难看到add方法用的是泛型方法,而其他的方法用的是普通方法,参数为object.
原因: add使用泛型方法限制添加的内容必须为集合对象要求的类型,而调用remove方法时不需要满足类型必须与集合要求类型一致,编译时不易报错,运行时也不会删除错误类型的数据
2.removeIf的用法: removeIf是Collection接口中的default方法,调用时括号内可以使用匿名类重写,或lambda,返回值值为true时删除对象
3.集合内对象为创建的bean类时,调用contains方法只能通过重写equals方法判断该对象的所有属性.
9.1.2迭代器
集合的专用遍历方式
Iterator iterator():返回集合中所有元素.
通过创建集合对象的迭代器,创建后有个指针指向-1
常用方法:
boolean hasNext(): 判断当前位置的下一个位置是否有对象
E next():指针后移,取出元素.
void remove(): 移除next取出的元素.
9.1.3增强for
底层原理是迭代器
注意: 增强for也就是foreach不能动态(不能在循环中)删除增加元素,动态增加和删除可以用for循环或iterator
for(集合/数组中元素的数据类型 变量名 : 集合/数组名) {
// 已经将当前遍历到的元素封装到变量中了,直接使用变量即可
}
9.2 List
存取有序,可重复,有索引
9.2.1方法
方法名 | 效果 |
---|---|
void add(int index,E element) | 指定索引添加集合规定类型的元素 |
E remove(int index) | 移除索引值位置的元素,返回该元素 |
E set(int index,E element) | 修改索引位置元素 |
E get(int index) | 查询索引位置元素 |
9.2.1 ArrayList
底层是数组存储,查询快,增删慢
方法 | 效果 |
---|---|
Boolean add (Object o) | 添加元素 |
E remove(int index) | 移除索引处元素,并返回 |
void set(int index ,E element) | 修改索引处元素 |
E get(int index) | 查询索引处元素 |
int size() | 得到实际保存元素的个数 |
ArrayList是List的实现类,对add方法进行方法重载将返回值变成了boolean,增加了新的方法size()
9.2.2LinkedList
底层是双链表,增删快,查询慢
方法 | 效果 |
---|---|
void addFirst(E e) | 链头添加元素 |
void addLast() | 链尾添加元素 |
E getFirst() | 查询链头元素 |
E getLast() | 查询链尾元素 |
E removeFirst() | 移除链头元素 |
E removeLast() | 移除链尾元素 |
虽然没有写List通用的方法,但是作为实现类,接口的方法都可以使用
9.3 Set
不能重复存储,没有索引,不能用普通for循环,只能用iterator或增强for
9.3.1 TreeSet
底层是红黑树,不能重复存储,没有索引,存取无序.
保证无重复的原因是设定排序规则后,相同的元素返回值是0不存.
可以将元素排序:
方法一:TreeSet()无参构造,基本引用类型有默认的排序方式,创建类时要实现comparable并对compareTo成员方法重写.
this. - o.是升序
@Override
public int compareTo(Phone o) {
int result = this.getPrice() - o.getPrice();
return result;
}
方法二:TreeSet(Comparator comparator)有参构造,Comparator是函数式接口,可用匿名类或lambda
o1. - o2是升序
TreeSet<Phone> st = new TreeSet<>(new Comparator<Phone>() {
@Override
public int compare(Phone o1, Phone o2) {
int result = o1.getPrice() - o2.getPrice();
return result;
}
});
9.3.2 HashSet
底层是Hash表,加载因子0.75,初始默认长度16,存到16*0.75个元素之后扩容成两倍.
元素唯一,存取无序,没有索引
保证元素唯一的原因是因为底层是哈希表,根据哈希值存储,属性相同(equals方法)且哈希值(hashcode()方法)也相同的元素只存一个,属性值不同但是哈希值相同的元素在哈希表中替换旧元素,旧元素和新元素以链表结构存储,JDK8后当链表存储的长度超过8时转成红黑树结构.
哈希值:JDK通过对象的地址或属性计算得到,重写hashcode和equals方法后得到的是通过属性计算的哈希值
9.3.3 LinkedHashSet
双链表加哈希表,继承自HashSet,可以保证存取有序
9.4 Map
双列集合,一个键对应一个值,称为键值对或键值对(entry)对象,键不能重复,值可以重复.
9.4.1 方法
基本功能 | 效果 |
---|---|
V put(K key,V value) | 可以添加,也可以通过键修改.返回值是替换前的value |
V remove(Object key) | 移除键对应的元素,返回值是value |
void clear() | 清空集合 |
boolean ContainsKey(Object key) | 判断是否存在该键 |
boolean ContainsValue(Object value) | 判断是否存在该值 |
boolean isEmpty() | 判断集合是否为空 |
int size () | 返回键值对个数 |
获取功能 | |
V get(Object key) | 通过键获得该键对应的值 |
Set< v > keySet() | 获得所有键的集合 |
collection< v > value() | 获得所有值的集合 |
set<Map.entrySet<K,V> setEntry | 获得键值对(整体)的集合 |
9.4.2遍历方法
方法一:(增强for快捷键map.keyset().for):通过set keySet()方法,获得键的set集合,再利用增强for遍历set集合调用V get(Object key)获得每个键对应的值.
方法二:利用键值对对象,通过Set<map.entry<K,V>> entrySet()获得键值对对象集合,遍历集合调用Entry对象的entry.getValue()和entry.getKey()
方法三:创建map.forEach()方法的实现类,forEach已经遍历了集合,重写
9.4.1 HashMap
底层是哈希表结构
保证键的唯一通过equals()和hashCode()
自定义对象要重写equals()和hashCode()
9.4.2TreeMap
底层是红黑树,排序时只关心键不关心值
自然排序:空参构造,实现comparable重写compareTo
比较器排序:有参构造,比较器comparator
10.泛型
将运行时期的问题提前到了编译时期
泛型类: class 类名 {}
泛型方法: 修饰符 返回值 方法名(){}
泛型接口 interface 接口名 {}
注意事项
1.泛型接口内的方法不需要定义成泛型
2.泛型接口的实现类也是泛型时,类型定义延缓到创建对象时.
3.泛型接口的实现类是普通类时,类型定义在实现类里确定.
通配符<?>,
通配符上限<? extend 类型> ,只能使用类型及其子类
通配符下限<? super 类型> ,只能使用类型及其父类
11.File
文件和目录的抽象表示,将文件和目录封装成对象,File封装的不是真正的文件,而是路径名,文件可能存在也可能不存在.
构造方法 | 效果 |
---|---|
File(String pathname) | 通过字符串表示文件的路径 |
File(String parent, String child) | 可以用两个字符串拼接路径 |
File(File parent,String child) | 可以通过一个文件对象和字符串拼接 |
注意事项: 路径名中间隔可以用/也可以用\\
(两个反斜杠,因为正则表达式\\表示的是一个\)
11.1路径
绝对路径:从根目录开始到访问文件.(Linux和Macos的根目录是/)
相对路径:File (“a.txt”):默认是当前项目的文件
File(“模块名\a.txt”):当前模块内的文件
11.2方法
方法名 | 效果 |
---|---|
创建 | |
public boolean crateNewFile() | File对象的路径下创建文件,创建成功返回True,文件存在创建失败返回false |
public boolean mkdir() | (只能创建一个文件夹)创建单级目录,创建成功返回True |
public boolean mkdirs() | 创建多级目录,创建成功返回true(能创建一个就算成功) |
删除 | |
public boolean delete() | 只能删除文件或空文件夹 |
查询 | |
public boolean isDirector() | 判断是否存在该目录 |
public boolean isFile() | 判断是否存在该文件 |
public boolean exist() | 判断这个东西是否存在 |
获取 | |
public String getName() | 获取当前文件或目录的名字 |
public File[] listFiles | 获取当前路径文件的文件数组,当目录或文件不存在或没有权限时返回null,当文件为空时返回长度为零的数组 |
12.IO流
站在内存的角度 I:input输入到内存,读数据 , O:output输出,写数据
有字符流和字节流两种
(当文件为纯文本文件时两者都可以用,用字符流更好,当文件不是纯文本文件时用字节流,但是当用字节流读取有文字内容时会出现乱码)
12.1字节流
字节流的抽象基类:InputStream,OutputStream(两个抽象类,是所有字节流的父类)
读到中文时会乱码,所以文本文件的读取不适合字节流,但是复制文本文件没有影响.
12.1.1字节输出流
字节输出流:FileOutputStream
文件不存在时可以创建,父类路径不存在时报错.
构造方法 | 说明 |
---|---|
FileOutputStream(String name) | 参数传递的路径, 如果文件存在,会将文件清空,然后输入内容 |
FileOutputStream(String name ,boolean append) | 参数传递的路径和一个布尔值,布尔值为True时续写,下一次写文件不会清空 |
FileOutputStream(File file) | 参数是文件对象 |
FileOutputStream(File file, boolean append) | 参数是文件对象和续写开关 |
方法 | 效果 |
---|---|
void write(int b) | 向文件写入一个int整数,文件中显示的是通过int值找ASCII码指定的内容 |
void write(byte[] b) | 向文件写入一个字节数组,每个字节对应的是ASCII指定的内容 |
void write(byte[] b , int off, int len ) | 向文件写入一个字节数组的一部分 |
void write("\r\n".getBytes()) | 换行操作,\r\n会被读到, ` Windows:\r\n, Mac os:\r , Linux: \n |
void write(“一个字符串”.getBytes()) | 可以将字符串转换成对应的字节数组进行输出 |
void close() | 释放,如果不释放内容,将会导致文件被占用,不能删除等 |
写数据时的异常处理,新关键字 finally
FileOutputStream fos = null;
try{
}catch(异常类型){
}finally{
if(fos != null)
fos.close();
}
12.1.2字节输入流
字节输入流:FileInputStream
路径不存在时报错
方法 | 效果 |
---|---|
int read() | 返回值是当前字符的ASCII码值 -1为空 |
int read(byte[] bytes) | 将文件内容读到数组中,返回数组中有效字符的个数,-1为空 |
int read(byte[] bytes, int off, int len ) | 将文件内容读到数组的指定位置,返回读取的有效数字,-1为空 |
void close() | 释放 |
12.1.3 字节流输入输出的应用
文件复制:复制一个文件的内容到一个新文件
(1)方法一: 一次复制一个字节
FileInputStream fis = new FileInputStream("/Users/jason/Downloads/除暴.mkv");
FileOutputStream fos = new FileOutputStream("/Users/jason/Desktop/FileTest/copy.mkv");
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fos.close();
fis.close();
(2)方法二: 一次读取一个数组
byte[] bytes = new byte[1024 << 3];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes,0,len);
}
12.1.4 字节缓冲流
构建了一个缓冲区,底层是数组,减少内存和主存之间的交换次数,从而减少时间.BufferOutputStream和BufferInputStream
复制文件应用的升级,利用字节缓冲流加一次传输一个数组.
12.2字符流
字符流的父类:Writer,Reader
字符流出现的原因:字节流读中文时会输出乱码,而字符流底层是字节流+编码表,解决了这一问题.
String解决乱码的方法
方法 | 说明 |
---|---|
byte[] getBytes() | String的方法,用平台默认的编码将字符串转化为字节数组 |
byte[] getBytes(String charsetName) | 用指定的编码将字符串转化为字节数组 |
String(byte[] bytes) | String的构造方法 ,将字节数组以默认编码方式转化为字符串 |
String(byte[] bytes, String charsetName) | 以指定方法转化为字符串 |
12.2.1 字符输出流
常用:FileWriter
构造方法
方法 | 说明 |
---|---|
FileWriter(File file) | 与字节输出流大同小异,也是可传两个参数 |
FileWriter(String fileName) | 同上 |
字符输出流的方法与字节流大同小异,区别在于字节流用字节数组Byte[],而字符流用字符数组Char[].
方法 | 说明 |
---|---|
void write(String str) | 可以写入一个字符串 |
void write(String str, int off, int len) | 可以写入字符串的指定长度内容 |
flush() | 刷新之后会将之前的数据写入,也可继续写 |
close() | 关闭之前会先刷新,但是关闭后不能再写数据 |
12.2.2 字符输入流
常用:FileReader
方法与字节输入流大同小异
12.2.3 字符缓冲流
构造方法 | |
---|---|
BufferedWriter(Writer out) | 字符缓冲流输出对象 |
BufferedWriter特有的方法:void newLine() | 写一个行分隔符,分隔符字符串根据系统属性而定 |
BufferedReader(Reader in) | 字符缓冲流输入对象 |
BufferedReader特有方法:String readLine() | 读一行,返回到字符串中,读到结尾返回null |
13 转换流
InputStreamReader将字节流输出为字符流
14 对象序列化
序列化:将对象保存到磁盘中,将内存的文件存到主存
反序列化: 将主存文件中的对象读到内存中
序列化时,自定义类需要实现Serializable,还要给定一个
private static final long serialVersionUID = 1L;(数字随意 )
transient 关键字修饰成员变量可以使变量不被序列化和反序列化
15 Properties集合
Map集合的实现类
一点注意事项:调用Properties 的 store(Writer writer,String s)方法时Writer对象要提前创建,不然无法close
Properties的方法,字符流和字节流都可以使用
FileWriter fw = new FileWriter("123.properties");
p.store(fw,"周日");
fw.close();
16 多线程
16.1 线程的三种实现方式
- 第一种:继承Thread类,重写run方法,
测试类中创建子类的对象调用star()
为什么调用star执行的确是run: run是用来封装线程执行内容的方法,调用star()和run()都会有相同的输出结果,但是star是开启了线程,而run是简单的方法调用. - 第二种:实现Runable接口,重写run方法,
测试类中创建实现类对象,创建Thread对象参数为实现类对象,通过Thread调用star() - 第三种:实现callable接口,重写call方法,
测试类中创建实现类对象,创建FutureTask对象参数为实现类对象,创建Thread对象参数为FutureTask的对象,通过Thread调用star()
FutureTask的get方法: 获得线程返回值(只有线程执行完才能得到)
16.2解决线程同步的问题
1.非静态同步方法: public synchronized 返回值 方法名(参数){} 锁对象是this
2.静态同步方法: public synchronized 返回值 方法名(参数){} 锁对象是类名.class
3.同步代码块: synchronized(任意对象){} 注: 解决同步问题的线程使用同一对象!
4.lock方法:Lock接口,通过创建实现类ReentrantLock对象,调用lock()和unlock()方法.
5.阻塞队列:
(1)ArrayBlockingQueue底层是数组,有界
使用方法:
构造方法 | 说明 |
---|---|
ArrayBlockingQueue(int capacity) | 括号内是数组的最大值 |
方法 | 说明 |
void put(E e) | 往数组中添加值 |
take() | 从数组中取出第一个 |
(2)LinkedListBlockingQueue底层是链表,界为int的最大范围
6.唤醒和等待方法
Object对象的方法
方法 | 说明 |
---|---|
void wait() | 使线程进入等待态 |
void notify() | 唤醒一个等待对象监视器的线程 |
void notifyAll() | 唤醒所有等待对象监视器的线程 |
16.3 线程的六种状态
状态 | 说明 |
---|---|
创建态NEW | 新建线程时的状态 |
就绪态RUNABLE | star时的状态 |
无线等待态WAITING | Object.wait()等,指线程等待其他线程的指定操作 |
阻塞态BLOCKED | 当线程想获取锁,但锁被其他线程拥有时 |
计时等待TIME_WAITING | Thread.sleep(long),Object.wait(long)时线程进入计时等待状态 |
死亡态TERMINATED | 运行完成的线程 |
16.4 创建线程池
方法 | 说明 |
---|---|
static ExecutorService newCachedThreadPool() | 线程池的默认创建方法: Executors的静态方法,最多创建int范围的线程,返回值是ExecutorService |
static newFixedThreadPool(int nThreads) | Executors的静态方法,参数是指定的线程个数 |
ThreadPoolExecutor(int 核心线程数,int 最大线程数,int 空闲线程的生命周期(数值),空闲进程的生命周期(单位),阻任务队列,线程工厂,拒绝策略) | ThreadPoolExecutor 的构造方法 |
最长用的是第三种七个参数,其中:
前三个为int,不能<0
第四个:调用TimeUnite.second等方法,
第五个:任务队列一般创建ArrayBlockingQueue<>()对象,参数为阻塞队列线程数
第六个:默认使用Executors.defaultThreadFactory()
第七个:拒绝策略,创建ThreadPoolExecutor.—Policy()对象
方法 | 说明 |
---|---|
ThreadPoolExecutor.AbortPolicy | 丢弃任务并抛出异常 |
ThreadPoolExecutor.DiscardPolicy | 抛弃任务不抛出异常 |
ThreadPoolExecutor.DiscardOldestPolicy | 抛弃等待最久的任务,把当前任务加入队列中 |
ThreadPoolExecutor.CallerRunsPolicy | 调用run方法绕过线程池,main直接执行 |
线程池对象的方法
方法 | 说明 |
---|---|
submit(runnable) | 提交一个线程对象,参数是一个接口类对象,需要实现类,或匿名内部类 |
shutdown() | 关闭线程池 |
16.5Volatile关键字
Volatile 修饰的成员变量,强制每个线程执行的时候需要查看,如果没有volatile关键字,程序也会查看成员变量的值,但是时间不确定.
也可以用Synchronized代码块或方法,
Synchronized原理:
1.获得锁
2.清空副本内容
3.查看共享数据最新内容,复制到副本中.
4.执行代码.
5.将最新值放回共享数据
6.释放锁
缺点很明显,影响进程的进度.
Volatile不能保证原子性
16.6 原子性_AtomicInteger
构造方法 | 说明 |
---|---|
public AtomicInteger() | 初始值为0 |
public AtomicInteger(int initialValue) | 初始值为参数 |
方法 | 说明 |
– | – |
int get() | 获取值 |
int getAndIncrement() | 先获取值然后自增+1 ,i++ |
int incrementAndGet() | 先自增+1在获得值 ++i |
int addAndGet(int data) | 先和参数相加然后获得结果 |
int getAndSet(int value) | 先获得值然后修改内容 |
AtomicInteger底层原理:CAS算法+自旋
三个操作数(内存值V,旧的预期值A,要修改的值B)
A==V 修改成功 V=B
A!=V 修改失败
重新获得最新值(自旋)
16.7乐观锁和悲观锁
乐观锁:每次做判断
悲观锁:每次先上锁
16.8并发工具类
并发安全措施
Map
-
HashTable:
由于HashMap在多线程时存在安全问题,所以出现了HashTable,但是HashTable的原理是对整个Hash表上锁,程序的性能不高,所以出现了CurrentHashMap -
CurrentHashMap:
只对Hash值相同的索引位置上锁,且hash表的长度创建之后不会改变.
java1.7:每次在索引处创建一个可变的数组.
java1.8只对索引出上锁,其余的与hash表相同
性能相对HashTable较高
Collection
- Collections.synchronize单列集合(单列集合对象)
CountDownLatch
妈妈线程等三个孩子线程吃饺子
方法 | 说明 |
---|---|
public CountDownLatch(int count) | 参数传递需要等待的线程数 |
public void await() | 让线程等待 |
public void countDown() | 当前线程执行完毕 |
Semaphore
卡车过点,一次过两个
方法 | 说明 |
---|---|
public Semaphore(int count) | 创建对象,参数是通行证的数量 |
public void acquire() | 获得通行证 |
public void release() | 释放通行证 |
17 网络编程
17.1 UDP的发送与接收
一头羊带着包裹,另一头羊带着箱子收包裹
DatagramSocket和DatagramPacket
单播
方法 | 说明 |
---|---|
DatagramSocket() | 创建套接字对象,发送端空参,接收端有参 |
DatagramPacket(byte[],len,InetAddress,port) | 发送端4个参数,接收端两个 |
void send(DatagramPacket) | |
void close | 发送端关闭 |
void receive(DatagramPacket) |
组播
组播发送端DatagramPacket(bytes , bytes.length,组播地址,端口)
组播地址:224.0.1.0~224.0.1.255是公用组播地址
接收端:接受对象不再是DatagramSocket而是MulticastSocket(端口),把MulticastSocket对象绑定到组播地址,joinGroup()
广播
将单播的发送地址变成广播255.255.255.255
17.2 TCP的发送与接收
客户端
public class TcpClient {
public static void main(String[] args) throws IOException {
Socket s = new Socket("127.0.0.1", 10000);
OutputStream outputStream = s.getOutputStream();
outputStream.write("yduanhua".getBytes());
s.close();
}
}
服务器端
public class TcpService {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
InputStream inputStream = s.getInputStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
String s1 = new String(bytes, 0, len);
System.out.println(s1);
}
}
18.反射
动态的获得信息或对象的成员方法,变量的功能称为java的反射机制
18.1.三种获得类对象的方式
反射需要类对象来获得信息
方法 | 说明 |
---|---|
类名.class | |
Class.forName(“全类名”) | 参数是字符串,其中全类名指某个文件在当前模块的位置,格式为包名.类名 |
对象名.getClass() |
18.2反射通过反射获得构造方法
通过类对象调用方法,获得构造参数
方法 | 说明 |
---|---|
Construct<>[] getConstructs() | 返回public修饰的构造方法 |
Construct<>[] getDeclaredConstruct() | 返回所有构造方法 |
Constructor getConstructor(Class<?>… parameterTypes) | 返回public修饰的固定参数的构造方法,参数是类对象 |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 返回固定参数的构造方法,参数是类对象 |
18.3 反射获得的构造参数构造对象
方法 | 说明 |
---|---|
T newInstance(Object…initargs) | 参数是构造方法的传参数据类型 |
setAccessible(boolean flag) | 当构造方法是private修饰时,需要用此方法获得临时权利 |
18.4 反射获得成员变量
成员变量是private时,获得的Field对象需要调用setAccessible(true)
方法 | 说明 |
---|---|
Field[] getFields() | 获得所有public修饰的成员变量 |
Field[] getDeclaredFields() | 获得所有成员变量 |
Field getField(String name) | 获得Public修饰的固定参数的成员变量,参数为变量名.字符串类型 |
Field getDeclaredField(String name) | 获得任意成员变量,参数为变量名,字符串类型 |
18.5 通过获取成员变量返回的Field对象修改和获得成员变量的值
方法 | 说明 |
---|---|
void set(Object obj, Object value ) | 赋值 |
Object get(Object o) | 获取值 |
18.6 获取成员方法
方法 | 说明 |
---|---|
Method[] getMethods() | 获得所有public修饰的方法 |
Method[] getDeclaredMethods() | 获得所有方法 |
Method getMethod(String name, Class<?>… parameterTypes) | 获得public修饰的特定方法,参数是字符串类型的方法名,方法传参类型的类对象 |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 获得任意一个方法,参数是字符串类型的方法名,方法传参类型的类对象 |
18.7 获得方法后的使用
方法 | 效果 |
---|---|
Object invoke(Object o, Object…args) | 返回值是方法的返回值,参数是调用方法的对象和方法需要的参数 |
19 XML
SAXReader saxReader = new SAXReader();
Document sx = saxReader.read("review/src/XML/Stu.xml");
//获取解析后XML的根标签
Element rootElement = sx.getRootElement();
//获取根标签下元素的集合
List<Element> students = rootElement.elements("student");
ArrayList<Student> arrayList = new ArrayList<>();
//将XML的内容封装成对象
for (Element student : students) {
String name = student.element("name").getText();
Integer age = Integer.valueOf(student.element("age").getText());
arrayList.add(new Student(name, age));
}
DTD约束
本地约束(dtd文件)
<?xml version="1.0" encoding="UTF-8" ?>
<!ELEMENT students (student+)>
<!ELEMENT student (name,age)> <!--student的属性必须按顺序-->
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST student ID CDATA #REQUIRED><!--定义ID-->
<?xml version="1.0" encoding="UTF-8" ?>
<!--引用dtd约束-->
<!DOCTYPE students SYSTEM 'studtd.dtd'>
<students>
<student ID="stu1"> <!--ID必须大写-->
<name>zhang</name>
<age>12</age>
</student>
<student ID="stu2">
<name>wang</name>
<age>34</age>
</student>
</students>
内部约束(XML内部)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students [
<!ELEMENT students (student+)>
<!ELEMENT student (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ATTLIST student ID CDATA #REQUIRED>
]>
<students>
<student ID="stu1">
<name>zhang</name>
<age>12</age>
</student>
<student ID="stu2">
<name>wang</name>
<age>34</age>
</student>
</students>
网络约束(几乎用不到)
20枚举
枚举有什么用:简介表示一些固定值
怎么用:掌握简单的构造方式即可
public enum Season {
SPRING("春"){
@Override
void show() {
}
},
SUMMER {
@Override
void show() {
}
},AUTUMN {
@Override
void show() {
}
},WINTER {
@Override
void show() {
}
};
private String name;
Season(String name) {
this.name = name;
}
Season() {};
abstract void show();
}
枚举中的每个枚举项就是一个对象,抽象方法必须全部重写
21 注解
有什么用:对代码进行标注,解释
注解:写给编译器看,注释:写给程序猿看
以下代码展示注解的重要用法之一,通过反射判断方法是否被注解
@Retention(RetentionPolicy.RUNTIME)//注解的存活时间
public @interface Test {//自定义注解
}
上述代码中的@Retention为元注解,描述注解的注解
元注解 | 说明 |
---|---|
@Target | 指定注解可以是用的地方 |
@Retention | 注解的保留时间 |
@Inherited | 表示自定义注解可以被继承 |
@Documented | 表示当前注解会出现在API文档中 |
public class Method {
@Test
public void method1() {
System.out.println("1");
}
public void method2() {
System.out.println("2");
}
}
public class MethodTest {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class clazz = Class.forName("AnnotationTest.Method");
Method[] declaredMethods = clazz.getDeclaredMethods();
Object o = clazz.newInstance();
for (Method declaredMethod : declaredMethods) {
//判断方法是否有注解
if (declaredMethod.isAnnotationPresent(Test.class)) {
declaredMethod.invoke(o);
}
}
}
}
22单元测试
用于测试公共的没有返回值没有参数的方法
使用方法:
1.将junit的jar包导入工程中
2.创建一个public void 方法(){}
3.方法上注解@Test
4.右键方法测试
相关注解 | 说明 |
---|---|
@Test | 测试该方法 |
@Befor | 测试方法前执行的方法 |
@After | 测试方法后执行的方法 |
23 日志
在开发中记录开发过程的点滴
日志的体系结构
使用方法:
1.导入log4j的jar包
2.编写配置文件log4j.properties,放在src下
3.代码中获取日志对象
4.按照级别设置日志信息
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class);
public static void main(String[] args) {
LOGGER.debug("a");
LOGGER.info("a");
LOGGER.warn("a");
}
}
日志级别:(只显示大于等于配置文件中的日志)
DEBUG < INFO < WARN < ERROR < FATAL