新手小白学java四进阶

  • 一、IO流(文件输入输出)(java.io)
  • IO流的分类
  • IO流的四大类:InputStream(字节输入流)、OutStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流),这四个类都是抽象类
  • 注意:在java中,只要类名以Stream的都是字节流;只要以Reader/Writer结尾的都是字符流
  • 所有的流都实现了Closeable接口,因此所有流使用结束要记得调用close()方法
  • 所有的输出流(OutStream、Writer)都实现了fluentable接口,都是可刷新的,因此在输出流在最终输出后,记得调用flush()方法刷新
  • java.io下常用16个流
  • FileInputStream
  • IDEA的默认当前路径是在:工程project的根目录
  • 读取read
  • 注意:上述读取read方式不常用,以下是开发中读取的正确编写方式:
  • available()方法:返回流中剩余的没有读到的字节数量
  • skip()方法:跳过几个字节不读
  • FileOutputStream
  • write()方法:如果通过这种构造方法FileOutputStream(String name)的形式创建对象,然后使用write()方法写入:谨慎使用,会先把原文件内容清空然后写入
  • 使用FileOutputStream的有参构造方法FileOutputStream(String name, boolean append)其中append处的布尔类型设置为true,之后的write写入就会:以追加的方式在原文件后面写入,不会清空原文件内容
  • 使用FileInputStream与FileOutputStream可以实现文件的复制
  • FileReader:几乎与FileInputStream用法相同,只不过将FileInputStream中的用的byte[]数组变成char[]数组即可
  • FileWriter:几乎与FileOutputStream用法相同,只不过将FileOutputStream中的用的byte[]数组变成char[]数组即可
  • write()方法
  • BufferedReader(带有缓冲区的字符输入流):与之前的in/outStream以及Reader/Writer相比,缓冲区流自带数组,因此无需像之前一样需要我们自己手动创建char[]和byte[]数组
  • 节点流与包装(处理)流:当一个流的构造方法需要传入一个流时,这个被传进来的流叫做节点流;外部负责包装的这个流,叫做包装流,又称处理流。并且关闭close时,只需将bufferedReader关闭即可,无需关闭节点流(因为BufferedReader在执行close()方法时,方法体内部也会执行节点流的close()方法)
  • readLine()方法:读一行
  • 转换流:将字节流转换成字符流InputStreamReader/OutputStreamWriter
  • 比如当一个包装流时BufferedReader想传入一个FileInputStream节点流时,由于类型不同(一个是字节流,一个是字符流),那么可以通过InputStreamReader将字节流FileInputStream转换成字符流Reader然后传入BufferedReader进行使用。
  • 数据流(也是包装流)
  • DataOutputStream:数据专属的流,在写入数据(write+Byte/Short/Int/Long/Double/Float/Boolean/char)时,会把数据内容和数据类型一同写入文件中
  • DataInputStream:字节输入流,DataOutputStream写入的文件,必须只能用DataInputSTream才能正确读出,并且读取时需要提前知道写入的顺序,读的顺序需要和写入的顺序一致,才可以正常取出数据。
  • 标准输出流:PrintWiter/PrintStream
  • PrintStream:标准的字节输出流,默认输出到控制台,无需手动close()
  • 可以手动设置标准输出流的输出方向(可以选择不输出到控制台,可以手动设置输出到其他文件中)
  • File类:文件和目录路径名的抽象表达形式
  • File构造方法
  • File类的常用方法
  • exists()方法:判断文件或目录是否存在
  • creatNewFile()方法:以文件的形式创建一个文件
  • mkdir()方法:以目录的形式创建一个目录
  • mkdirs()方法:以多重目录的形式创建一个多重目录
  • getParent()方法:获取指定文件或者目录的父路径
  • getAbsolutePath()方法:获取绝对路径
  • getName()方法:获取文件名
  • isDirectory()方法:判断是目录还是文件
  • lastModified()方法:文件最后一个被修改的时间
  • length()方法:获取文件大小是多少字节
  • listFiles()方法:获取当前目录下的所有子文件
  • ObjectOutputStream:用于实现序列化Serialize
  • 序列化的实现:注意,参与序列化的对象必须实现Serializable接口
  • ObjectInputStream:用于实现反序列化Deserialize
  • 反序列化的对象也需要实现Serializable接口
  • 序列化与反序列化集合
  • 一次序列化多个对象:即将对象放到集合中,然后将集合序列化
  • 反序列化集合
  • transient关键字:用来不参加序列化操作
  • 关于序列化版本号(用于区分同名的类)
  • 注意:不建议自动生成序列化版本号,建议我们手动写出来赋值
  • IO 与properties的联合使用:对于一些需要经常修改的信息,可以将其单独写到一个文件(属性配置文件)中,让程序动态读取。这样一来,就算里面的内容被修改,java代码无需改动,也无需重新编译,服务器也无需重启,就可以动态的获得新信息。
  • 线程
  • 进程A的内存与进程B的内存是独立,不共享的
  • 而在java中,线程A和线程B是共享堆内存和方法区内存;但是栈内存是独立的,一个线程有其自己单独的一个栈内存。各自可以同时执行,互不影响,这就是多线程。
  • 单核并不能真正实现多线程并发
  • 实现进程的两种方式
  • 第一种:编写一个类,直接继承java.long.Thead,必须重写run方法。
  • 注意:run()方法与start()方法的区别!!!!
  • 第二种(更常用):编写一个类,实现java.lang.Runnable接口,实现run方法
  • 第二种还可以采用匿名内部类的方式
  • 修改/获取线程名字的方法:setName()和getName()
  • 注意:当线程没有设置名字时,默认名字是:Thread-0,Thread-1,等等
  • 获取当前线程对象:currentThread()静态方法
  • 线程的sleep()静态方法
  • sleep面试题
  • 终止睡眠的线程(即唤醒)的方法:interrupt()方法
  • 同时注意:run()方法中的异常不能throws抛给上级,只能用try catch。因为run()方法在父类(Runnale接口)中没有抛出任何异常,因此由于子类不能比父类抛出更多的异常,所以run()方法中只能用try catch来解决异常,而不能通过throws抛给上级。
  • 强行终止线程的执行:stop()方法——已过时,不建议使用
  • 合理终止线程的执行(常用):在线程中设置一个boolean的成员变量即可
  • 线程调度
  • 线程优先级:获取线程优先级方法:getPriority()
  • Thread.yield()静态方法:线程让位,让当前的线程暂停回到就绪态,让给其他线程
  • join()方法:线程合并
  • 线程安全!!!!!!
  • 线程不安全的条件
  • 解决线程安全:线程同步机制:线程排队执行,不能并发执行
  • 同步与异步
  • 线程同步机制:同步代码块 synchronized
  • 注意:局部变量永远不会有线程安全问题
  • synchronized还可以用在实例方法上进行修饰,用来锁this表示的对象。
  • synchronized也可以用于修饰静态方法,是类锁,将此类全部锁住排队!!!!
  • synchronized小总结
  • 死锁:持有某个资源去请求另一个资源时容易发生,因此不建议嵌套使用synchronized
  • 开发中应该如何解决安全问题
  • 守护线程:又称后台线程,如垃圾回收线程,当用户线程结束后,守护进程自动结束
  • 守护进程的实现:setDaemon()方法
  • 定时器java.util.Timer:间隔特定的时间,执行特定的程序
  • 定时器的实现:
  • 定时器例子:定时备份
  • 实现线程的第三种方式(JDK8以后的新特性):实现Callable接口(其中的call()方法相当于线程中的run()方法)
  • wait()和notify()方法:是Object类中的方法,而不是线程的方法
  • 生产者和消费者:
  • 反射机制:通过反射机制可以操作j字节码文件
  • 获取Class的三种方式:要操作一个类的字节码,收下你需要获取这个类的字节码即Class
  • 第一种:Class.forName()静态方法
  • 第二种方式:通过Object祖先级别的类中的getClass()方法
  • 第三种方式:类.class
  • 通过反射来实例化对象
  • 反射机制灵活性
  • forName()方法的发生:若只想执行静态代码块,可以使用forName()方法
  • 获取类路径下(在src下的都是类路径下的)文件的绝对路径
  • 直接以流的方式返回而无需获取绝对路径:getResourceAsStream()
  • 资源绑定器ResourceBundle:sun公司写好的,用来获取属性配置文件中的内容,注意,仅能用于绑定properties属性文件(即文件扩展名为properties),且此文件必须在类路径下,并且扩展名properties省略不写。
  • 类加载器
  • 反射机制小总结
  • 使用反射获取属性field
  • getFields()方法是获得目标类中的public修饰的属性filed。
  • getDeclaredFields()方法获取目标类中声明的所有属性
  • 获取一个类的类名:getName()和getSimpleName()方法
  • 获取指定类中的属性的类型:getType()方法
  • 获取指定类中的属性的修饰符列表:getModifiers()方法:返回一个数字,数字对应着修饰符的代号。将数字转换成对应的修饰符,用静态方法Modifier.toString(int i)
  • 通过反射机制,反编译一个类的属性field(略)
  • 通过反射机制,访问对象的属性
  • 注意:反射机制的一大缺点:可以打破封装(setAccessible(true)),直接在外部给私有属性赋值
  • 可变长度参数:类型后面跟三个点:如int... args
  • 反射机制中的Method
  • 获取类中所有的method:getDeclaredMethods()方法
  • 获取类中方法的返回值类型:getReturnType()方法;同理,获取方法的修饰符类型:getModifiers()方法
  • 获取方法中形式参数列表的类型:getParameterTypes()方法
  • 反编译 Method(了解,略)
  • 通过反射机制,调用一个对象(注意不是类)的方法:获取类,new对象,获取方法,然后使用invoke()方法调用对象的方法!!!******
  • 反射Constructor构造方法
  • 获取构造方法:getDeclaredConstructors()方法
  • 通过反射机制调用构造方法实例化对象:和之前的一样,对于无参构造方法:直接获取类,然后类名.newInstance()方法即可;对于有参构造:先获取有参构造方法(getDeclaredConstructor(形参)),然后调用构造方法new对象即可
  • 通过反射机制获取父类(getSuperClass()方法)和父接口(getInterfaces()方法)
  • 注解/注释类型Annotation:是一种引用数据类型
  • 注解定义与使用
  • JDK已经内置的注解类:java.lang包中有Deprecated过时的、Override重写、SuppressWarnings三种注解
  • override注解:只能注解方法,只在编译阶段起作用,与运行期无关
  • 元注解:就是修饰注解的注解,主要有Target和Tetention
  • 元注解Retention:表示目标只能保存在XX中
  • 元注解target:表示目标只能出现在xxx中,即只允许标注xxx
  • Deprecated表示已过时的:可以用来注解类、方法、变量等等
  • 注解中定义属性
  • 注意:如果一个注解的属性的名字是value的话,并且只有一个的话,使用时,该属性名value可以省略不写。(有两个叫value的属性不行)
  • 注解中的属性可以是哪些类型?
  • 通过反射机制获取注解
  • 通过反射机制获取注解对象中属性的值
  • 注解在开发中的作用


一、IO流(文件输入输出)(java.io)

IO流的分类

java进阶视频 java进阶教程_多线程

IO流的四大类:InputStream(字节输入流)、OutStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流),这四个类都是抽象类

java进阶视频 java进阶教程_java进阶视频_02

注意:在java中,只要类名以Stream的都是字节流;只要以Reader/Writer结尾的都是字符流

所有的流都实现了Closeable接口,因此所有流使用结束要记得调用close()方法

java进阶视频 java进阶教程_java进阶视频_03

所有的输出流(OutStream、Writer)都实现了fluentable接口,都是可刷新的,因此在输出流在最终输出后,记得调用flush()方法刷新

java进阶视频 java进阶教程_编程语言_04

java.io下常用16个流

java进阶视频 java进阶教程_java_05

FileInputStream

java进阶视频 java进阶教程_jvm_06


java进阶视频 java进阶教程_jvm_07

IDEA的默认当前路径是在:工程project的根目录

java进阶视频 java进阶教程_多线程_08

读取read

java进阶视频 java进阶教程_多线程_09


int read(byte[] b):返回值是读取到的字节的数量,而不是值本身

以读取存储"abcdef"的txt文件为例:

java进阶视频 java进阶教程_java_10


如何把读取的内容依次输出:

java进阶视频 java进阶教程_jvm_11

