Java 开发总结(SE 篇)

常用 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();
  1. 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新建线程时的状态
就绪态RUNABLEstar时的状态
无线等待态WAITINGObject.wait()等,指线程等待其他线程的指定操作
阻塞态BLOCKED当线程想获取锁,但锁被其他线程拥有时
计时等待TIME_WAITINGThread.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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值