目录
[1. ThreadLocal](#1. ThreadLocal)
[2. finalize、finalization、finally](#2. finalize、finalization、finally)
[2.1 finalize用途](#2.1 finalize用途)
[2.2 finally](#2.2 finally)
[2.3 finally代码块和finalize()方法区别](#2.3 finally代码块和finalize()方法区别)
[6.1 问题一](#6.1 问题一)
[6.2 问题二](#6.2 问题二)
[7.1 定义](#7.1 定义)
[7.2 作用](#7.2 作用)
[7.3 序列化和反序列化](#7.3 序列化和反序列化)
[8.1 定义](#8.1 定义)
[8.2 区别](#8.2 区别)
[10.1 网络分层](#10.1 网络分层)
[10.2 通信](#10.2 通信)
[10.3 UDP通信特点](#10.3 UDP通信特点)
[11.1 作用](#11.1 作用)
[11.2 实例获取](#11.2 实例获取)
[11.3 设计模式](#11.3 设计模式)
[12.1 值传递](#12.1 值传递)
[12.2 引用传递](#12.2 引用传递)
[16.1 字节流](#16.1 字节流)
[16.2 字符流](#16.2 字符流)
[16.3 转换桥梁](#16.3 转换桥梁)
[16.4 主要区别](#16.4 主要区别)
1. ThreadLocal
ThreadLocal不是解决对象的共享访问问题,通过***ThreadLocal.set()***到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。
各个线程独立的对象不是通过***ThreadLocal.set()***创建的,而是线程新New的对象。
ThreadLocal.set()将新建对象的引用保存到线程独有的map中,每当有其他线程对这个引用指向的对象做出修改时,其他线程Thread对象中保存的值也会发生变化。
java
//ThreadLocal源码
//Thread类中有threadlocalmap对象
public void set(T value){
Thread t=Thread.currentThread();
ThreadLocalMap map=getMap(t);
if(map!=null){
map.set(this,value);
}else {createMap(t,value);}
}
public T get(){
Thread t=Thread.currentThread();
ThreadLocalMap map=getmap(t);
if(map!=null){ return (T)map.get(this);}
T value=initialValue();
createMap(t,value);
return value;
}
当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。
2. finalize、finalization、finally
2.1 finalize用途
(一)垃圾回收器:garbage colector 决定回收某对象时,就会运行该对象的finalize()方法--但在Java中很不幸,如果内存总是充足的,垃圾回收可能永远不会执行。
(二)主要用途:回收特殊渠道申请的内存--如:JNI调用non-Java程序,它的工作就是回收这部分内存。
2.2 finally
常用于Try--catch--finally中释放资源,回收内存,因为finally块中的内容一定会被执行。
需要注意:
**--**在try中return之前会执行finally,如果finally中有return则直接return,值为finally中修改的。
**--**如果finally中没有return,则执行try中return,数值仍是try中的。
2.3 finally代码块和finalize()方法区别
(一)无论是否抛出异常,finally代码块都会执行,主要用于释放占用内存;
(二)finalize()是Object中的一个protected方法,在对象被垃圾回收之前由Java虚拟机调用的。
3.修饰权限

4.Object
了解常用方法:hashcode()、equals()、toString()、getCalss()、wait()、noitfy()、notifyAll()、finalize()。
5.equls和==的区别
基本数据类型:==进行比较,比的是实际值;
复合数据类型:==进行比较,比的是内存地址;
复合数据类型:equal进行比较:(String、Ingeter、date)等重写了equal比较的是内容,没有重写equal的,比较的还是内存地址
StringBuffer和StringBuilder特殊,==和equal都是比较地址
6.异常
6.1 问题一
Java中的两种异常类型是什么?有什么区别?
运行时异常(不受检查)和编译时异常(受检查)。
运行时异常不必抛出,编译时异常必须修改或抛出。
6.2 问题二
throw和throws有什么区别?
throw关键字用来在程序中明确的抛出异常;
throws语句用来表明方法不能处理的异常。
7.序列化
7.1 定义
将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象,序列化可以弥补不同操作系统之间的差异。
7.2 作用
Java远程方法调用(RMI);
对JavaBeans进行序列化。
7.3 序列化和反序列化
(一)实现方式:
实现Serializable接口:该接口仅为可序列化的标志,无实际属性和方法。若不添加readObject()和writeObject()方法,采用默认序列化机制;
实现Externalizable接口:能自主控制序列化内容,决定那些属性可被序列化。
(二)反序列化:
实现Serializable接口的对象,反序列化时不调用类的构造方法,完全基于字节操作;
实现Externalizable接口的对象,反序列化时会调用构造方法。
(三)注意事项:
被static修饰的属性不参与序列化;
对象的类名、属性会被序列化,方法不会;
确保序列化对象所在类的属性也可被序列化;
通过网络、文件序列化时,需按写入顺序读取对象;
反序列化必须有对应类的class文件。
(四)常见序列化协议
COM、CORBA、XML&SOAP、JSON、Thirft、Protobuf、Avro。

协议对比:XML序列化性能和简洁性差,Thrift与Protobuf相比,在时空开销方面有劣势;Protobuf和Avro在性能和简洁性等方面表现优越。
8.comparable接口和comparator接口
8.1 定义
comparable接口(自然排序):使用Array或者Collection的排序方法时,自定义类需要实现该接口的compareTo(TOBJ)方法。
comparator接口(比较器排序):可以实现两个对象的特定字段比较(如比较两个员工年龄),该接口的compare(Object o1,Object o2)方法可以传递两个对象。
8.2 区别
自然排序用于单逻辑:比如我一直需要按照年龄从小到大排序。
比较器排序适用于多逻辑:比如我现在需要从小到大排,后面我又需要从大到小排,此时只需要修改传入的比较器对象即可完成这一部分改变。
9.接口和抽象类



10.Socket
Socket(套接字)是在传输层提供的一种抽象,它使得不同主机之间的进程能够进行通信,以下是 Socket 通信原理的详细介绍:
10.1 网络分层
常见的是 TCP/IP 四层模型(应用层、传输层、网络层、数据链路层);
Socket 位于应用层和传输层之间,为应用程序提供了一个访问传输层服务的接口,应用程序通过 Socket 来发送和接收数据,无需关心底层网络协议的复杂细节。
10.2 通信
(一)准备
创建Socket对象:
java
//创建客户端Socket
Socket socket=new Socket();
绑定端口:
java
//在服务器端创建监听指定接口:port的sserverSocket
ServerSocket serverSocket=new ServerSocket(port);
监听连接(服务器端):
java
serverSocket.listen();
(二)建立连接(以TCP为例)
TCP 是一种面向连接的可靠传输协议,建立连接的过程通常被称为三次握手:
第一次握手:客户端向服务器发送一个带有 SYN(同步序列号)标志的 TCP 报文段,该报文段包含客户端的初始序列号(client_isn),表示客户端请求建立连接。
第二次握手:服务器接收到客户端的 SYN 报文后,向客户端发送一个带有 SYN 和 ACK(确认)标志的 TCP 报文段。其中 ACK 标志位用于确认收到客户端的 SYN,确认号为client_isn + 1,同时服务器也发送自己的初始序列号(server_isn) 。
第三次握手:客户端收到服务器的 SYN + ACK 报文后,向服务器发送一个带有 ACK 标志的 TCP 报文,确认号为server_isn + 1,表示客户端确认收到服务器的 SYN + ACK 报文,至此连接建立完成。
(三)数据传输
**发送数据:**连接建立后,应用程序可以通过 Socket 发送数据。数据会被传递给传输层,传输层根据选择的协议(如 TCP 或 UDP)对数据进行封装。以 TCP 为例,数据会被分割成合适大小的 TCP 报文段,添加 TCP 头部信息(包含源端口、目的端口、序列号、确认号等),然后交给网络层。网络层再添加 IP 头部信息(包含源 IP 地址、目的 IP 地址等),继续向下传递,最终通过物理网络发送出去。
**接收数据:**当数据到达目标主机时,从物理层开始逐层向上解封装。网络层去掉 IP 头部信息,将数据交给传输层;传输层检查 TCP 头部信息,进行确认、排序等操作后,去掉 TCP 头部信息,将数据交给应用层的 Socket,应用程序就可以从 Socket 中读取接收到的数据。
(四)关闭连接(以TCP为例)
TCP 连接的关闭通常需要四次挥手:
第一次挥手:客户端向服务器发送一个带有 FIN(结束)标志的 TCP 报文段,表示客户端数据发送完毕,请求关闭连接。
第二次挥手:服务器收到客户端的 FIN 报文后,向客户端发送一个带有 ACK 标志的 TCP 报文,确认收到客户端的 FIN,此时客户端到服务器的连接关闭,但服务器到客户端的连接仍然保持。
第三次挥手:服务器处理完剩余数据后,向客户端发送一个带有 FIN 标志的 TCP 报文,表示服务器也准备关闭连接。
第四次挥手:客户端收到服务器的 FIN 报文后,向服务器发送一个带有 ACK 标志的 TCP 报文,确认收到服务器的 FIN,此时服务器到客户端的连接也关闭,整个 TCP 连接完全关闭。
10.3 UDP通信特点
UDP 是一种无连接的不可靠传输协议,与 TCP 不同,它不需要建立连接和进行挥手操作。应用程序直接通过 UDP Socket 发送数据,数据被封装成 UDP 数据报,添加 UDP 头部信息(包含源端口、目的端口、长度等)后交给网络层发送。UDP 不保证数据的可靠传输,可能会出现数据丢失、乱序等情况,但它的传输效率高,适合对实时性要求高、对数据准确性要求相对较低的应用场景,如视频直播、网络游戏等。
11.Runtime类
11.1 作用
Runtime类封装了JVM(Java虚拟机),每个Java程序启动会对应一个JVM进程,每个进程对应一个由JVM实例化的Runtime实例。
11.2 实例获取
由于Runtime类的构造方法被私有化,不能直接实例化,应用通过public static Runtime getRuntime()这个静态方法获取当前Runtime运行时对象的引用。
11.3 设计模式
这种通过静态方法获取唯一实例的方式,符合单例设计模式。获取实例后,可调用Runtime对象的方法控制Java虚拟机的状态和行为。
12.值的传递与引用传递
12.1 值传递
针对基本型变量,传递的是变量的一个副本,修改副本不会对原变量产生影响。
12.2 引用传递
通常针对对象型变量,传递的是对象地址的一个副本,并非原对象本身。
一般观点认为,Java 里的传递都属于值传递,但 Java 中实例对象的传递是引用传递。
13.泛型中的"T"与"?(通配符)"
T(类型参数):在使用泛型方法(如:show1方法)时,T是一个具体的类型占位符,调用方法时会确定T代表的实际类型。
如List<Student> list1,调用此方法T就为Student类型,若添加其他类型就会报错。
?(通配符):表示集合可以是任意类型的泛型集合。
14.枚举类Enum


定义的枚举类(如Day)会被编译为一个继承Enum类的最终类(final class),这限制了枚举类不能被继承。
编译器会为枚举类自动添加一些方法:
- value()方法:返回包含所有枚举实例的数组,方便遍历枚举值,其内部是返回枚举实例数组的克隆。
- valueOf(String s)方法:根据字符串参数获取对应的枚举实例,内部间接调用了Enum类的valueOf方法。
枚举类有私有构造函数,确保枚举类只能在类内部创建。
枚举类中定义的每个枚举实例(如:MONDAY,TUESDAY等),都会被编译成public static final修饰的枚举类类型变量,且在静态代码块中完成这些枚举实例的初始化,同时还会创建一个包含所有枚举实例的数组(如$VALUES),用于支持values()方法等操作。
15.Java注解
@Override:用于标明方法覆盖了父类的方法(重写)。
@Deprecated:用于标明已过时的方法或类--传递废弃信息--保持旧代码兼容,平滑过渡。
@SuppressWarnings:用于有选择地关闭编译器对类、方法、成员变量、变量初始化等的警告。其作用目标涵盖类型、字段、方法、参数、构造方法、局部变量等,保留策略为源码级别,且有String[] value()方法,用于指定要抑制的警告类型。
16.字节流,字符流
16.1 字节流
基类:InputStream(输入)和OutputStream(输出);
文件:FileInputStream(文件字节输入)和FileOutputStream(文件字节输出);
数组:ByteArrayInputStream(字节数组输入)和ByteArrayOutputStream(字节数组输出);
操作时不使用缓冲区,直接与文件交互,若不关闭资源(close方法),文件也能输出。
16.2 字符流
基类:Reader(输入)和Writer(输出);
缓冲:BufferedReader(带缓冲的字符输入)和BufferedWriter(带缓冲字符输出);
文件:FileReader(文件字符输入)和FileWriter(文件字符输出);
用于处理字符、字符数组或字符串,操作时使用缓冲区,若不使用close方法且不强制刷新(flush方法),则不会输出内容。
16.3 转换桥梁
InputStreamReader类是字节流到字符流的桥梁,能读入字节并根据指定编码转换为字符流。
16.4 主要区别
(一)缓冲区使用:字节流操作不使用缓冲区,字符流使用缓冲区。
(二)资源关闭与输出:字节流不关闭资源也可能输出,字符流不关闭且不刷新则无输出。
(三)读取返回值范围:Reader的read()方法返回0-65535范围的字符(占2字节),InputStream的read()方法返回0-255范围的字节,对于像汉字这类不能用0-255表示的值,需用字符流读取。
(四)处理对象:字节流处理字节、字节数组或二进制对象;字符流处理字符、字符数组或字符串。
17.静态内部类
java
// 外部类
class Outer {
// 外部类静态成员
static int staticVar = 10;
// 外部类非静态成员
int nonStaticVar = 20;
// 静态内部类(嵌套类)
static class Inner {
// 静态内部类静态成员
static int innerStaticVar = 30;
// 静态内部类非静态成员
int innerNonStaticVar = 40;
// 静态内部类方法
void innerMethod() {
// 可访问外部类静态成员
System.out.println("外部类静态变量:" + staticVar);
// 不可访问外部类非静态成员(编译报错)
// System.out.println("外部类非静态变量:" + nonStaticVar);
// 访问自身静态和非静态成员
System.out.println("内部类静态变量:" + innerStaticVar);
System.out.println("内部类非静态变量:" + innerNonStaticVar);
}
}
// 外部类方法
void outerMethod() {
// 访问静态内部类静态成员(直接通过内部类访问)
System.out.println("内部类静态变量:" + Inner.innerStaticVar);
// 访问静态内部类非静态成员(需实例化内部类)
Inner inner = new Inner();
System.out.println("内部类非静态变量:" + inner.innerNonStaticVar);
}
}
// 测试类
public class Test {
public static void main(String[] args) {
// 实例化静态内部类(无需外部类实例)
Outer.Inner inner = new Outer.Inner();
inner.innerMethod();
// 实例化外部类并调用其方法
Outer outer = new Outer();
outer.outerMethod();
}
}
代码展示了Java中静态内部类的使用规则:
定义与实例化: 静态内部类被声明为static,可独立于外部类实例化,无需依赖外部类对象。普通内部类需外部类实例化后才能实例化,而静态内部类可直接通过外部类.内部类 方式实例化。
成员访问规则:
静态内部类内部:不能访问外部类的非静态成员(变量和方法),但可访问外部类的静态成员;自身可定义静态或非静态成员。
外部类访问静态内部类成员:不能直接访问,需通过静态内部类的实例来访问其非静态成员,可直接通过内部类.静态成员访问其静态成员
与非静态内部类的区别:
静态内部类可拥有静态成员,非静态内部类不能有静态成员。
静态内部类的非静态成员可访问外部类静态变量,不可访问外部类非静态变量;非静态内部类的非静态成员可访问外部类非静态变量。
非静态内部类可随意访问外部类成员(包括私有成员),静态内部类对象无法访问外部类非静态成员。
作用域:
静态内部类(如Person类)仅在其外部类(如StaticTest类)范围可见,其他类中引用或初始化会报错。
18.匿名类
**基本定义:**没有名字的内部类。
**成员与方法限制:**不能定义任何静态成员、方法;其中的方法不能是抽象的。
**实现要求:**必须实现接口或抽象父类的所有抽象方法,且因为创建时会立即实例化,所以不能是抽象类。
**继承与实现:**会继承一个父类(有且只有一个)或实现一个接口(有且只有一个),可实现父类或接口中所有抽象方法,也能改写父类方法、添加自定义方法。
**外部类成员访问:**访问的外部类成员变量或成员方法必须用static修饰
**构造器与同名成员:**因为没有类名,不能定义构造器;当与外部类有同名变量(方法)时,默认访问匿名内部类的,要访问外部类的需加上外部类的类名。