注意:上述读取read方式不常用,以下是开发中读取的正确编写方式:

初版:

java进阶视频 java进阶教程_java_12


终极改进版:

java进阶视频 java进阶教程_jvm_13


catch与finally中的内容同上

available()方法:返回流中剩余的没有读到的字节数量

java进阶视频 java进阶教程_java进阶视频_14


仍以读取“abcdef”为例:

java进阶视频 java进阶教程_jvm_15

skip()方法:跳过几个字节不读

java进阶视频 java进阶教程_编程语言_16


仍以读取“abcdef”为例:

java进阶视频 java进阶教程_编程语言_17

FileOutputStream

write()方法:如果通过这种构造方法FileOutputStream(String name)的形式创建对象,然后使用write()方法写入:谨慎使用,会先把原文件内容清空然后写入

java进阶视频 java进阶教程_jvm_18


java进阶视频 java进阶教程_java_19

使用FileOutputStream的有参构造方法FileOutputStream(String name, boolean append)其中append处的布尔类型设置为true,之后的write写入就会:以追加的方式在原文件后面写入,不会清空原文件内容

java进阶视频 java进阶教程_编程语言_20


java进阶视频 java进阶教程_java进阶视频_21


此时,会自动在原文件的末尾写入,而不会清空原文件内容再写入

