3.5万字 JavaSE温故而知新!(结合jvm 基础+高级+多线程+面试题)
Posted 结构化思维wz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.5万字 JavaSE温故而知新!(结合jvm 基础+高级+多线程+面试题)相关的知识,希望对你有一定的参考价值。
💟 JavaSE温故而知新
结合jvm学习java。学自胡鑫喆老师(yyds)。可能是你见过最好最通俗的java笔记,每一个例子每一个图都会让你有新的理解。不论是小白初学还是复习用,都会有新的收获。并非最终版 持续更新中。
获取Markdown版或面试题答案可直接私聊
一、Java基础
🐤 为了简洁美观的代码而奋斗!
- 可读性
- 可用性
- 高效性
- 可维护性
- 可重用性
- 可拓展性
- 弱耦合性
JDK、JRE、JVM
JDK(java程序开发包)=JRE +Tools
JRE=JVM(虚拟机)+API
javac ``XXX.java
生成 .class
文件
java XXX
运行
基础语法
Java编码规范
- 标识符命名规范:望文知意、大小写规则(类名单词首字母大写、变量名或方法名首单词小写后面单词首字母大写、包名全小写、常量名全大写)
- 缩进
- 注释规范:注释量不低于100%
1.注释
/**
* @author 王泽
* 这里是文档注释,可以与命令 javadoc 生成帮助文档
*/
public class Jichu01 {
public void zhushi(){//这是行内注释
System.out.println("第一节、注释");
}
/* 这里是多行注释
这里是多行注释
这里是多行注释
*/
}
2.关键字
(1)用于数据类型。
用于数据类型的关键字有 boolean、byte、char、 double、 false、float、int、long、new、short、true、void、instanceof。
(2)用于语句。
用于语句的关键字有break、case、 catch、 continue、 default 、do、 else、 for、 if、return、switch、try、 while、 finally、 throw、this、 super。
(3)用于修饰
用于修饰的关键字有 abstract、final、native、private、 protected、public、static、synchronized、
transient、 volatile。
(4)用于方法、类、接口、包和异常。
用于方法、类、接口、包和异常的关键字有 class、 extends、 implements、interface、 package、import、throws。
还有些关键字,如cat、 future、 generic、innerr、 operator、 outer、rest、var等都是Java保留的没有意义的关键字。
另外,Java还有3个保留字:true、false、null。它们不是关键字,而是文字。包含Java定义的值。和关键字一样,它们也不可以作为标识符使用。
3.数据类型
⭐️ 八大基本数据类型: // 1 字节 占 8位二进制位
基本数据类型 | 存储大小 | 取值范围 | 默认值
byte | 8 位有符号数 |-2^7−27 到 2^7-127−1 | 0
short | 16 位有符号数 |-2^{15}−215 到 2^{15}-1215−1 |0
int | 32 位有符号数 |-2^{31}−231 到 2^{31}-1231−1 |0
long | 64 位有符号数 | -2^{63}−263 到 2^{63}-1263−1 |0L
float | 32 位 | 负数 -3.402823e+38 到 -1.401298e-45,正数 1.401298e-45 到 3.402823e+38 0.0f
double | 64 位 |负数 -1.797693e+308 到 -4.9000000e-324,正数 4.9000000e-324 到 1.797693e+308 0.0d
char |16 位 |0-65535 |’\\u0000’
boolean |1 位 |true 和 false |false👀 注意:
整数类型的直接量默认是 int 类型,如果直接量超出了 int 类型的取值范围,则必须在其后面加上字母 L 或 l,将直接量显性声明为 long 类型,否则会导致编译错误。
浮点类型的直接量默认是 double 类型,如果要将直接量表示成 float 类型,则必须在其后面加上字母 F 或 f。将 double 类型的直接量赋值给 float 类型的变量是不允许的,会导致编译错误。
将小范围类型的变量转换为大范围类型称为拓宽类型,不需要显性声明类型转换。将大范围类型的变量转换为小范围类型称为缩窄类型,必须显性声明类型转换,否则会导致编译错误。
布尔类型不能转换成其他基本数据类型,其他基本数据类型也不能转换成布尔类型。
字符类型与数字类型之间可以进行转换。
将数字类型转换成字符类型时,只使用整数的低 16 位(浮点数类型将整数部分转换成字符类型)。
将字符类型转换成数字类型时,字符的统一码转换成指定的数值类型。如果字符的统一码超出了转换成的数值类型的取值范围,则必须显性声明类型转换。
特殊字符与转义字符序列
💯 例题:
public static void main(String[] args) {
int a =4;
long b =5L;
int c =(int)b;
long d = a;
char e = 'A';
int f = e;
System.out.println(c); //5
System.out.println(d); //4
System.out.println(f); //65
/*Unicode 编码方式
char c ='A'; char c = 65; char c='/u0041';// 这三个都是相等的 都是A
'A' -----65
'a'------97
'0'------48
*/
}
对象数据类型:类,接口,数组
4.变量和常量
变量:
数据类型 变量名 [=值];
作用域:
- 类变量(静态变量) static
- 成员变量(实例变量)
- 局部变量(方法内)先赋值再使用
常量
final MAX_A=10;
Java变量和常量的储存位置
- 类常量和静态变量:基本类型的常量在运行时常量池中,引用类型的常量(例如字符串)在运行时常量池中保存自堆中的直接引用。静态变量也是(因为静态变量必须在类加载的时候就初始化,因为它是可以通过类名访问的)
- 除静态变量之外的类变量:类变量只有在对象创建之后才分配内存,所以基本类型的话在堆中的对象中,引用类型的话在堆中、堆中的对象保存引用
- 局部变量:局部变量也是只有对象才有的,但是它在方法中,所以其实它是在栈上的:如果是基本类型,就保存在栈上;如果是引用类型,就保存在堆上,然后在栈中保存一个引用
5.运算符
- 算数运算符
+ - * / % ++ --
- 赋值运算符
=
- 关系运算符
> < >= <= == != instanceof
- 逻辑运算符
&& || !
- 位运算符
& | ^ ~ >> << >>>
- 条件运算符
xx? xx :xx
- 拓展运算符
+= -= *=...
6.流程控制
顺序结构 程序默认
选择结构
- if 单选择
- if-else 双选择
- if-else if-else 多选择结构
- switch case
循环结构
- while
- do…while
- for
- 增强for循环
几个关键字的使用 break 、continue
break语句在switch中是用来中止case的。实际上break语句在for、while、do···while循环语句中,用于强行退出当前循环,为什么说是当前循环呢,因为break只能跳出离它最近的那个循环的循环体,假设有两个循环嵌套使用,break用在内层循环下,则break只能跳出内层循环,如下:
for(int i=0; i<n; i++) { // 外层循环 for(int j=0; j<n ;j++) { // 内层循环 break; } }
continue语句只能用于for、while、do···while循环语句中,用于让程序直接跳过其后面的语句,进行下一次循环。
例:输出10以内的所有奇数
1 public class ContinueDemo { 2 3 public static void main(String[] args) { 4 int i = 0; 5 6 while(i < 10) { 7 i++; 8 9 if(i%2 == 0) { // 能被2整除,是偶数 10 continue; // 跳过当前循环 11 } 12 13 System.out.print(i + " "); 14 } 15 } 16 17 }
这里if条件判断是否为偶数,如果是偶数则执行continue,直接跳出本次循环,不进行continue后的步骤(即不执行输出语句),然后下一次循环为奇数,输出i
9*9乘法表
public static void main(String[] args) {
for (int i =1;i <= 9;i++){
for (int j=1;j <= i;j++){
System.out.print(j+"*"+i+"="+(i*j)+"\\t");
}
System.out.println("");
}
}
return语句可以从一个方法返回,并把控制权交给调用它的语句。
7.方法(函数)
完成特定功能的一部分独立存在的代码
-
函数的定义
修饰符 (static) 返回值类型 方法名(参数表){ 方法体; }
-
方法的调用
函数名(参数表)
-
方法的参数
(数据类型 形参名1,数据类型 形参名2) 形参:是一个在方法内部有效的局部变量 赋值的时候会发生在函数调用的时候,也就是实参 例如: static void xiaoWang(){ xiaoliu("排骨",8); } static void xiaoliu(String eat,int x){ System.out.println("今天给老公做了"+eat+",还买了"+x+"瓶啤酒"); }
-
方法的返回值
return:程序流程会返回到方法的调用点。
8.方法与JVM结合分析
栈空间:用来存储函数内部调用时产生的数据。(局部变量)
栈帧:每次函数调用时的数据 局部变量表
嵌套调用分析
public static void main(String[] args){
int a =10;
m1(a);
}
static void m1(int b){
m2(b);
}
static void m2(int c){
int d = 20;
}
运行时JVM分析:
局部变量随栈帧共存亡
递归调用分析
当把一个大问题分解成若干个小问题,发现小问题的求解方式和大问题相同,这时候就可以用递归来解决。
/*这样会导致栈溢出*/
public static void main(String[] args){
m1();
}
static void m1(){
m1();
}
递归必备:回归条件
计算n的阶乘
package com.jichu;
/**
* @author 王泽
* 计算n的阶乘
* n! = n* (n-1)!
*/
public class Fact {
public static void main(String[] args) {
System.out.println(fact(4));
}
/**计算n的阶乘*/
static int fact(int n){
if (n==1){ return 1;}
int result = n*fact(n-1);
return result;
}
}
计算斐波那契数列的第n项
static int fobo (int n){ if (n == 1){ return 0;} if (n == 2) {return 1;} return fobo(n-1) + fabo(n-2); }
9.数组
数组的语法:
1️⃣数组的定义:
//数据类型[] 数组名;
int[] a;
2️⃣ 定义后JVM不会为其分配内存,所以我们需要为数组分配空间
——隐式初始化
a = new int[5];
JVM会自动给每个数据给一个默认值 0(数值类型)false(boolean) 空指针null(对象类型) ,不同的数据类型分配不同默认值。
——显示初始化
a = new int[ ]{5,6,8,9};
数组长度由大括号里的数据决定。
合并写法:
int[] a =new int [5]; //隐式
int[] a = {5,6,8,9}; //显示
3️⃣ 使用
数组名[下标]
⭐️ 常用数组操作
1.查询数组长度
数组名.length
a.length2.遍历数组 (按顺序访问数组中的所有元素)
for(int i = 0; i<a.length;i++){ 操作..... }
数组的内存结构
public static void main(String[] args){
int[] a = new int[5]; //只要有new 就是在堆空间开辟空间
}
JVM中分析
这个数组在堆中的空间是连续的。
new int[5];
就是开辟这些空间,然后将首地址赋值给a
数组的空间在内存中是连续的
- 数组的长度固定,不可改变
- 数组的下标从0开始 (追求最快的寻址速度)
- 查询效率是最高的,增加元素或删除元素是最低效率
改变数组长度的方法
- 不可能在原数组中改变
- 只能创建一个新数组
a=b;
把新数组的地址给原数组- 再把原数组里的元素赋值到新数组
b[i]=a[i];
简写:
java.util.Arrays.copyOf(原数组,新数组长度);
多个数组变量中可以存储相同地址
package com.jichu; import java.util.Arrays; /** * @author 王泽 */ public class ShuZu { public static void main(String[] args) { int[] a; a = new int[5]; int[] d = new int[10]; for (int i = 0; i < a.length; i++) { a[i]=i; System.out.println(a[i]); } System.out.println("-----------"); a = d; System.out.println(a.length); System.out.println("------------"); for (int i = 0; i < a.length; i++) { a[i]=i; System.out.println(a[i]); } } }
二维数组
int[][] a; //由若干个整形数组组成
a = new int[3][4]; // 长度为三
二维数组的遍历:
for(int i = 0; i<a.length ; i++){ for(int j=0; j<a[i].length ;j++){ sout(a[i][j]+"\\t"); } }
二维数组的赋值:
int[][] a={{1,2,3,4},{5,6,7,8},{0,5,6,8}}
-
int[][] a =new int[3][]; //不指定二维数组长度的
a[0] = new int[5];
a[1] = new int[3];
a[2] = new int[4];
-
int[][] a =new int[][4]; 这句话是错误的,不能空缺高维长度
面向对象
⭕️ 面向对象的思想
世界是由对象组成,对象:一切客观存在的事物。 # 1.对象的组成: - 属性 对象有什么 - 方法 对象能做什么,行为 # 2.对象之间的联系 - is a 继承关系 - has a 关联关系(一个对象成为另一个对象的属性) - use a 依赖关系(一个对象调用另一个对象的方法) # 3.面向对象的思想 - 面对需求,我们先找出解决问题的对象,让对象之间建立适当的关系。
💻 面向对象的编程思想
用计算机中的对象,模拟现实中的对象。
用计算机中类型的概念,对应现实世界中的类的概念
类:对象共性的抽象,人对一类事物的认识。
人(类)-李沁(对象)
1.定义一个Java类
成员变量与局部变量对比:(定义位置不同)
- 成员变量有默认值 在对象创建的过程中,属性会被自动分配到默认值
- 成员比那里的作用范围,至少是全类内部
- 成员变量和局部变量可以同名,同名时局部变量优先访问
方法:行为(对象的功能) 函数
方法声明:
// 修饰符(多个,顺序不重要) 返回值类型 方法名(参数表)抛出的异常 public static void main(String[] args)
方法实现:{ }
构造方法 特殊的方法
- 没有返回值类型
- 方法名必须和类名相同
- 不允许手工调用,在对象的构造过程中自动调用
- 如果不写,会自动生成无参构造
方法的重载
一个类的同一个行为,由于参数的不同所造成的实现差异,对对象的调用者屏蔽
方法名相同,参数表不同(只有参数名不同,不构成重载)
理解:例如我们有一个人的类,类里有吃的方法,根据方法的重载传不同的食物对应不同的吃法。
2.对象的创建和使用
对象的创建:
一个类就相当于自定义的数据类型,创建对象就像基础数据类型一样的声明方法,只不过要用new来创建。
通过类创建对象new
new 类名();
//() ---> 构造方法
结合JVM对象的创建过程
- 分配堆空间 属性 被赋值为 默认值
- 初始化属性 属性 被赋值为 初始值
- 调用构造方法 (通常构造方法用来给属性赋值)属性 通常被赋值为 构造参数
对象的使用
//类 对象名 = new 类();
Girl baby = new Girl(18,"D+");
//baby 存贮对象的地址
baby.属性;
baby.方法();
3.变量的JVM分析
简单变量 VS 引用
看变量类型
- 8种基本类型的变量 简单变量 存在栈中,存值
- 引用类型(对象,数组…) 存在栈中的是地址,对象存在堆中
成员变量 VS 局部变量
看定义的位置
- 局部变量:函数内部定义,存在栈空间
- 成员变量:函数外部定义,存在堆空间
案例分析:
4.this
特殊的引用,代表对象自身,或者当前对象
this.属性/方法 代表调用当前对象的属性/方法
- 可写可不写
- 必须写的时候:局部变量与成员变量同名的时候,并且想访问成员变量
调用构造方法可以直接写this.() 调用本类其他构造方法
必须是写在构造方法的第一行
5.面向对象的三大特性
封装
任何对象都会有一个明确的边界,这个边界对对象内部的数据起到保护隔离的作用。
访问级别 | 访问控制修饰符 | 同类 | 同包 | 子类(不同包) | 不同包(其他类) |
---|---|---|---|---|---|
公共 | public | 允许 | 允许 | 允许 | 允许 |
受保护 | protected | 允许 | 允许 | 允许 | 不允许 |
默认 | 缺省修饰符 | 允许 | 允许 | 不允许 | 不允许 |
私有 | private | 允许 | 不允许 | 不允许 | 不允许 |
属性设置为private,为属性提供公开的setXXX 和getXXX方法
继承
is a 关系
Class A extends B
结合jvm分析:
3.5万字,图解 Pandas