java学习知识点2

13  泛型

14  线程

76be578d65e54e089acff5b10fa32fda.png

程序是为了完成特定任务,用某种语言编写的一组指令的集合

进程是运行中的程序,操作系统为进程分配内存空间

进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程,有自身的产生,存在和消亡的过程

线程是进程创建的,是进程的实体,一个进程可以有多个线程

并发指同一时刻多个任务交替执行,造成貌似同时的错觉

并行指同一时刻多个任务同时进行,多核cpu并行执行

14.1 线程创建

方法一:继承Thread类,重写run方法

继承Thread类的类可以当做线程使用,需要重写run方法,写上自己的业务代码,实际上是实现了Runnable接口的run方法

方法二:实现Runnable接口,重写run方法。一般用于多个线程共享一个资源的情况,避免了单继承限制

因为java是单继承的,有些类已经继承了其他父类,无法再继承Thread类,所以可以通过实现Runnable接口来创建线程

一样需要重写run方法,但是该接口没有start方法,需要通过创建Thread对象,形参为线程类,通过Thread类的start方法创建线程

底层使用了设计模式中的代理模式

方法三:实现Callable接口,重写call方法。当线程终止时无法返回结果,可以实现有返回值的call方法,call方法可以引发异常,但run方法不行。不能直接替换Runnable,因为Thread构造方法没有Callable

通过FutureTask类作为Runnable和Callable的中介类,该类实现了Runnable接口,同时构造器可以传递Callable。

使用时创建FutureTask<返回值类型>对象,构造器参数为新的Callable类对象(基本方法),参数为()->{call实现方法}(lam表达式)。然后创建线程,传入FutureTask对象.start()

get方法可以获取线程执行结果

isDone方法可以获取线程状态(是否执行完毕)

在线程任务量大时可以新开线程帮助处理,最后处理完毕统一一次合并

方法四:线程池方式

14.2 线程方法

Thread.sleep(毫秒数)

14.3 线程使用过程

进程会创建main主线程,主线程中可以通过start创建子线程

可以在控制台使用jconsole监控线程执行情况

主线程退出不代表子线程也退出,在所有线程都执行完毕后,结束进程

希望主线程结束后子线程也结束可以设置为守护线程

想在main线程中终止子线程,可以修改子线程中用于保持循环的flag变量,在子线程中提供set方法修改flag变量,使其退出run方法

14.4 start和run方法

run方法只是普通方法,没有启动线程,仍然是串行化执行,会使程序阻塞在run方法处,执行完毕才会继续执行后续代码

start方法才会启动线程,首先启动native方法start0,启动多线程

14.5 Thread代理类

Thread代理类实现了Runnable接口,内部有私有的Runnable属性,构造器形参就是该私有属性,重写了run方法,有start方法,方法内调用start0方法,start0方法内部调用run方法,run方法判断Runnable属性是否为空,不为空则执行Runnable对象的run方法

使用时只需要将同样实现了Runnable接口的对象作为实参传入即可

执行时使用start创建,执行start0方法,调用run方法,进入代理对象,会动态绑定至传入类型的运行类型,执行我们写好的run方法

14.6 线程常用方法

setName设置线程名称

getName返回线程名称

getState获取线程状态

start使线程开始执行,底层会创建新的线程,调用run

run调用线程对象run方法,不会启动新的线程

setPriority更改线程优先级,优先级最大是10,最小是1,NORM为5

getPriority获取线程优先级

sleep在指定毫秒数内让正在执行的线程休眠

interrupt中断线程,但没有结束线程,一般用于中断正在休眠的线程,当线程执行到interrupt时,可以catch一个异常,加入自己的业务代码

yield线程礼让,让出CPU给其他线程,但是礼让时间不确定,不一定礼让成功(进入内核态由CPU决定)资源丰富时礼让不成功

join线程插队,插队的线程插队成功则一定先执行完插队的线程的所有任务