使用FileInputStream与FileOutputStream可以实现文件的复制

java进阶视频 java进阶教程_java进阶视频_22


java进阶视频 java进阶教程_多线程_23

FileReader:几乎与FileInputStream用法相同,只不过将FileInputStream中的用的byte[]数组变成char[]数组即可

整体框架一模一样:

java进阶视频 java进阶教程_jvm_24


java进阶视频 java进阶教程_多线程_25

FileWriter:几乎与FileOutputStream用法相同,只不过将FileOutputStream中的用的byte[]数组变成char[]数组即可

java进阶视频 java进阶教程_java进阶视频_26

write()方法

java进阶视频 java进阶教程_多线程_27

BufferedReader(带有缓冲区的字符输入流):与之前的in/outStream以及Reader/Writer相比,缓冲区流自带数组,因此无需像之前一样需要我们自己手动创建char[]和byte[]数组

java进阶视频 java进阶教程_java进阶视频_28

节点流与包装(处理)流:当一个流的构造方法需要传入一个流时,这个被传进来的流叫做节点流;外部负责包装的这个流,叫做包装流,又称处理流。并且关闭close时,只需将bufferedReader关闭即可,无需关闭节点流(因为BufferedReader在执行close()方法时,方法体内部也会执行节点流的close()方法)

java进阶视频 java进阶教程_java进阶视频_29

readLine()方法:读一行

java进阶视频 java进阶教程_jvm_30

java进阶视频 java进阶教程_编程语言_31

转换流:将字节流转换成字符流InputStreamReader/OutputStreamWriter

java进阶视频 java进阶教程_java进阶视频_32

比如当一个包装流时BufferedReader想传入一个FileInputStream节点流时,由于类型不同(一个是字节流,一个是字符流),那么可以通过InputStreamReader将字节流FileInputStream转换成字符流Reader然后传入BufferedReader进行使用。

java进阶视频 java进阶教程_编程语言_33

数据流(也是包装流)

DataOutputStream:数据专属的流,在写入数据(write+Byte/Short/Int/Long/Double/Float/Boolean/char)时,会把数据内容和数据类型一同写入文件中

java进阶视频 java进阶教程_java进阶视频_34


java进阶视频 java进阶教程_多线程_35

DataInputStream:字节输入流,DataOutputStream写入的文件,必须只能用DataInputSTream才能正确读出,并且读取时需要提前知道写入的顺序,读的顺序需要和写入的顺序一致,才可以正常取出数据。

java进阶视频 java进阶教程_多线程_36

标准输出流:PrintWiter/PrintStream

PrintStream:标准的字节输出流,默认输出到控制台,无需手动close()

java进阶视频 java进阶教程_多线程_37

可以手动设置标准输出流的输出方向(可以选择不输出到控制台,可以手动设置输出到其他文件中)

java进阶视频 java进阶教程_java进阶视频_38


例子:手写一个日志工具

定义一个日志类:

java进阶视频 java进阶教程_编程语言_39


进行测试:

java进阶视频 java进阶教程_编程语言_40


输出结果:

java进阶视频 java进阶教程_多线程_41

