1.IO流
接口中的变量默认是public static final 的,方法默认是public abstract 的按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。
- 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
- 处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。
JAVA常用的节点流:
- 文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。
- 字符串 StringReader StringWriter 对字符串进行处理的节点流。
- 数 组 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。
- 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter对管道进行处理的节点流。
常用处理流(关闭处理流使用关闭里面的节点流)
-
缓冲流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
-
转换流:InputStreamReader OutputStreamReader 实现字节流和字符流之间的转换。
-
数据流 DataInputStream DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来.
流的关闭顺序
- 一般情况下是:先打开的后关闭,后打开的先关闭
- 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b。例如,处理流a依赖节点流b,应该先关闭处理流a,再关闭节点流b
- 可以只关闭处理流,不用关闭节点流。处理流关闭的时候,会调用其处理的节点流的关闭方法。
2.JSP内置对象
一共有9个内置对象
- pageContext javax.servlet.jsp.PageContext
- request javax.servlet.http.HttpServletRequest
- response javax.servlet.http.HttpServletResponse
- session javax.servlet.http.HttpSession
- application javax.servlet.ServletContext
- config javax.serlvet.ServletConfig
- exception java.lang.Throwable
- page java.lang.Object
- out javax.servlet.jsp.JspWriter
作用:
1、pageContext 表示页容器 EL表达式、 标签 、上传
2、request 服务器端取得客户端的信息:头信息 、Cookie 、请求参数 ,最大用处在MVC设计模式上
3、response 服务器端回应客户端信息:Cookie、重定向
4、session 表示每一个用户,用于登录验证上
5、application 表示整个服务器
6、config 取得初始化参数,初始化参数在web.xml文件中配置
7、exception 表示的是错误页的处理操作
8、page 如同this一样,代表整个jsp页面自身
9、out 输出 ,但是尽量使用表达式输出
3.JVM垃圾回收方式
两个最基本的java回收算法:复制算法和标记清理算法
复制算法:两个区域A和B,初始对象在A,继续存活的对象被转移到B。此为新生代最常用的算法
标记清理:一块区域,标记可达对象(可达性分析),然后回收不可达对象,会出现碎片,那么引出标记-整理算法:多了碎片整理,整理出更大的内存放更大的对象
两个概念:新生代和年老代
新生代:初始对象,生命周期短的
永久代:长时间存在的对象
整个java的垃圾回收是新生代和年老代的协作,这种叫做分代回收。
P.S:Serial New收集器是针对新生代的收集器,采用的是复制算法
Parallel New(并行)收集器,新生代采用复制算法,老年代采用标记整理
Parallel Scavenge(并行)收集器,针对新生代,采用复制收集算法
Serial Old(串行)收集器,新生代采用复制,老年代采用标记整理
Parallel Old(并行)收集器,针对老年代,标记整理
CMS收集器,基于标记清理
G1收集器:整体上是基于标记整理,局部采用复制
综上:新生代基本采用复制算法,老年代采用标记整理算法。cms采用标记清理。
4.使用泛型的好处
1,类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
2,消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
3,潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。
所以泛型只是提高了数据传输安全性,并没有改变程序运行的性能
5.Math类的方法
ceil:大于等于 x,并且与它最接近的整数。
floor:小于等于 x,且与 x 最接近的整数。
round: 它表示四舍五入,算法为 Math.floor(x+0.5),即将原来的数字加上 0.5 后再向下取整,所以,Math.round(11.5) 的结果为12,Math.round(-11.5) 的结果为-11。
6.三目表达式
byte b = 1;
char c = 1;
short s = 1;
int i = 1;
// 三目,一边为byte另一边为char,结果为int
// 其它情况结果为两边中范围大的。适用包装类型
i = true ? b : c; // int
b = true ? b : b; // byte
s = true ? b : s; // short
// 表达式,两边为byte,short,char,结果为int型
// 其它情况结果为两边中范围大的。适用包装类型
i = b + c; // int
i = b + b; // int
i = b + s; // int
// 当 a 为基本数据类型时,a += b,相当于 a = (a) (a + b)
// 当 a 为包装类型时, a += b 就是 a = a + b
b += s; // 没问题
c += i; // 没问题
// 常量任君搞,long以上不能越
b = (char) 1 + (short) 1 + (int) 1; // 没问题
// i = (long) 1 // 错误
7.集合容器
8.类的初始化注意点
虚拟机规范严格规定了有且只有五种情况必须立即对类进行“初始化”:
- 使用new关键字实例化对象的时候、读取或设置一个类的静态字段的时候,已经调用一个类的静态方法的时候。
- 使用java.lang.reflect包的方法对类进行反射调用的时候,如果类没有初始化,则需要先触发其初始化。
- 当初始化一个类的时候,如果发现其父类没有被初始化就会先初始化它的父类。
- 当虚拟机启动的时候,用户需要指定一个要执行的主类(就是包含main()方法的那个类),虚拟机会先初始化这个类;
- 使用Jdk1.7动态语言支持的时候的一些情况。
除了这五种之外,其他的所有引用类的方式都不会触发初始化,称为被动引用。下面是被动引用的三个例子:
-
通过子类引用父类的的静态字段,不会导致子类初始化。
-
通过数组定义来引用类,不会触发此类的初始化。
public class NotInitialization { public static void main(String[] args) { SuperClass[] sca = new SuperClass[10]; } }
-
常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
public class ConstClass { static { System.out.println("ConstClass init!"); } public static final int value = 123; } public class NotInitialization{ public static void main(String[] args) { int x = ConstClass.value; } }
虽然在Java源码中引用了ConstClass类中的常量value,但其实在编译阶段通过常量传播优化,已经将此常量的值“123”存储到了NotInitialization类的常量池中,以后NotInitialization对常量ConstClass.value的引用实际都被转化为NotInitialization类对自身常量池的引用了。也就是说,实际上NotInitialization的Class文件之中并没有ConstClass类的符号引用入口,这两个类在编译成Class之后就不存在任何联系了。
9.抽象类与接口的区别
抽象类:用abstract
修饰,抽象类中可以没有抽象方法,但抽象方法肯定在抽象类中,且抽象方法定义时不能有方法体;抽象类不可以实例化只能通过继承在子类中实现其所有的抽象方法;抽象类如果不被继承就没有任何意义;抽象类为子类定义了一个公共类型,封装了子类中的重复内容。
接口:同Interface关键字定义接口,是特殊的抽象类因为类中只包含抽象方法;接口中不能定义成员变量可以定义常量;接口是其通过其他类使用implements
关键字定义实现类,一个类一旦实现接口就必须实现其中的所有抽象方法,一个类可以实现多个接口,接口名之间用逗号隔开即可;一个接口可以通过extends
关键字继承另一个接口,与此同时继承了父类中的所有方法。
10.序列化
序列化的定义是:将一个对象编码成一个字节流(I/O);而与之相反的操作被称为反序列化。序列化保存的是对象的状态,静态变量数以类的状态,因此序列化