14.7 用户线程和守护线程

用户线程也叫工作线程,当线程的任务执行完或通知方式结束

守护线程一般是为用户线程服务的,当所有用户线程结束,守护线程自动结束

常见的守护线程:垃圾回收机制

希望主线程结束后子线程也结束可以通过setDaemon(true)方法设置为守护线程

14.8 线程生命周期

NEW尚未启动的线程

RUNNABLE在JVM中执行的线程

BLOCKED被阻塞等待监视器锁定的线程

WAITING正在等待另一个线程执行特定动作的线程

TIMED_WAITING等待另一个线程执行动作达到指定等待时间的线程

TERMINATED退出的线程

14.9 线程同步

14.9.1 Synchronized

线程同步保证数据在同一时刻最多只有一个线程访问

1.同步代码块synchronized(对象/this){被同步代码},得到对象的锁才能操作同步代码

2.方法声明时在访问修饰符后加synchronized

14.9.2 互斥锁

互斥锁用于保证数据操作的完整性,每个对象对应一个互斥锁标记,该标记保证任意时刻只能有一个线程访问该对象,会导致程序执行效率降低

synchronized用来连接互斥锁

非静态同步方法的锁可以是this,也可以是其他对象,但要求是同一对象

静态同步方法的锁是当前类本身,在类.class上

14.9.3 写一个死锁

主线程中创建两个线程对象,分别传入true和false

分别对象.start()方法启动线程

线程类构造器形参传入flag

分别有两个对象属性o1和o2,以及flag

public void run{

if(flag){

         synchronized(o1){

                执行代码

                synchronized(o2){

                        执行代码                

                        }        

                }

        }else{

        synchronized(o2){

                执行代码

                synchronized(o1){

                        执行代码

                        }

                }

        }        

}

14.9.4 释放锁

1.线程同步代码块或方法执行结束

2.线程在同步代码块或方法中遇到break,return

3.线程同步代码块或方法中出现了未处理的error或Exception,导致异常结束

4.线程同步代码块或方法中执行了线程对象的wait方法,当前线程暂停,并释放锁

14.9.5 不释放锁

1.线程执行同步代码块或方法时,调用了Thread.sleep,yield方法暂停线程执行

2.线程执行同步代码块或方法时,其他线程调用了该线程的suspend方法将线程挂起(不推荐使用)

15 IO

de05757b4dff4dfdad5780306587a08a.png

cf0aae590f234ea9bbd13d528999db92.png

文件是保存数据的地方,文件在程序中以流的形式操作

15.1 文件对象构造器和方法

File(pathname)根据路径构建一个File对象,路径以字符串形式存储(路径中的\需要转义)

File(父目录文件,子路径)根据父目录+子路径构建

File(父目录,子路径)根据父目录+子路径构建

File对象只是在内存中,想要写入磁盘需要通过文件对象创建文件:file.createNewFile(需要处理IO异常)

getName获取文件名

getAbsolutePath获取绝对路径

getParent获取父目录

length文件字节大小

exits是否存在该文件

isFile是否是文件

isDirectory是否是目录

mkdir创建一级目录(在java中,目录也被当做文件)

mkdirs创建多级目录

delete删除空目录或文件

15.2 节点流

java中数据的输入和输出是以流(stream)的形式进行

输入流是数据从数据源文件到程序内存的路径,反之为输出流

流按数据单位分为字节流(8bit)和字符流

流按流向分为输入流和输出流

流按角色分为节点流和处理/包装流

字节输入流InputStream,字节输出流OutputStream

字符输入流Reader,字符输出流Writer

上述四个都是抽象类,其他IO流的类都是由上述四个类派生出的

字节流传输二进制文件不会造成文件传输损失,字符流传输文本文件更适合

15.2.1 字节输入流InputStream

常用子类:FileInputStream文件输入流,BufferedInputStream缓冲字节输入流,ObjectInputStream对象字节输入流