File类:文件和目录路径名的抽象表达形式

java进阶视频 java进阶教程_编程语言_42

File构造方法

java进阶视频 java进阶教程_java_43


java进阶视频 java进阶教程_多线程_44

File类的常用方法

exists()方法:判断文件或目录是否存在

java进阶视频 java进阶教程_多线程_45

creatNewFile()方法:以文件的形式创建一个文件

java进阶视频 java进阶教程_java进阶视频_46

mkdir()方法:以目录的形式创建一个目录

java进阶视频 java进阶教程_多线程_47

mkdirs()方法:以多重目录的形式创建一个多重目录

java进阶视频 java进阶教程_jvm_48

getParent()方法:获取指定文件或者目录的父路径

java进阶视频 java进阶教程_java_49

getAbsolutePath()方法:获取绝对路径

getName()方法:获取文件名

java进阶视频 java进阶教程_java进阶视频_50


java进阶视频 java进阶教程_多线程_51

isDirectory()方法:判断是目录还是文件

java进阶视频 java进阶教程_编程语言_52


java进阶视频 java进阶教程_编程语言_53

lastModified()方法:文件最后一个被修改的时间

java进阶视频 java进阶教程_java进阶视频_54


java进阶视频 java进阶教程_java_55

length()方法:获取文件大小是多少字节

java进阶视频 java进阶教程_java进阶视频_56

listFiles()方法:获取当前目录下的所有子文件

java进阶视频 java进阶教程_编程语言_57


java进阶视频 java进阶教程_编程语言_58

ObjectOutputStream:用于实现序列化Serialize

用于将java对象存储到硬盘文件中,是将java对象保存下来的过程。

java进阶视频 java进阶教程_java进阶视频_59

序列化的实现:注意,参与序列化的对象必须实现Serializable接口

java进阶视频 java进阶教程_多线程_60

java进阶视频 java进阶教程_java_61


java进阶视频 java进阶教程_java进阶视频_62

ObjectInputStream:用于实现反序列化Deserialize

用于将硬盘上的数据恢复到内存中,并恢复成java对象的过程。

反序列化的对象也需要实现Serializable接口

java进阶视频 java进阶教程_编程语言_63

序列化与反序列化集合

一次序列化多个对象:即将对象放到集合中,然后将集合序列化

java进阶视频 java进阶教程_jvm_64

反序列化集合

java进阶视频 java进阶教程_jvm_65

transient关键字:用来不参加序列化操作

java进阶视频 java进阶教程_java_66

关于序列化版本号(用于区分同名的类)

java进阶视频 java进阶教程_java_67

java进阶视频 java进阶教程_java进阶视频_68


从ArrayList的源代码学习手动设置序列化版本号:

java进阶视频 java进阶教程_编程语言_69

注意:不建议自动生成序列化版本号,建议我们手动写出来赋值

IO 与properties的联合使用:对于一些需要经常修改的信息,可以将其单独写到一个文件(属性配置文件)中,让程序动态读取。这样一来,就算里面的内容被修改,java代码无需改动,也无需重新编译,服务器也无需重启,就可以动态的获得新信息。

java进阶视频 java进阶教程_java_70


java进阶视频 java进阶教程_编程语言_71


属性配置文件内部的格式:

java进阶视频 java进阶教程_java_72

线程

进程A的内存与进程B的内存是独立,不共享的

而在java中,线程A和线程B是共享堆内存和方法区内存;但是栈内存是独立的,一个线程有其自己单独的一个栈内存。各自可以同时执行,互不影响,这就是多线程。

java进阶视频 java进阶教程_多线程_73


java进阶视频 java进阶教程_多线程_74

单核并不能真正实现多线程并发

java进阶视频 java进阶教程_多线程_75

实现进程的两种方式

第一种:编写一个类,直接继承java.long.Thead,必须重写run方法。

java进阶视频 java进阶教程_java进阶视频_76

java进阶视频 java进阶教程_java_77


以下面例子:

java进阶视频 java进阶教程_java进阶视频_78


