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编码规范

  1. 标识符命名规范:望文知意、大小写规则(类名单词首字母大写、变量名或方法名首单词小写后面单词首字母大写、包名全小写、常量名全大写)
  2. 缩进
  3. 注释规范:注释量不低于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 位(浮点数类型将整数部分转换成字符类型)。

    将字符类型转换成数字类型时,字符的统一码转换成指定的数值类型。如果字符的统一码超出了转换成的数值类型的取值范围,则必须显性声明类型转换。

特殊字符与转义字符序列
在这里插入图片描述


💯 例题:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lManAqD0-1625741443282)(JavaSE复习.assets/image-20210630171521801.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iEEDxCx7-1625741443282)(JavaSE复习.assets/image-20210630171559319.png)]

 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变量和常量的储存位置

  1. 类常量和静态变量:基本类型的常量在运行时常量池中,引用类型的常量(例如字符串)在运行时常量池中保存自堆中的直接引用。静态变量也是(因为静态变量必须在类加载的时候就初始化,因为它是可以通过类名访问的)
  2. 除静态变量之外的类变量:类变量只有在对象创建之后才分配内存,所以基本类型的话在堆中的对象中,引用类型的话在堆中、堆中的对象保存引用
  3. 局部变量:局部变量也是只有对象才有的,但是它在方法中,所以其实它是在栈上的:如果是基本类型,就保存在栈上;如果是引用类型,就保存在堆上,然后在栈中保存一个引用

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结合分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yrZ42nK5-1625741443283)(JavaSE复习.assets/image-20210702150557125.png)]

栈空间:用来存储函数内部调用时产生的数据。(局部变量)

栈帧:每次函数调用时的数据 局部变量表

嵌套调用分析

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分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8zs08YhL-1625741443284)(JavaSE复习.assets/image-20210702151335196.png)]
局部变量随栈帧共存亡

递归调用分析

当把一个大问题分解成若干个小问题,发现小问题的求解方式和大问题相同,这时候就可以用递归来解决。

/*这样会导致栈溢出*/
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;
    }

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XJl9DlpW-1625741443284)(JavaSE复习.assets/image-20210702171006974.png)]

计算斐波那契数列的第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(数值类型)falseboolean)  空指针null(对象类型) ,不同的数据类型分配不同默认值。

——显示初始化

a = new int[ ]{5,6,8,9};
数组长度由大括号里的数据决定。

合并写法:

int[] a =new int [5]; //隐式

int[] a = {5,6,8,9}; //显示

3️⃣ 使用

数组名[下标]

⭐️ 常用数组操作

1.查询数组长度 数组名.length a.length

2.遍历数组 (按顺序访问数组中的所有元素)

for(int i = 0; i<a.length;i++){
    操作.....
}

数组的内存结构

public static void main(String[] args){
    int[] a = new int[5];  //只要有new 就是在堆空间开辟空间
}

JVM中分析

这个数组在堆中的空间是连续的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rgV7vsF2-1625741443285)(JavaSE复习.assets/image-20210702220126778.png)]

new int[5];就是开辟这些空间,然后将首地址赋值给a

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zd1IiZiG-1625741443287)(JavaSE复习.assets/image-20210702220235912.png)]

数组的空间在内存中是连续的

  • 数组的长度固定,不可改变
  • 数组的下标从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];  // 长度为三

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vtEuite4-1625741443288)(JavaSE复习.assets/image-20210703094933228.png)]

二维数组的遍历:

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对象的创建过程

  1. 分配堆空间 属性 被赋值为 默认值
  2. 初始化属性 属性 被赋值为 初始值
  3. 调用构造方法 (通常构造方法用来给属性赋值)属性 通常被赋值为 构造参数

对象的使用

//类  对象名 = new 类();
 Girl baby = new Girl(18,"D+");  
//baby 存贮对象的地址
baby.属性;
baby.方法();

3.变量的JVM分析

简单变量 VS 引用

看变量类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bASuVRyE-1625741443289)(JavaSE复习.assets/image-20210703145832644.png)]

  • 8种基本类型的变量 简单变量 存在栈中,存值
  • 引用类型(对象,数组…) 存在栈中的是地址,对象存在堆中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b64iQBJw-1625741443290)(JavaSE复习.assets/image-20210703150414650.png)]

成员变量 VS 局部变量

看定义的位置

  • 局部变量:函数内部定义,存在栈空间
  • 成员变量:函数外部定义,存在堆空间

案例分析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wGirrSg1-1625741443290)(JavaSE复习.assets/image-20210703151609712.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ca9cVeEv-1625741443290)(JavaSE复习.assets/image-20210703151746501.png)]

4.this

特殊的引用,代表对象自身,或者当前对象

this.属性/方法 代表调用当前对象的属性/方法

  • 可写可不写
  • 必须写的时候:局部变量与成员变量同名的时候,并且想访问成员变量
调用构造方法可以直接写this.() 调用本类其他构造方法 

必须是写在构造方法的第一行

5.面向对象的三大特性

封装

任何对象都会有一个明确的边界,这个边界对对象内部的数据起到保护隔离的作用。

访问级别访问控制修饰符同类同包子类(不同包)不同包(其他类)
公共public允许允许允许允许
受保护protected允许允许允许不允许
默认缺省修饰符允许允许不允许不允许
私有private允许不允许不允许不允许

属性设置为private,为属性提供公开的setXXX 和getXXX方法

继承

is a 关系

Class A extends B

结合jvm分析:

[外链图片转存失败,源站可能有防盗链<p>以上是关于3.5万字 JavaSE温故而知新!(结合jvm 基础+高级+多线程+面试题)的主要内容,如果未能解决你的问题,请参考以下文章</p> 
<p > <a style=3.5万字,图解 Pandas

二万字爆肝JavaSE基础知识

JVM万字详解,复习必备。

万字详解JVM,让你一文吃透

2万字长文 JVM 内存结构

万字精美图文 | JVM学习面试大总结