FileInputStream文件输入流构造器:形参传入file对象或使用文件描述符或指定文件路径创建

read方法逐个字节读取文件中内容,返回读取到的字节数值。也可以传入byte数组形参(提升读取效率),数组长度为一次最大读取字节数,read返回-1则表示读取结束,正常读取则返回实际读取的字节数,通过读取的字节数读取字符数组,创建字符串

执行完毕最后需要close方法关闭输入流

使用字节流读取中文字符会出现乱码,因为编码时使用多个字节存储中文,但是读取时是一个字节一个字节读取转换

15.2.2 字节输出流OutputStream

构造器使用new FileOutputStream(文件路径)则会覆盖原来的内容

使用new FileOutputStream(文件路径,true)则表示追加在后面,而不是覆盖

write方法写入字节(转换为int形式);也可以写入字节数组byte,可以直接使用String自带的getBytes方法转换成byte数组;也可以在getBytes方法后,开始位置,结束位置截取字符串写入

若写入时不存在路径文件,则自动创建

15.2.3 使用节点流读取并保存字节流

1.分别创建空输入和输出流对象

2.设置读取和输出路径字符串

3.try中构造读取和输出对象

4.创建byte数组,定义int读取长度

5.while中read的返回值不等于-1则write(数组,0,返回值(数组长度))

6.finally中try,当输入流对象不为空则close,输出流对象不为空则close

15.2.4 字符输入流FileReader

构造器(File或String)

read每次读取单个字符,读取到的是字符的比特码,读取到文件末尾则返回-1。传入字符数组则返回读取到的字符数

15.2.5 字符输出流FileReader

构造器(File或String)覆盖模式,流指针在首端

构造器(File或String,true)追加模式,流指针在尾端

write方法可以写入单个字符,字符数组,数组指定部分(直接输入字符串需要使用toCharArray转换成数组),整个字符串,字符串指定部分

使用后需要close或者flush才能读取到文件,底层中调用了一个writeBytes方法写入数据

15.3 处理流

节点流可以从特定的数据源读取数据(FileReader,FileWriter)

处理流(包装流)连接在已经存在的流之上,为程序提供更强大的读写功能(BufferedReader,BufferedWriter)

BufferedReader可以封装一个节点流Reader(修饰器模式)

节点流是底层流,直接和数据源相接

处理流是包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出

处理流优势主要以增加缓冲的方式提高输入输出的效率,提供了便捷方法一次输入输出大批量数据,更加灵活方便

15.3.1 修饰器模式和包装类

最底层为Reader抽象类,提供多种空的读取方法

根据不同的读取种类设计不同的类继承Reader类,实现需要的读取方法

BufferedReader继承Reader类,并且有Reader属性,构造器传入Reader类,则实际使用时可以传入任意的Reader子类进行构造。同时BufferedReader本身不但实现了Reader本身的方法,还提供了多种个性化读取方法,使得读取更加灵活

15.3.2 字符输入流BufferedReader(处理流)

构造器传入字符输入流类(通过文件路径构造)

readline方法按行读取文件,返回null则表示文件读取完毕

关闭流只需要close方法关闭BufferedReader即可,底层会自动关闭节点流

15.3.3 字符输入流BufferedWriter(处理流)

构造器传入字符输出流类(通过文件路径构造),默认覆盖模式,希望用追加模式则在构造器的节点流类构造器中加true

newLine换行

write写入字符串

15.3.4 使用处理流读取并保存字节流

1.创建输入输出地址字符串

2.创建BufferedReader和BufferedWriter指向null

3.try中创建输入输出对象

4.while循环当readline返回不为null时读取,使用String接收读取的变量

5.write写入读取的内容String变量,newLine换行

6.finally中判断输入和输出流,不为null则close

15.3.5 字节输入流BufferedInputStream(处理流)