首先main方法会通过一个主线程执行(在一个栈区),当代码执行到myThread.start()时,此时start()方法会开辟出另一块栈内存空间,一旦开辟出来空间,start()方法就结束了,mian方法会继续往下执行。而与此同时,由于start()开启了myThread线程,因此在新开辟的myThead栈内存区会自动调用run方法(类似于main)执行。因此,main方法在start()代码执行结束之后,main的主线程与myThread的分支线程并发,同时执行。

注意:run()方法与start()方法的区别!!!!

java进阶视频 java进阶教程_java进阶视频_79


只有执行start()才会去为新的线程开辟新的栈内存。

而如上图所示,在main方法中调用myThead.run()方法,和普通的方法调用一样,在main方法的栈区调用run()方法压栈,然后执行,而不会开辟新的线程,也不能实现并发,只有执行完run()方法体重的代码后,main方法才会继续往下执行。

java进阶视频 java进阶教程_编程语言_80

java进阶视频 java进阶教程_jvm_81

第二种(更常用):编写一个类,实现java.lang.Runnable接口,实现run方法

java进阶视频 java进阶教程_编程语言_82

java进阶视频 java进阶教程_编程语言_83

第二种还可以采用匿名内部类的方式

java进阶视频 java进阶教程_多线程_84

修改/获取线程名字的方法:setName()和getName()

java进阶视频 java进阶教程_jvm_85

注意:当线程没有设置名字时,默认名字是:Thread-0,Thread-1,等等

获取当前线程对象:currentThread()静态方法

这是java.lang.Thread包下的方法:currentThread()

java进阶视频 java进阶教程_jvm_86


java进阶视频 java进阶教程_编程语言_87

线程的sleep()静态方法

java进阶视频 java进阶教程_java_88

java进阶视频 java进阶教程_java_89


java进阶视频 java进阶教程_java_90

sleep面试题

java进阶视频 java进阶教程_jvm_91


注意:sleep()是Thread类的静态方法,即使用引用.sleep()的方式去调用sleep方法,但本质还是会转换成类名Thread.sleep()的方法执行,来阻塞sleep代码所在当前的线程。

终止睡眠的线程(即唤醒)的方法:interrupt()方法

java进阶视频 java进阶教程_java进阶视频_92

同时注意:run()方法中的异常不能throws抛给上级,只能用try catch。因为run()方法在父类(Runnale接口)中没有抛出任何异常,因此由于子类不能比父类抛出更多的异常,所以run()方法中只能用try catch来解决异常,而不能通过throws抛给上级。

java进阶视频 java进阶教程_java进阶视频_93

强行终止线程的执行:stop()方法——已过时,不建议使用

缺点:容易丢失数据,因为这种方式是直接杀死线程,线程没有保存的数据会丢失。

合理终止线程的执行(常用):在线程中设置一个boolean的成员变量即可

java进阶视频 java进阶教程_多线程_94


我们可以在else中的方法体中执行保存数据的操作,将数据保存完毕之后再return即可。

java进阶视频 java进阶教程_编程语言_95

线程调度

java进阶视频 java进阶教程_java进阶视频_96


java进阶视频 java进阶教程_java_97

线程优先级:获取线程优先级方法:getPriority()

java进阶视频 java进阶教程_编程语言_98


最高10,默认5,最低1

Thread.yield()静态方法:线程让位,让当前的线程暂停回到就绪态,让给其他线程

join()方法:线程合并

java进阶视频 java进阶教程_java进阶视频_99

线程安全!!!!!!

java进阶视频 java进阶教程_java_100

线程不安全的条件

java进阶视频 java进阶教程_jvm_101


java进阶视频 java进阶教程_java_102

解决线程安全:线程同步机制:线程排队执行,不能并发执行

java进阶视频 java进阶教程_jvm_103

同步与异步

java进阶视频 java进阶教程_java_104

线程同步机制:同步代码块 synchronized

线程同步机制的语法:

synchronized(){

}

其中小括号()中的对象是,被若干指定线程共享的对象,从而实现若干指定线程对此对象的访问需要排队,而不能同时进行,从而实现了线程的安全和同步。

java进阶视频 java进阶教程_java_105


java进阶视频 java进阶教程_编程语言_106

注意:局部变量永远不会有线程安全问题

java进阶视频 java进阶教程_java进阶视频_107

synchronized还可以用在实例方法上进行修饰,用来锁this表示的对象。

java进阶视频 java进阶教程_java进阶视频_108


