一语法:
1.switch支持字符串: 在java虚拟机与字节码这个层次上,还是只支持switch语句中使用与整数类型兼容的类型。这个只是在编译器层次实现的,虽然开发人员在源代码使用了字符串,但在编译过程中,编译器会转化成与整数类型兼容的模式(哈希值,并且会在case语句中再用equals进行比较,防止不同字符串hash值一致)
2.枚举类型:是一个完整的java类,除了定义其中包含的枚举值之外,还可以包含任意的方法和域,以及实现任意的接口。
3.异常:
1)自定义异常要根据项目的抽象层次来,上层的不会care底层的细节,所以在抽象边缘要重新封装
2)写在try中的rescoure会自动释放,代替了finally中的释放资源
二. Java语言的动态性
1.动态代理,只能针对接口。当调用老接口时,通过InvocationHandler接口来调用新接口。
三.I/O:
1. inputStream流无法复用,它本身不是数据,只是一次性的。所以当一个流到末尾时,其实再也读不了数据了
2.流复用的方法:
1) 用BufferedInputStream: 在流开始的地方进行标记,当一个接收者读完流所有的内容以后,再进行重置。
2)直接读到一个字节数组中,然后传递这个字节数组
3.过滤输入输出流
1)读取数据时用DataInputStream/DataOutputStream,数据类型与字节数组的转化是平台相关的,所以最好不要自己用别的流去转化
2)读取Java对象时可用ObjectInputStream/ObjectOutputStream
3)流的前瞻功能:读取剩下的一部分以后如果不合适还要放回去,下次重头读取,合适继续读:PushBackInputStream的unread方法
4)处理文本类型:字符流:Reader/Writer
一个典型的应用场景是把InputStream对象中的内容转化成一个String类型的字符串。用InputStreamReader的readLine方法
5)缓冲区
6)文件通道:FileChannel
读取或写入文件时,或者文件复制时,最好用用FileChannel的transferTo和transferFrom方法。
首先用FileChannel的open(文件路径,打开方式)打开文件
大文件操作:性能问题,FileChannel类的map方法可以把一个文件的全部或部分内容映射到内存中。内存映射文件的原理在于把操作系统的内存地址映射到要操作的文件上。读取这些内存地址就相当于读取文件的内容,而改变这些内存地址的值就相当于修改文件中的内容。长时间可以能失败,force方法强制更新。
当两个程序用一个文件进行同步传输时,用lock/tryLock方法将其锁定,避免同步冲突。
7)原来的网络通信:
如果要创建一个网络客户端程序,只需要先创建一个java.net,Socket类的对象,再连接到远程服务器。当连接成功之后,可以从Socket类的对象中获取到套接字连接对应的输入输出流,通过输入流可以得到服务器端发送的数据,通过输出流可以向服务器端发送数据。对服务器端来说,则可以创建一个java.net.ServerSocket类的对象并使用其accept方法在指定的端口进行监听。调用方法accept时会处于阻塞状态,等待客户端程序的连接请求。当有新的连接建立时,accept方法会返回一个与连接发起者进行通信时所使用的Socket对象。
Socket/ServerSocket类中提供的与建立连接和数据传输相关的方法都是阻塞式的,也就是说,如果操作没完成,当前线程会处于等待状态。在等待这段时间,其它代码无法执行。性能低。所以用多线程。在服务器端,一般会有一个线程专门来调用ServerSocket类的accept方法来监听连接请求。一旦有新的连接建立,就会创建一个新的线程来专门处理这个请求。用线程池管理
8)套接字通道:
a.原理: 如果程序对网络操作的并发性和吞吐量的要求比较高,比较好的办法是通过非阻塞式的套接字通道实现多路复用或者使用NIO.2的异步套接字通道。通过一个选择器Selector来同时对多个套接字通道进行监听,当其中的某个套接字通道上有它感兴趣的事件发生时,这些通道会变为可用状态,可以在选择器的选择操作中被选中。
b.过程:非阻塞式的套接字通道可以通过register方法注册到某个Selector类的对象上,以声明由该Selector类的对象来管理当前这个套接字通道。在进行注册是,需要提供一个套接字通道感兴趣的时间的列表。这些事件包括连接完成,接收到新连接请求,有数据可读和写入数据等。这些事件定义在SelectionKey类中。在完成注册之后,可以调用Selector类的对象的select方法来进行选择。选择操作完成之后,可以从Selector类的对象中得到一个可用的套接字通道列表。对于这个列表中的套接字通道来说,至少有一个它注册时声明的感兴趣的事情发生了。然后根据时间类型来处理。这种非阻塞模式read方法只会读取当时可以立即读取的数据,而不会等数据到来。因此可能read不到任何数据。
c.例子:在使用选择器之前,首先要创建它。通过Selector类的open方法可以创建一个新的选择器。有了选择器后,下一步是通过configureBlocking方法将通道设置成非阻塞模式,把套接字通道注册到选择器上。然后在注册时要指定套接字通道感兴趣的事件。注册完成之后,下一步就是调用Selector类的对象的select方法进行通道选择操作。直接调用select方法是会阻塞的,直到所有监听的套接字通道中至少有一个它们所感兴趣的事件发生为之。在执行完select方法后,通过调用selectedKeys方法可以获取到表示被选中的通道的SelectionKey类对象的集合。每一个SelectionKey类对象与一个被监听的通道相对应,然后对其发生的什么类型的事件进行判断处理。
通过SelectionKey类的对象的cancel方法可以取消选择器对此通道的管理。对于一个通道来说,由于数据是持续不断传输的,所以不需要额外的操作;如果read方法返回值为0,说明本次没有数据可读;-1说明通道所有数据已经读取完毕,应该通过SelectionKey类的对象的cancel方法取消对此通道的监听。
9) NIO.2
a.文件路径抽象:Path代替字符串,有多个方法可以操作
b.遍历当前文件目录: DirectoryStream接口.快,可以有过滤条件
c.遍历文件目录树:FileVistor,遍历时可以有跳过,继续,不在遍历等状态,可以控制遍历方式(比如拷贝代码时,SVN的文件不拷贝)
d.文件属性相关: Files类中的静态方法可以操控属性
e.监视目录变化: 热部署时监视哪个文件变化了。原来是在一个独立的线程中使用File类的listFiles方法来定时检查目录中的内容,并与之前的内容比较,判断是否有新的文件出现,或者原文件被修改。
Watchable接口。也要register注册,并且用WatchKey说明对哪个事件感兴趣,查询方式也分为阻塞式(take)/非阻塞式(poll),将监控放在while循环里,一旦有改动,take之后语句可以继续执行,遍历WatchKey 的pollEvents方法得到所有的event。这里会有上下文信息,然后处理
f.zip/jar: 原来使用java.util.zip和java.util.jar中的类,之前往压缩包里添加新文件的做法是创建一个临时文件夹做中转,把zip文件中已有的内容复制,然后添加新的文件。
使用文件系统FileSystem.newFileSystem()就可以当做一个普通的File进行操作
g.异步通道: 套接字阻塞的使用方式与文件通道相同,非阻塞用选择器实现。异步通道有两种使用方式:Future对象,需要显示get。另一种是completionHandler接口,实际的调用结果作为参数传回来。read和write方法需要显示指定位置。
四.国际化与本土化:
1.Java平台内部统一使用UTF-16编码格式,因此在单个程序内部不会出现编码问题。编码问题会出现在程序与外界发生字符数据传递的时候。也就是说当跨边界的字节序列需要转化为字符时,会出现问题。解决方法是在程序与外界的输入输出边界严格控制字符的编码格式。确保这些字符以正确的UTF-16格式进入程序内部。
2.原来是通过String.getBytes(字符集)完成。现在有CharSet类
3.Web应用乱码两种情况: 作为Web应用URL的一部分(get);出现在HTML表单提交的数据中(post)
4.对于URL中文,先用UTF-8转化成对应的字节序列,再对这个字节序列中的每个字节都使用百分号编码格式。JAVA有java.net.URLEncoder类。服务器端处理GET请求时,一般底层应用服务器会提供相关的URL解码功能,只需要对应用服务器进行配置即可。
5.Post请求:应该在Post请求HTTP头显示声明Content - Type的值。页面字符集的几个影响因素:Content-Type//用户通过浏览器自己指定的字符集。开发推荐都设置成utf-8
五.Java虚拟机:
1.虚拟机的主要作用有两个:一个是为应用程序屏蔽底层操作系统的细节;一个是为应用程序提供必要的运行时的支持能力。
2.强引用:new出来的。造成内存泄漏两种,第一是隐式的强引用,单向队列前面的。对象不会被用到,但也不会被回收。逻辑错误。第二是存活时间过长cache。
3.不同的厂商有不同的虚拟机,都遵守虚拟机实现规范。HotSpot Java SE7使用的。采用分代回收,标记-清除-压缩算法。在回收过程中,最长回收的是年轻代内存区域。
4.垃圾回收算法考虑因素
1)串行(非服务器)/并行(服务器,有多个CPU)回收
2)处理存活对象方式: 考虑处理存活对象时间以及之后内存分配时间: 压缩(到一块连续内存,处理慢,分配会很快)/不压缩(反之)/复制
六.对象生命周期:
1.初始化顺序: 静态代码块和静态域(按出现树勋)之后是父类,之后是子类,先实例域的值,后构造方法
2.不要在父类中调用子类重写的方法
3.对象序列化: ObjectOutputStream 的write方法,new时需要用OutputStream指明实际的输出目的,文件或网络。 字节流---Java对象
ObjectInputStream的read方法,new时需要用inputStream指明实际来源。
需要实现Serializable接口。transient关键字修饰的属性不会被实例化,
只有serialVersionUID一致,才认为兼容,否则失败。如果没有明确指定,那么会根据类中各种元素的特征计算出一个散列值
七. 动态代理:
1. 两个条件: 1)要代理的接口 2) InvocationHandler(里面的invoke方法执行自己逻辑然后调用原类方法,组合)