构造器传入字节输入流类(通过文件路径构造)

read方法等同于底层流使用

15.3.6 字节输出流 BufferedOutputStream(处理流)

构造器传入字节输出流类(通过文件路径构造)

write方法等同于底层流使用

字节流也可以操作文本文件,因为本质都是字节流

15.4 对象流

序列化指在保存数据时,保存数据的值和数据类型

反序列化指在恢复数据时,恢复数据的值和数据类型

需要让某个对象支持序列化机制,则必须让该类可序列化,实现Serializable(无方法)或Enternalizable(有方法需要实现)接口

序列化的类可继承,继承的类也可序列化

序列化的类中建议添加SerialVersionUID,提高版本兼容性(当类被修改时,序列化不会认为是新的类)

序列化对象时默认将所有属性序列化除了static或transient修饰的成员

序列化对象时,要求属性(对象)的类型也实现序列化接口

15.4.1 对象输出流ObjectOutputStream

构造器传入new FileOutputStream(路径)

writeInt/Boolean/.../UTF/Object方法传入对象,如果传入基本数据类型会自动装箱,传入的对象需要实现Serializable接口

15.4.2 对象输入流ObjectInputStream

反序列化的读取顺序需要和序列化的顺序一致

恢复对象时,读取到的对象是Object类型,想要调用原本的对象成员,需要向下转型

15.5 标准输入输出流

标准输入(键盘)System.in 是System类的public final static InputStream属性

编译类型是InputStream,运行类型是BufferedInputStream

通过Scanner对象.next()接收输入数据

标准输出(显示器)System.out 是System类的public final static PrintStream属性

编译类型是PrintStream,运行类型是PrintStream

15.6 转换流

处理纯文本数据时,使用字符流效率更高,并且能有效解决中文问题,建议将字节流转换为字符流

15.6.1 InputStreamReader

将字节流转换成字符流,可以指定编码方式

1.构造器传入FileInputStream(文件路径),编码方式。底层仍然使用FileInputStream

2.BufferedReader对象构造器传入InputStreamReader对象

3.通过BufferedReader对象readLine获取字符串即可

15.6.2 OutputStreamWriter

将字节流转换成字符流,可以指定编码方式

1.构造器传入FileOutputStream(文件路径),编码方式。

2.write()写入

3.close

15.7 打印流

只有输出流,没有输入流

15.7.1 打印字节输出流PrintStream

System.out输出的编译类型和运行类型都是PrintStream

默认输出位置为显示器,可以通过setOut方法传入PrintStream对象(输出路径),会调用native方法setOut0修改底层输出位置

print方法打印输出,底层判断输入字符串是否为空,若为空则返回null字符串,若不为空则调用write方法输出

15.7.2 打印字符输出流PrintWriter

构造器可以传入System.out(显示器输出),也可以传入FileWriter(输出路径)

15.8 Properties类

是Hashtable的子类,以键值对形式存储文件,键值对之间不需要有空格,值不需要用引号,默认类型String

load方法,加载配置文件的键值对到Properties对象

list方法,将数据显示到指定设备

getProperty(key)根据键获取值

setProperty(key,value)设置键值对到Properties对象

store将Properties中的键值对存储到配置文件中,idea保存配置文件中文默认存储为unicode码

16 网络编程

17 反射

反射机制允许程序在执行器借助反射API取得任何类的内部信息,并且操作对象的属性和方法

加载类,返回Class类型的对象(包含类的完整结构信息),通过加载的对象.newInstance方法得到加载的对象实例

在反射中,可以把方法也视为对象,通过方法对象.invoke实现方法调用

通过Class 对象(一个类只能有一个Class对象)可以得到类的结构,相当于一面镜子,透过镜子看到类内部结构

17.1 java处理阶段

1.编译阶段:通过javac编译为class字节码文件

2.加载阶段:通过类加载器将class文件加载到内存中,生成Class类对象(堆中)