java进阶视频 java进阶教程_jvm_109

java进阶视频 java进阶教程_java_110


java进阶视频 java进阶教程_java进阶视频_111

synchronized也可以用于修饰静态方法,是类锁,将此类全部锁住排队!!!!

synchronized小总结

java进阶视频 java进阶教程_编程语言_112


以上都是排它锁

还有互斥锁(后续学习)

死锁:持有某个资源去请求另一个资源时容易发生,因此不建议嵌套使用synchronized

开发中应该如何解决安全问题

java进阶视频 java进阶教程_jvm_113

守护线程:又称后台线程,如垃圾回收线程,当用户线程结束后,守护进程自动结束

java进阶视频 java进阶教程_编程语言_114

守护进程的实现:setDaemon()方法

java进阶视频 java进阶教程_java进阶视频_115


java进阶视频 java进阶教程_编程语言_116

定时器java.util.Timer:间隔特定的时间,执行特定的程序

java进阶视频 java进阶教程_编程语言_117

定时器的实现:

java进阶视频 java进阶教程_jvm_118

java进阶视频 java进阶教程_多线程_119


java进阶视频 java进阶教程_多线程_120

定时器例子:定时备份

java进阶视频 java进阶教程_多线程_121


java进阶视频 java进阶教程_jvm_122

实现线程的第三种方式(JDK8以后的新特性):实现Callable接口(其中的call()方法相当于线程中的run()方法)

java进阶视频 java进阶教程_编程语言_123

java进阶视频 java进阶教程_多线程_124


java进阶视频 java进阶教程_java进阶视频_125

wait()和notify()方法:是Object类中的方法,而不是线程的方法

java进阶视频 java进阶教程_多线程_126


java进阶视频 java进阶教程_多线程_127

生产者和消费者:

java进阶视频 java进阶教程_多线程_128

反射机制:通过反射机制可以操作j字节码文件

java进阶视频 java进阶教程_编程语言_129


java进阶视频 java进阶教程_多线程_130

获取Class的三种方式:要操作一个类的字节码,收下你需要获取这个类的字节码即Class

java进阶视频 java进阶教程_多线程_131

第一种:Class.forName()静态方法

java进阶视频 java进阶教程_多线程_132


java进阶视频 java进阶教程_jvm_133

第二种方式:通过Object祖先级别的类中的getClass()方法

java进阶视频 java进阶教程_java_134


java进阶视频 java进阶教程_jvm_135


java进阶视频 java进阶教程_编程语言_136

第三种方式:类.class

java进阶视频 java进阶教程_java_137

通过反射来实例化对象

java进阶视频 java进阶教程_编程语言_138


java进阶视频 java进阶教程_java进阶视频_139

反射机制灵活性

java进阶视频 java进阶教程_java进阶视频_140


java进阶视频 java进阶教程_java_141

forName()方法的发生:若只想执行静态代码块,可以使用forName()方法

java进阶视频 java进阶教程_jvm_142


java进阶视频 java进阶教程_多线程_143

获取类路径下(在src下的都是类路径下的)文件的绝对路径

java进阶视频 java进阶教程_java进阶视频_144


java进阶视频 java进阶教程_java_145

直接以流的方式返回而无需获取绝对路径:getResourceAsStream()

java进阶视频 java进阶教程_jvm_146

资源绑定器ResourceBundle:sun公司写好的,用来获取属性配置文件中的内容,注意,仅能用于绑定properties属性文件(即文件扩展名为properties),且此文件必须在类路径下,并且扩展名properties省略不写。

java进阶视频 java进阶教程_java_147

类加载器

java进阶视频 java进阶教程_jvm_148


java进阶视频 java进阶教程_jvm_149

反射机制小总结

java进阶视频 java进阶教程_java进阶视频_150


java进阶视频 java进阶教程_java进阶视频_151


java进阶视频 java进阶教程_java进阶视频_152


java进阶视频 java进阶教程_jvm_153

使用反射获取属性field

java进阶视频 java进阶教程_jvm_154


以自己定义的student类为例:

java进阶视频 java进阶教程_编程语言_155

getFields()方法是获得目标类中的public修饰的属性filed。

java进阶视频 java进阶教程_java_156

getDeclaredFields()方法获取目标类中声明的所有属性

