2022年10月10日 11:27 周一转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
何为反射
#
赋予了我们在运行时分析类以及执行类中方法的能力;运行中获取任意一个类的所有属性和方法,以及调用这些方法和属性
应用场景
#
Spring/Spring Boot 、MyBatis等框架都用了大量反射机制,以下为
JDK动态代理
Cglib动态代理(没有实现接口的Car
...
2022年10月10日 10:39 周一转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
什么是序列化?什么是反序列化
#
当需要持久化Java对象,比如将Java对象保存在文件中、或者在网络中传输Java对象,这些场景都需要用到序列化
即:
- 序列化:将数据结构/对象,转换成二进制字节流
- 反序列化:将在序列化过程中所生成的二进制字节流,转换成数据结构或者对象的过程
对于Java,序列化的是对象(Object),也就是实例化后的类(Class)
序列化的目的,是通过网络传输对象,或者说是将对象存储到文件系统、数据库、内存中,如图:

实际场景
#
- 对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
- 将对象存储到文件中的时候需要进行序列化,将对象从文件中读取出来需要进行反序列化。
- 将对象存储到缓存数据库(如 Redis)时需要用到序列化,将对象从缓存数据库中读取出来需要反序列化
序列化协议对于TCP/IP 4层模型的哪一层
#
4层包括,网络接口层,网络层,传输层,应用层
如下图所示:

OSI七层协议模型中,表示层就是对应用层的用户数据,进行处理转换成二进制流;反过来的话,就是将二进制流转换成应用层的用户数据,即序列化和反序列化,
因为,OSI 七层协议模型中的应用层、表示层和会话层对应的都是 TCP/IP 四层模型中的应用层,所以序列化协议属于 TCP/IP 协议应用层的一部分
常见序列化协议对比
#
kryo 英音 [k’rɪəʊ] ,除了JDK自带的序列化,还有hessian、kryo、protostuff
2022年10月9日 11:30 周日转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
形参&&实参
值传递&&引用传递
- 程序设计将实参传递给方法的方式分为两种,值传递:方法接收实参值的拷贝,会创建副本;引用传递:方法接受的是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参
Java中只有值传递,原因:
传递基本类型参数
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
System.out.println("num1 = " + num1);
System.out.println("num2 = " + num2);
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
//输出
a = 20
b = 10
num1 = 10
num2 = 20
传递引用类型参数 1
...
2022年10月8日 15:23 周六转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
异常
#
(算数异常,类型转换异常,不合法的线程状态异常,下标超出异常,空指针异常,参数类型异常,数字格式异常,不支持操作异常)
ArithmeticException,ClassCastException,IllegalThreadStateException,IndexOutOfBoundsException
NullPointerException,IllegalArgumentException,NumberFormatException,SecurityException,UnsupportedOperationException
```illegal 英[ɪˈliːɡl] 非法的```
```Arithmetic 英[əˈrɪθmətɪk] 算术```
Error: 程序无法处理的错误 ,不建议通过catch 捕获,已办错误发生时JVM会选择线程终止
OutOfMemoryError (堆,Java heap space),VirtualMachineError,StackOverFlowError,AssertionError (断言),IOError
Throwable类常用方法
- String getMessage() //简要描述
- String toString() //详细
- String getLocalizedMessage() //本地化信息,如果子类(Throwable的子类)没有覆盖该方法,则与gtMessage() 结果一样
- void printStackTrace() //打印Throwable对象封装的异常信息
try-catch-finally如何使用
try后面必须要有catch或者finally;无论是否捕获异常,finally都会执行;当在 try
块或 catch
块中遇到 return
语句时,finally
语句块将在方法返回之前被执行。
...
2022年9月29日 10:16 周四转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
面向对象基础
#
区别
- 面向过程把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。
- 面向对象会先抽象出对象,然后用对象执行方法的方式解决问题。
- 面向对象编程 易维护、易复用、易扩展
对象实例与对象引用的不同
new 运算符,new 创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。
一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。
对象的相等一般比较的是内存中存放的内容是否相等;引用相等一般比较的是他们指向的内存地址是否相等
如果一个类没有声明构造方法,该程序能正确执行吗?
如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了
- 构造方法特点:名字与类名相同;没有返回值但不能用void声明构造函数;生成类的对象时自动执行
- 构造方法不能重写(override),但能重载 (overload)
面向对象三大特征
2022年9月28日 10:51 周三转载自https://github.com/Snailclimb/JavaGuide (添加小部分笔记)感谢作者!
基础概念及常识
#
Java语言特点
- 面向对象(封装、继承、多态)
- 平台无关性(Java虚拟机)
- 等等
JVM并非只有一种,只要满足JVM规范,可以开发自己专属JVM
JDK与JRE
- JDK,JavaDevelopmentKit,包含JRE,还有编译器(javac)和工具(如javadoc、jdb)。能够创建和编译程序
- JRE,Java运行时环境,包括Java虚拟机、Java类库,及Java命令等。但是不能创建新程序
字节码,采用字节码的好处
- Java中,JVM可以理解的代码称为字节码(.class文件),不面向任何处理器,只面向虚拟机
- Java程序从源代码到运行的过程

- java代码必须先编译为字节码,之后呢,.class–>机器码,这里JVM类加载器先加载字节码文件,然后通过解释器进行解释执行(也就是字节码需要由Java解释器来解释执行)
- Java解释器是JVM的一部分
编译与解释并存
- 编译型:通过编译器将源代码一次性翻译成可被该平台执行的机器码,执行快、开发效率低
- 解释型:通过解释器一句一句的将代码解释成机器代码后执行,执行慢,开发效率高
- 如图

为什么说 Java 语言“编译与解释并存”?
这是因为 Java 语言既具有编译型语言的特征,也具有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class
文件),这种字节码必须由 Java 解释器来解释执行。
Java与C++区别
- 没学过C++,Java不提供指针直接访问内存
- Java为单继承;但是Java支持继承多接口
- Java有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存
注释分为 单行注释、多行注释、文档注释