3.运行阶段:创建对象后,该对象知道其属于哪个Class对象,得到Class对象后,调用方法,操作属性等待

17.2 反射机制作用

1.在运行时判断任意一个对象所属的类

2.在运行时构造任意一个类的对象

3.在运行时得到任意一个类具有的对象成员和方法

4.在运行时调用任意一个对象的成员变量和方法

5.生成动态代理

优点:可以动态创建和使用对象(框架底层核心),使用灵活

缺点:反射是解释执行,对执行速度有影响

17.3 反射常用类

java.lang.Class,代表一个类

java.lang.reflect.Method,代表类的方法

java.lang.reflect.Field,代表成员变量(无法获取私有属性)

java.lang.reflect.Constructor,代表构造方法,getConstructor获取无参构造器,传入String.class表示传入String类的Class对象作为形参。可以通过获取到的构造器创建对象

17.4 反射调用优化

Method,Field,Constructor在使用前都会调用setAcccessible方法进行安全检查

可以传入参数true取消访问检查提高反射效率

17.5 Class类

Class也继承Object类

Class对象是系统创建的,而不是new出来的(通过类加载器ClassLoader加载)

对于某个类的Class对象,在内存中只有一份,因为类只加载一次

每个类实例都知道自己由哪个类实例生成

通过Class可以完整得到一个类的结构

Class对象(成员变量,构造器,成员方法)存放在堆中

类的字节码二进制数据放在方法区中,有的地方称为类的元数据(包括方法代码,变量名,方法名,访问权限等)

17.6 Class类常用方法

Class<?>表示不确定的Java类型,用来接收获取到的Class对象

Class.forName(类路径),通过类路径获取Class类对象

Class类对象.getClass,返回Class类对象的运行类型(java.lang.Class)

Class类对象.getPackage().getName(),返回类所在包名

Class类对象.getName(),返回类全路径名

(类名)Class类对象.newInstance(),通过Class类对象创建类的对象实例

Class类对象.getField(),返回属性,通过Field类对象接收

Class类对象.getFields(),返回所有属性,通过Field类数组对象接收

Field类对象.get(属性名),获取属性值 

Field类对象.set(属性名,属性值),给属性赋值 

17.7 类对象获取方法

编译阶段可以使用Class.forName(类全路径)获取(用于配置文件,读取全路径加载类)

加载阶段可以使用类.class获取(用于参数传递,比如通过反射得到对应构造器对象)

运行阶段可以使用对象.getClass获取(通过创建好的对象获取Class对象)

还可以通过类加载器:类加载器变量 = 对象.getClass().getClassLoader();

                                Class对象 = 类加载器变量.loadClass(类的全路径名)

得到Class对象

获取基本数据类型的包装Class类对象:Class<Integer> 对象 = int.class

还可以通过 Integer.TYPE获取基本数据类型的包装Class类对象

外部类,接口,数组,二维数组,注解,枚举,包装类,Void,Class都具有Class对象

17.8 类的加载

静态加载(new方法创建对象时,子类加载时同时加载父类,调用类中静态成员时):在编译时加载的类,如果不存在则报错,依赖性强

动态加载(反射):运行时加载所需的类,不使用,即使不存在该类则不报错,降低了依赖性

类先加载,将类的class文件读入内存,并为之创建一个java.lang.Class对象,该过程由类加载器完成。

然后连接(将类的二进制数据合并到JRE中):首先进行安全验证,然后对静态变量进行默认初始化,最后解析,虚拟机将常量池中符号引用替换为直接引用。

最后进行自定义初始化,JVM负责对类进行初始化,主要是指静态成员

方法区中存储类的字节码的二进制数据,堆中存储类的Class对象 

17.8.1 类加载阶段

JVM在类的加载阶段主要目的是将字节码从不同数据源(class文件,jar包或网络)转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象

17.8.2 类连接阶段