java进阶视频 java进阶教程_编程语言_157


java进阶视频 java进阶教程_java进阶视频_158

获取一个类的类名:getName()和getSimpleName()方法

java进阶视频 java进阶教程_多线程_159

获取指定类中的属性的类型:getType()方法

java进阶视频 java进阶教程_多线程_160

获取指定类中的属性的修饰符列表:getModifiers()方法:返回一个数字,数字对应着修饰符的代号。将数字转换成对应的修饰符,用静态方法Modifier.toString(int i)

java进阶视频 java进阶教程_java进阶视频_161

通过反射机制,反编译一个类的属性field(略)

通过反射机制,访问对象的属性

java进阶视频 java进阶教程_编程语言_162

注意:反射机制的一大缺点:可以打破封装(setAccessible(true)),直接在外部给私有属性赋值

java进阶视频 java进阶教程_多线程_163

可变长度参数:类型后面跟三个点:如int… args

java进阶视频 java进阶教程_java进阶视频_164


java进阶视频 java进阶教程_java进阶视频_165


java进阶视频 java进阶教程_jvm_166

反射机制中的Method

获取类中所有的method:getDeclaredMethods()方法

java进阶视频 java进阶教程_java_167

获取类中方法的返回值类型:getReturnType()方法;同理,获取方法的修饰符类型:getModifiers()方法

java进阶视频 java进阶教程_java_168

获取方法中形式参数列表的类型:getParameterTypes()方法

java进阶视频 java进阶教程_多线程_169

反编译 Method(了解,略)

通过反射机制,调用一个对象(注意不是类)的方法:获取类,new对象,获取方法,然后使用invoke()方法调用对象的方法!!!******

java进阶视频 java进阶教程_java进阶视频_170

java进阶视频 java进阶教程_java_171

java进阶视频 java进阶教程_java进阶视频_172

反射Constructor构造方法

获取构造方法:getDeclaredConstructors()方法

通过反射机制调用构造方法实例化对象:和之前的一样,对于无参构造方法:直接获取类,然后类名.newInstance()方法即可;对于有参构造:先获取有参构造方法(getDeclaredConstructor(形参)),然后调用构造方法new对象即可

java进阶视频 java进阶教程_多线程_173

通过反射机制获取父类(getSuperClass()方法)和父接口(getInterfaces()方法)

java进阶视频 java进阶教程_多线程_174

注解/注释类型Annotation:是一种引用数据类型

注解定义与使用

[修饰符列表] @interface 注解类型名{

}

java进阶视频 java进阶教程_java_175

java进阶视频 java进阶教程_java进阶视频_176

JDK已经内置的注解类:java.lang包中有Deprecated过时的、Override重写、SuppressWarnings三种注解

java进阶视频 java进阶教程_java进阶视频_177

override注解:只能注解方法,只在编译阶段起作用,与运行期无关

java进阶视频 java进阶教程_多线程_178

元注解:就是修饰注解的注解,主要有Target和Tetention

java进阶视频 java进阶教程_java_179


java进阶视频 java进阶教程_jvm_180


并且可以在运行时被反射机制所读取。

元注解Retention:表示目标只能保存在XX中

java进阶视频 java进阶教程_编程语言_181

元注解target:表示目标只能出现在xxx中,即只允许标注xxx

java进阶视频 java进阶教程_java进阶视频_182

Deprecated表示已过时的:可以用来注解类、方法、变量等等

java进阶视频 java进阶教程_多线程_183


别人调用时,会发现已过时的方法中间会有一道横杠。

java进阶视频 java进阶教程_java_184

注解中定义属性

java进阶视频 java进阶教程_java进阶视频_185


java进阶视频 java进阶教程_jvm_186

注意:如果一个注解的属性的名字是value的话,并且只有一个的话,使用时,该属性名value可以省略不写。(有两个叫value的属性不行)

java进阶视频 java进阶教程_java_187

注解中的属性可以是哪些类型?

java进阶视频 java进阶教程_java_188


在使用注解的时候,如果属性数组中只有一个元素,大括号可以省略

通过反射机制获取注解

java进阶视频 java进阶教程_多线程_189

通过反射机制获取注解对象中属性的值

java进阶视频 java进阶教程_java进阶视频_190

注解在开发中的作用