标识符与关键字
标识符即名字,关键字则是被赋予特殊含义的标识符
自增自减运算符
当 b = ++a
时,先自增(自己增加 1),再赋值(赋值给 b);当 b = a++
时,先赋值(赋值给 b),再自增(自己增加 1)
continue/break/return
continue
:指跳出当前的这一次循环,继续下一次循环。break
:指跳出整个循环体,继续执行循环下面的语句。return
用于跳出所在方法,结束该方法的运行。
变量
- 成员变量和局部变量
- 成员变量可以被
public
,private
,static
等修饰符所修饰,而局部变量不能被访问控制修饰符及 static
所修饰;但是,成员变量和局部变量都能被 final
所修饰 - 从变量在内存中的存储方式来看,如果成员变量是使用
static
修饰的,那么这个成员变量是属于类的,如果没有使用 static
修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。 - 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动生成,随着方法的调用结束而消亡(即方法栈弹出后消亡)。
- final必须显示赋初始值,其他都自动以类型默认值赋值
- 静态变量:被类所有实例共享
字符型常量与字符串常量区别
...
2022年9月23日 10:31 周五代码
#
static int s;
int i;
int j;
{
int i = 1;
i++;
j++;
s++;
}
public void test(int j) {
j++;
i++;
s++;
}
public static void main(String[] args) {
Exam5 obj1 = new Exam5();
Exam5 obj2 = new Exam5();
obj1.test(10);
obj1.test(20);
obj2.test(30);
System.out.println(obj1.i + "," + obj1.j + "," + obj1.s);
System.out.println(obj2.i + "," + obj2.j + "," + obj2.s);
}
运行结果
#
分析
#
就近原则
#
代码中有很多修改变量的语句,下面是用就近原则+作用域分析的图

...
2022年9月22日 21:20 周四编程题
#
有n步台阶,一次只能上1步或2步,共有多少种走法
分析
#
分析
n = 1,1步 f(1) = 1
n = 2, 两个1步,2步 f(2) = 2
n = 3, 分两种情况: 最后1步是2级台阶/最后1步是1级台阶,
即 f(3) = f(1)+f(2)
n = 4, 分两种情况: 最后1步是2级台阶/最后1步是1级台阶,
即f(4) = f(2)+f(3)
也就是说,不管有几(n)个台阶,总要分成两种情况:最后1步是2级台阶/最后1步是1级台阶,即 f(n)= f(n-2) + f(n-1)
递归
#
public static int f(int n){
if(n==1 || n==2){
return n;
}
return f(n-2)+f(n-1);
}
public static void main(String[] args) {
System.out.println(f(1)); //1
System.out.println(f(2)); //2
System.out.println(f(3)); //3
System.out.println(f(4)); //5
System.out.println(f(5)); //8
}
- debug调试
方法栈
f(4)—->分解成f(2)+f(3)
f(2)—返回-
f(3)—f(2)返回—f(1)返回 【f(3)分解成f(2)和f(1)】
方法栈的个数:

使用循环
#
public static int loop(int n){
if (n < 1) {
throw new IllegalArgumentException(n + "不能小于1");
}
if (n == 1 || n == 2) {
return n;
}
int one=2;//最后只走1步,会有2种走法
int two=1;//最后走2步,会有1种走法
int sum=0;
for(int i=3;i<=n;i++){
//最后跨两级台阶+最后跨一级台阶的走法
sum=two+one;
two=one;
one=sum;
}
return sum;
}

...
2022年9月22日 10:24 周四代码
#
public class Exam4 {
public static void main(String[] args) {
int i = 1;
String str = "hello";
Integer num = 2;
int[] arr = {1, 2, 3, 4, 5};
MyData my = new MyData();
change(i, str, num, arr, my);
System.out.println("i = " + i);
System.out.println("str = " + str);
System.out.println("num = " + num);
System.out.println("arr = " + Arrays.toString(arr));
System.out.println("my.a = " + my.a);
}
public static void change(int j, String s, Integer n, int[] a,
MyData m) {
j+=1;
s+="world";
n+=1;
a[0]+=1;
m.a+=1;
}
}
结果
...