首先进行验证,了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全

验证阶段工作包括:文件格式验证,(是否以魔数oxcafebabe开头),元数据验证,字节码验证和符号引用验证

可以考虑使用-Xverify:none参数关闭大部分验证措施,缩短虚拟机类加载时间

接下来进行准备阶段,JVM在该阶段对静态变量分配内存并初始化(对应数据类型的默认初始值),这些变量使用的内存都在方法区中进行分配

实例属性不会分配内存,静态变量分配内存默认初始化,静态final常量会分配内存并赋值

第三步解析阶段,虚拟机将常量池内的符号引用替换为直接引用,从逻辑地址转化为物理内存地址

第四步初始化阶段,此阶段执行<clinit>()方法,该方法是由编译器语句在源文件中出现的顺序,依次自动收集类中所有静态变量的赋值动作和静态代码块中的语句,并进行合并

虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁,同步,如果多个线程同时初始化一个类,则只有一个线程会执行<clinit>()方法,其他线程会被阻塞等待,直到活动线程执行<clinit>()方法完毕

17.9 通过反射获取类结构

17.9.1 java.lang.reflect.Class类

getName获取全类名

getSimpleName获取简单类名

getFields获取所有public修饰的属性,包括本类和所以父类的

getDeclaredFields获取本类中所有属性

getMethods获取所有public修饰的方法,包括本类和所以父类的

getDeclaredMethods获取本类中所有方法

getConstructors获取所有public修饰的本类构造器

getDeclaredConstructors获取本类中所有构造器

getPackage以package形式返回包信息

getSuperClass以Class形式返回父类信息

getInterfaces以Class[]形式返回接口信息

getAnnotations以Annotation[]形式返回注解信息

17.9.2 java.lang.reflect.Field类

getModifiers以int形式返回修饰符,默认修饰符为0,public是1,private是2,protected是4,static是8,final是16(多个修饰符值会累加)

getType以Class形式返回类型

getName返回属性名

17.9.3 java.lang.reflect.Method类

getModifiers以int形式返回修饰符,默认修饰符为0,public是1,private是2,protected是4,static是8,final是16(多个修饰符值会累加)

getReturnType以Class形式获取返回值类型

getName返回方法名

getParameterTypes以Class[]返回参数类型数组

17.9.4 java.lang.reflect.Constructor类

getModifiers以int形式返回修饰符,默认修饰符为0,public是1,private是2,protected是4,static是8,final是16(多个修饰符值会累加)

getParameterTypes以Class[]形式获取返回值类型

getName返回构造器名

17.10 通过反射构建类

17.10.1 通过反射创建对象

方法一:调用类中public的无参构造器,newInstance:调用无参构造器获取类对象

方法二:调用指定构造器,

getConstructor(Class...clazz)根据参数列表,获取对应的public构造器对象;然后通过获取到的构造器对象调用newInstance方法创建对象

getDecalaredConstructor(Class...clazz)根据参数列表,获取对应本类的构造器对象(可以是非public构造器),首先setAccessible(true)开启暴破,然后通过获取到的构造器对象调用newInstance方法创建对象。

Constructor方法:

        setAccessible()暴破,可以访问private类型构造器/方法/属性

        newInstance(Object...obj)调用构造器

17.10.2 通过反射访问成员属性

1.根据属性名获取Field对象

2.暴破

3.访问:属性对象.set(对象,值)/属性对象.get(对象)

4.静态属性则set和get的对象参数可以写成null

17.10.3 通过反射访问成员方法

1.根据方法名获取Method方法对象(对象名,形参列表),形参为int(类型).class

2.暴破

3.访问:方法对象.invoke(对象,实参列表)

静态属性则invoke的对象参数可以写成null

方法的返回值返回Object类型(编译类型),运行类型与方法返回类型一致

18 MySQL

19 JDBC和连接池

20 正则表达式

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值