前面基础的部分都已熟练掌握,无需笔记反复记忆。
-
封装
-
标准的JavaBean:
=========================================================================
-
成员变量与局部变量:
=========================================================================
-
字符串变量:
-
字符串常见的面试题:
-
String的各种方法使用:
字符串与字符串之间比对内容需要用equals方法,返回值是Boolean值。
equalsIgnoreCase()方法 可以忽略大小写。
=========================================================================
-
数组:
数字定义并且启动之后,类型就固定了,长度也被固定了。
一般都用简化格式。
=========================================================================
-
方法
=========================================================================
-
构造器
=========================================================================
-
Static
static是静态的意思,可以修饰成员变量,表示该成员变量在内存中只存在一份,可以被共享访问、修改。
在同一个类中访问静态成员变量,类名可以省略。
=========================================================================
静态代码块可以对静态数据进行初始化的操作,构造代码块可以初始化实例资源,在创建对象的时候,就可以在调用构造器之前执行,那么就可以提前把资源初始化好,以免每创建一个对象都需要去初始化一下资源。
=========================================================================
-
饿汉单例模式:
创建一个类,将这个类的构造器给私有起来。然后用static修饰创造一个静态变量储存为对象。这样无论对这个类创建几个对象都始终只有一个
-
懒汉单例模式:
同样的也需要将构造器给私有起来,然后定义一个私有的空的对象,与饿汉单例不同的就是懒汉单例会在创建对象的时候去返回对象(懒汉单例创建了一个返回对象的方法),而不是像饿汉单例在加载类的时候就创建对象。
=========================================================================
-
继承
-
什么是继承?
-
为什么需要使用继承
可以提高代码的复用性!
继承之后的子类往往都是比父类更强的。
子类可以继承父类的私有成员。 但是不能直接访问。
Java只能单继承,不能多继承。 可以用反推法证明。
不能多继承,但是可以多层继承。
Java中的所有类要么直接继承了Object类,要么默认继承了Object类,要么间接继承了Object类,Object类是祖宗类。
访问的特点:
如果非要指定找子类的加this关键字
如果指定找父类的加super关键字(必须是要在子类的方法中)
方法的重写:
this和super:
=========================================================================
包:
最重要的还是导包,同一个包的类可以直接调用。
如果是在不同包内的类,需要导包才能进行调用。
如果是两个不同包下的相同名称得类,都需要调用的话:
只能导一个包,另一个必须要写包路径。才能够两个一起使用。
=========================================================================
权限修饰符:
=========================================================================
final关键字:
比如用final去修饰一个数组,那么数组的地址不能改变,但是数组内的元素可以被重新赋值。
=========================================================================
常量: 命名规范:英文单词全部大写,多个单词用下划线连接起来。
常量的执行原理:
在编译阶段,常量会进行宏替换,把使用常量的地方全部替换成字面值。
这样,使用常量跟使用字面值运行起来的效率是一样的。
=========================================================================
枚举可以拿来做信息标志和分类,代码可读性好,入参约束严谨,是最好的信息分类技术。
PS:(但是一般在公司还是选择常量作为信息标志,因为简单)!!!
=========================================================================
抽象类:
有了抽象方法,那么就失去了创建对象的能力。
因为抽象方法没有具体内容。
=========================================================================
接口:
什么是接口?
接口就是体现规范的,其中的抽象方法定义的一组行为规范,接口是更加彻底的抽象。
JDK8版本开始后,Java对接口的成员方法进行了新增。
允许接口中直接定义带有方法体的方法!
1、要实现多继承多实现,那么接口的静态方法只能由接口自己去调用。避免两个接口有同名的方法。产生冲突。
2、如果一个类继承的父类和实现的接口类中有名字相同的方法,那么优先使用父类的!
3、一个类实现多接口,多个接口存在同名的默认方法,不冲突,这个类重写该方法即可!
4、一个接口继承多个接口是可以的,如果多个接口中存在规范冲突则不能多继承。
=========================================================================
多态:
=========================================================================
内部类:
1、静态内部类(开发中用的少)
2、成员内部类
第一个78直接访问,因为在同一个类中
第二个110需要this关键字
第三个需要用外部类名.this
3、局部内部类
4、匿名内部类
不会主动的去定义匿名内部类,需要或者是可以写的时候才会去使用。
匿名内部类可以进一步的简化代码!!
=========================================================================
常用API:
Object的toString方法:
equals方法:
StringBuilder:
String Builder只是拼接字符串的一种手段,最后还是得恢复成字符串。
String builder在调用append的之后,还是返回的String builder类型,所以可以链式编程。
String builder在拼接的过程中,在内存中只创建一个对象,相比于String 用+号来连接的方法,更加的节省内存占用。
Math类:
System类:
BigDecimal类:
Date类:
SimpleDateFormat类:
Calendar类:
Calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化。
=========================================================================
包装类:
包装类就是八种基本类型的引用类型。
正则表达式: String.matches("正则表达式");
Array类常用API:
LambDa表达式:
进一步的省略:
=========================================================================
集合:
数组和集合的差别:
Collection类的常用API:
迭代器:
增强for循环: for(变量类型 变量名:数组名){}
Lambda表达式的遍历:
List:
List的底层结构是基于数组的,在创建一个List就会创建一个10大小的数组,在超过10个数据之后,就会将原有数组扩大1.5倍,然后将数据迁移到新的数组中。 删除数据就会按index删除,然后将后面的数据往右移一格。
LinkedList:
LinkedList基于双链表,所以可以实现栈和队列的操作。
push压栈,pop弹栈。 push底层就是addFirst,pop就是removeFirst()
队列的话,出队就是removeLast()
边遍历边删除的注意事项:
Iterator<String> it =list.iterator();
使用迭代器删除的时候,需要注意不能用list的remove方法,需要用迭代器的remove方法。
foreach不能边遍历便删除。
迭代器和for循环可以边遍历边删除。
for循环解决方法:
1、可以从最后往前删,(int i = list.size();i>=0;i--)
2、可以在循环体内,删除成功的语句后面加一个i--,那么在删除成功之后,回退一格。
=========================================================================
泛型:
通配符:?
Set集合:
LinkedHashSet:
TreeSet:
综合分析:
可变参数:
Collections集合工具类:
=========================================================================
Map集合:
Map集合的常用API:
Map集合遍历方法一:
方法二:
方法三:
HashMap:
LinkedHashMap就是变得有序,保证存入和取出的顺序是一致的。底层逻辑也是哈希表。LinkedHashMap采用双链表的方式。
TreeMap:
整体特点:
=========================================================================
创建不可变集合:
=========================================================================
Stream流:
获取Stream流,Map集合需要分开获取键流和值流,map集合调用EntrySet方法也可以获取到Stream流。
JDK16开始,可以用Stream流调用toList方法,但是得到的是一个不可变集合。
stream流调用.collect(Collector.toList())得到的是一个可变集合。
每个流只能被操作一次,执行了终结语句之后,流就被销毁了。不能被二次调用!!!
=========================================================================
异常处理:
运行时异常:
编译时异常:
异常的出现过程:
处理异常:
自定义异常:
=========================================================================
日志技术:
=========================================================================
File类:
相对路径比较重要,可以定位到工程下的文件。
File封装的对象可以是一个不存在的路径,因为File对象可以把它创建出来。
方法递归:
=========================================================================
字符集:
=========================================================================
IO流:
-
文件字节输入流:
文件过大,内存溢出只是理论上的结论。实际操作中出现的问题很少。
-
文件字节输出流:
OutputStream os = new FileOutputStream("文件路径",true);
在后面加上一个true的参数,就可以在第二次创造这个流的时候不清空该路径下的数据。实现追加数据的功能。
当需要写入换行符(/r/n)或者汉字的话,需要将字符转换为字节。"汉字".getBytes()
-
try-catch-finally:
优化后的资源释放操作,可以不用编程人员手动的编写代码去释放流对象,系统会自动调用他们的释放流方法。(里面只能放置资源对象)
JDK7改进的方法比较常用,JDK9改进的方法会使得外部定义的流对象需要再嵌套一个try-catch,不是很方便,但是如果这个流对象是被方法传来的,就非常方便。
=========================================================================
-
文件字符输入流:
Reader reader = new FileReader("文件路径");
char[] buffer = new char[1024];
int len;
while((len == reader.read(buffer)) != -1){
String rs = new String(buffer,0,len);
System.out.print(rs);
}
-
字符输出流:
=========================================================================
缓冲流:
字节缓冲输入、输出流和之前普通的没有区别,只是多提供了一个8KB的缓冲区,让流内的数据执行的更加的快。
字符缓冲输入流新增的readLine()方法可以读取一行的数据进行返回。
=========================================================================
字符输入转换流:
字符输出转换流:
对象序列化:
对象的反序列化:
需要被序列化的对象中用transient修饰的变量,在反序列化的时候将不会被展示出来。
可以给需要被序列化的对象设置一个序列化ID,serialVersonUID="参数";
序列化ID主要就是防止项目中改变了对象的数据,而电脑硬盘中存储的被序列化之后的对象不一致。提醒你该重新序列化对象。
打印流:
如果创建的时候,打印流后面直接加的文件路径,那么也是会每次覆盖掉之前的内容。
如果创建打印流的时候,后面加的是低级的字符流,那么可以在低级的字符流里面去控制需不需要追加。
Properties:
=========================================================================
IO框架:
=========================================================================
线程:
定义一个类继承Callable接口,然后重写里面的run方法。再把这个类交给FutureTask对象,这样就可以交给Thread去执行。FutureTask这个对象可以调用get方法,而且它会等待线程执行完成之后再对结果进行读取。
线程安全:
方式一:
this作为锁对象的意思就是,对于同一个对象来操作这个共享资源你的时候,把这个对象仅允许一个线程进来即可。
方式二:
方式三:
private final Lock lock = new ReentrantLock();
try{
method body;
} finally{
lock.unlock(); //建议将解锁放在finally执行,否则方法执行出现异常,那么共享区域将死锁
}
线程通信:
线程池:
重要的:
当核心线程都在忙,临时线程也在忙,并且等待队列也满了的时候,再来的新任务将会被处理掉。
前两个和第四个创建线程池的方法,不会控制任务队列的任务数量,会导致内存溢出的风险。
第三个线程与任务数1:1增长,也存在内存溢出的风险
建议:
Timer定时器:
ScheduledExecutorService定时器:
线程的生命周期:
网络通信:
UDP通信:
UDP广播
组播
TCP:
客户端:
服务端:
让一个服务端接收多个客户端的请求:需要引入多线程
使用线程池优化:
即时通信:
BS模拟:
=========================================================================
单元测试:
反射:
反射获取构造器对象: