一.Basic IO
1.Java 中有几种类型的流
按照流的方向:输入流(inputStream)和输出流(outputStream).
按照实现功能分:节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)和处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接)
按照处理数据的单位: 字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。
- 字节流如何转为字符流
字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象 - 如何将一个 java 对象序列化到文件里
在 java 中能够被序列化的类必须先实现 Serializable 接口,该接口没有任何抽象方法只是起到一个标记作用
//对象输入流
ObjectInputStream objectInputStream =new ObjectInputStream
(new FileInputStream(new File("D://obj")));
User user = (User)objectInputStream.readObject();
System.out.println(user);
objectInputStream.close();
二、lambda
1.用 lambda 表达式实现 Runnable
// Java 8之前:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8, too much code for too little to do");
}
}).start();
//Java 8方式:
new Thread( () -> System.out.println
("In Java8, Lambda expression rocks !!") ).start();
输出:
too much code, for too little to do
Lambda expression rocks !!
2.使用 Java 8 lambda 表达式进行事件处理
// Java 8之前:
JButton show = new JButton("Show");
show.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Event handling without lambda expression is boring");
}
});
// Java 8方式:
show.addActionListener((e) -> {
System.out.println("Light, Camera, Action !! Lambda expressions Rocks");
});
3.使用 Java 8 lambda 表达式进行事件处理 使用 lambda 表达式对列表进行迭代
// Java 8之前:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}
// Java 8之后:
List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
features.forEach(n -> System.out.println(n));
//使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,
//看起来像C++的作用域解析运算符
features.forEach(System.out::println);
输出:
Lambdas
Default Method
Stream API
Date and Time API
三、GC基本知识
- Java 中为什么会有 GC 机制呢
Java 中为什么会有 GC 机制呢?
安全性考虑;-- for security.
减少内存泄露;-- erase memory leak in some degree.
减少程序员工作量。-- Programmers don't worry about memory releasing. - 对于 Java 的 GC 哪些内存需要回收
内存运行时 JVM 会有一个运行时数据区来管理内存。它主要包括 5 大部分:程序计数器 (Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap).
而其中程序计数器、虚拟机栈、本地方法栈是每个线程私有的内存空间,随线程而生,随线程而亡。例如栈中每一个栈帧中分配多少内存基本上在类结构确定是哪个时就已知了,因此这 3 个区域的内存分配和回收都是确定的,无需考虑内存回收的问题。但方法区和堆就不同了,一个接口的多个实现类需要的内存可能不一样,我们只有在程序运行期间才会知道会创
310建哪些对象,这部分内存的分配和回收都是动态的,GC 主要关注的是这部分内存。总而言之,GC 主要进行回收的内存是 JVM 中的方法区和堆; - Java 的 GC 什么时候回收垃圾
很容易想到的一个答案是:对一个对象添加引用计数器。每当有地方引用它时,计数器值加 1;当引用失效时,计数器值减 1.而当计数器的值为 0 时这个对象就不会再被使用,判断为已死。是不是简单又直观。然而,很遗憾。这种做法是错误的!为什么是错的呢?事实上,用引用计数法确实在大部分情况下是一个不错的解决方案,而在实际的应用中也有不少案例,但它却无法解决对象之间的循环引用问题。比如对象 A 中有一个字段指向了对象 B,而对象 B 中也有一个字段指向了对象 A,而事实上他们俩都不再使用,但计数器的值永远都不可能为 0,也就不会被回收,然后就
发生了内存泄露。
所以,正确的做法应该是怎样呢?
在 Java,C#等语言中,比较主流的判定一个对象已死的方法是:可达性分析(Reachability Analysis).所有生成的对象都是一个称为"GC Roots"的根的子树。从 GC Roots 开始向下搜索,搜索所经过的路径称为引用链
(Reference Chain),当一个对象到 GC Roots 没有任何引用链可以到达时,就称这个对象是不可达的(不可引用的),也就是可以被 GC 回收了。无论是引用计数器还是可达性分析,判定对象是否存活都与引用有关!那么,如何定义对象的引用呢?
我们希望给出这样一类描述:当内存空间还够时,能够保存在内存中;如果进行了垃圾回收之后内存空间仍旧非常紧张,则可以抛弃这些对象。所以根据不同的需求,给出如下四种引用,根据引用类型的不同,GC 回收时也会有不
同的操作:
1)强引用(Strong Reference):Object obj = new Object();只要强引用还存在,GC 永远不会回收掉被引用的对象。
2)软引用(Soft Reference):描述一些还有用但非必需的对象。在系统将会发生内存溢出之前,会把这些对象列入回收范围进行二次回收(即系统将会发生内存溢出了,才会对他们进行回收。)
3)弱引用(Weak Reference):程度比软引用还要弱一些。这些对象只能生存到下次 GC 之前。当 GC 工作时,无论内存是否足够都会将其回收(即只要进行 GC,就会对他们进行回收。)
4)虚引用(Phantom Reference):一个对象是否存在虚引用,完全不会对其生存时间构成影响。
关于方法区中需要回收的是一些废弃的常量和无用的类。
1.废弃的常量的回收。这里看引用计数就可以了。没有对象引用该常量就可以放心的回收了。
2.无用的类的回收。什么是无用的类呢?
A.该类所有的实例都已经被回收。也就是 Java 堆中不存在该类的任何实例;
B.加载该类的 ClassLoader 已经被回收;
C.该类对应的 java.lang.Class 对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
总而言之:
对于堆中的对象,主要用可达性分析判断一个对象是否还存在引用,如果该对象没有任何引用就应该被回收。而根据我们实际对引用的不同需求,又分成了 4 种引用,每种引用的回收机制也是不同的。
对于方法区中的常量和类,当一个常量没有任何对象引用它,它就可以被回收了。而对于类,如果可以判定它为无用类,就可以被回收了。
四、Spring相关
1、Spring bean
Spring beans 是那些形成 Spring 应用的主干的 java 对象。它们被 Spring IOC 容器初始化,装配,和管理。这些 beans 通过容器中配置的元数据创建。比如,以 XML 文件中<bean/> 的形式定义。Spring 框架定义的 beans 都是单例 beans。
2.Spring 支持的几种 bean 的作用域
singleton : bean 在每个 Spring ioc 容器中只有一个实例。
prototype:一个 bean 的定义可以有多个实例。
request:每次 http 请求都会创建一个 bean,该作用域仅在基于 web 的 Spring ApplicationContext 情形下有
效。
session : 在 一 个 HTTP Session 中 , 一 个 bean 定 义 对 应 一 个 实 例 。 该 作 用 域 仅 在 基 于 web 的Spring ApplicationContext 情形下有效。
global-session:在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的Spring ApplicationContext 情形下有效。
缺省的 Spring bean 的作用域是 Singleton。 - Spring bean 的生命周期
bean 定义:在配置文件里面用<bean></bean>来进行定义。
bean 初始化:有两种方式初始化:
1).在配置文件中通过指定 init-method 属性来完成
2).实现 org.springframwork.beans.factory.InitializingBean 接口
bean 调用:有三种方式可以得到 bean 实例,并进行调用
bean 销毁:销毁有两种方式
1).使用配置文件指定的 destroy-method 属性
2).实现 org.springframwork.bean.factory.DisposeableBean 接口
4.ApplicationContext
ApplicationContext 是在 BeanFactory 的基础上构建,是相对比较高级的容器实现,除了 BeanFactory 的所有支持外,ApplicationContext 还提供了事件发布、国际化支持等功能。ApplicationContext 管理的对象,在容器启动后默认全部初始化并且绑定完成。
ApplicationContext接口还通过继承其他接口扩展了BeanFactory的功能:
MessageSource———为应用提供国际化访问功能
ResourceLoader———提供资源(如URL和文件系统)的访问支持
ApplicationEventPublisher———引入事件机制,包括启动事件、关闭事件等,让容器在上下文中提供了对应用事件的支持。
FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载 beans 的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载 beans 的定义,这里,你需要正确设置classpath 因为这个容器将在 classpath 里找 bean 配置。
WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个 WEB 应用的所有 bean。
5.Spring AOP
AOP(Aspect Oriented Programming),即面向切面编程,可以说是 OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP 引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过 OOP 允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在 OOP 设计中,它导致了大量代码的
重复,而不利于各个模块的重用。
AOP 技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
使用"横切"技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。
AOP 核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组 API 提供横切功能。比如,一个日志模块可以被称作日志的 AOP 切面。根据需求的不同,一个应用程序可以有若干切面。在 Spring AOP 中,切面通过带有@Aspect 注解的类实现。
6.事务传播
https://www.cnblogs.com/colddream/articles/6017517.html
五、Thread
https://www.cnblogs.com/yangdy/p/5274455.html
https://blog.csdn.net/guoxiaolongonly/article/details/50717574
https://www.cnblogs.com/skywang12345/p/3479224.html
六、tcp、udp
https://www.cnblogs.com/xiohao/p/4439164.html
七、http header
https://blog.csdn.net/u010429424/article/details/78032006
八、REST
https://www.cnblogs.com/loveis715/p/4669091.html
九、UML
https://www.cnblogs.com/shindo/p/5579191.html
https://blog.csdn.net/hit_the_lights/article/details/80558508
十、设计模式
http://www.runoob.com/design-pattern/design-pattern-tutorial.html
十一、递归
https://blog.csdn.net/qq_34039315/article/details/78679029