Java大汇总(下)

72 阅读5分钟

动态代理

  1. jdk自带的动态代理可以代理一个已经实现接口的类。

  2. cglib代理可以代理一个普通的类。

  3. 动态代理的基本实现原理都是通过字节码框架动态生成字节码,并且在用defineclass加载类后,获取代理类的实例。

一般需要实现一个代理处理器,用来处理被代理类的前置操作和后置操作。在JDK动态代理中,这个类叫做invocationHandler。

  1. JDK动态代理首先获取被代理类的方法,并且只获取在接口中声明的方法,生成代理类的字节码后,首先把这个类通过defineclass定义成一个类,然后把该类加载到jvm,之后我们就可以通过,A.class.GetMethod()获取其方法,然后通过invoke调用其方法,在调用这个方法时,实际上会通过被代理类的引用再去调用原方法。

  2. 而对于cglib动态代理,一般会把被代理类设为代理类的父类,然后获取被代理类中所有非final的方法,通过asm字节码框架生成代理类的字节码,这个代理类很神奇,他会保留原来的方法以及代理后的方法,通过方法数组的形式保存。

cglib的动态代理需要实现一个enhancer和一个interceptor,在interceptor中配置我们需要的代理内容。如果没有配置interceptor,那么代理类会调用被代理类自己的方法,如果配置了interceptor,则会使用代理类修饰过的方法。

多线程

这里先不讲juc包里的多线程类。juc相关内容会在Java并发专题讲解。

  1. 线程的实现可以通过继承Thread类和实现Runable接口 也可以使用线程池。callable配合future可以实现线程中的数据获取。

  2. Java中的线程有7种状态,new runable running blocked waiting timewaiting terminate blocked是线程等待其他线程锁释放。waiting是wait以后线程无限等待其他线程使用notify唤醒 timewating是有限时间地等待被唤醒,也可能是sleep固定时间。

  3. Thread的join是实例方法,比如a.join(b),则说明a线程要等b线程运行完才会运行。

  4. o.wait方法会让持有该对象o的线程释放锁并且进入阻塞状态,notify则是持有o锁对象的线程通知其他等待锁的线程获取锁。notify方法并不会释放锁。注意这两个方法都只能在synchronized同步方法或同步块里使用。

  5. synchronized方法底层使用系统调用的mutex锁,开销较大,jvm会为每个锁对象维护一个等待队列,让等待该对象锁的线程在这个队列中等待。当线程获取不到锁时则让线程阻塞,而其他检查notify以后则会通知任意一个线程,所以这个锁时非公平锁。

  6. Thread.sleep(),Thread.interrupt()等方法都是类方法,表示当前调用该方法的线程的操作。

一个线程实例连续start两次会抛异常,这是因为线程start后会设置标识,如果再次start则判断为错误。

IO流

  1. IO流也是Java中比较重要的一块,Java中主要有字节流,字符流,文件等。其中文件也是通过流的方式打开,读取和写入的。

  2. IO流的很多接口都使用了装饰者模式,即将原类型通过传入装饰类构造函数的方式,增强原类型,以此获得像带有缓冲区的字节流,或者将字节流封装成字符流等等,其中需要注意的是编码问题,后者打印出来的结果可能是乱码哦。

  3. IO流与网络编程息息相关,一个socket接入后,我们可以获取它的输入流和输出流,以获取TCP数据包的内容,并且可以往数据报里写入内容,因为TCP协议也是按照流的方式进行传输的,实际上TCP会将这些数据进行分包处理,并且通过差错检验,超时重传,滑动窗口协议等方式,保证了TCP数据包的高效和可靠传输。

网络编程

承接IO流的内容

  1. IO流与网络编程息息相关,一个socket接入后,我们可以获取它的输入流和输出流,以获取TCP数据包的内容,并且可以往数据报里写入内容,因为TCP协议也是按照流的方式进行传输的,实际上TCP会将这些数据进行分包处理,并且通过差错检验,超时重传,滑动窗口协议等方式,保证了TCP数据包的高效和可靠传输。

  2. 除了使用socket来获取TCP数据包外,还可以使用UDP的DatagramPacket来封装UDP数据包,因为UDP数据包的大小是确定的,所以不是使用流方式处理,而是需要事先定义他的长度,源端口和目标端口等信息。

  3. 为了方便网络编程,Java提供了一系列类型来支持网络编程的api,比如URL类,InetAddress类等。

Java8

  1. 接口中的默认方法,接口终于可以有方法实现了,使用注解即可标识出默认方法。

  2. lambda表达式实现了函数式编程,通过注解可以声明一个函数式接口,该接口中只能有一个方法,这个方法正是使用lambda表达式时会调用到的接口。

  3. Option类实现了非空检验

  4. 各种api的更新,包括chm,hashmap的实现等

  5. Stream流概念,实现了集合类的流式访问,可以基于此使用map和reduce并行计算。

为方便大家学习,可以观看 适合0基础学习Java的视频教程 这个视频教程学习Java。