语言基础

JAVA运行环境

Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。

JDK 是 Java Development Kit,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器(javac)和工具,能够创建和编译程序。

JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。

oracle jdk与openjdk

Oracle JDK由Oracle公司开发,Oracle JDK采用了商业实现OpenJDK是Java SE平台版的开源和免费实现,虽然OpenJDK的部分功能有所缺失,但整体相差不大

关键字

标识符

常量与变量

常量

在程序运行期间,固定不变的量

数据类型

类型名称默认值大小最小值最大值包装类缓存区间
booleanfalse1B0(false)1(true)Boolean
byte(byte)01B-128127Byte-128~127
char'\u0000'2B'\u0000''\uFFFF'Character(char)0 ~ (char)127
short(short)02B-3276832767Short-128 ~ 127
int04B-2^312^31-1Integer-128 ~ 127
long0L8B-2^632^63-1Long-128 ~ 127
float0.0f4B1.4e-453.4e+38Float
double0.0d8B4.9e-3241.798e+308Double

浮点数的表示

packet-beta  0-22: "有效数字(23位)"  23-30: "指数(8位)"  31: "符号(1位)"

指数 = $X + 2^{x的二进制位数-1}$

有效数字 = 使用原码存储

由于某些数字不能由有限二进制位精确表示 所以会出现1f-0.9f != 0.1 这种情况

变量

程序运行期间,内容可以发生改变的量

数据类型转换

数据范围从小到大

范围小的类型 范围小的变量名 = (范围小的类) 原本范围大的数据;

数据溢出

当被转换的数值范围大于目标类型时,就会发生数据溢出,导致一部分数据丢失

ASCII 码表

使用数字表示某些字符

202083111314

运算符

进行特定操作的符号

算术运算符

+ - * / %

加号的三种用法:

自增自减运算符

赋值运算符

比较运算符

> < >= <= == !=

逻辑运算符

&& || !

当 a && b 中的a为false时 就不会去计算b表达式

位运算符

// 以下所有操作都代表的是在2进制操作下System.out.println(2 << 2); // 左移 8System.out.println(2 >> 1); // 右移 2System.out.println(0xffffffff >>> 3); // 无符号右移(忽略掉符号位,对符号位也会移动)System.out.println(8 | 0); // 位或 8System.out.println(8 & 0); // 位与 0System.out.println(8 ^ 0); // 异或 8System.out.println(~8); // 位非 -9

方法

方法签名包括方法名称与参数列表 是方法的唯一标识

方法调用

参数的传递

在JAVA中 参数都是通过值来进行传递的

要避免使用Object作为可变参数

入参保护:对于入参数据量进行判断控制 处理不了 直接返回错误

参数校验:对于外部的输入 都需要校验 基于防御式编程理念 但是对于一些底层的方法就不必校验 越靠近外部 越需要校验

修饰符

访问权限修饰符

static

可以被用来:

  1. 修饰类变量
  1. 修饰方法
  1. 修饰代码块

初始化时机

  1. 父类的静态变量和静态块比子类优先初始化;
  2. 静态变量和静态块比类构造器优先初始化。

问:如何证明 static 静态变量和类实例无关

答:不需要创建该类的实例就可以使用静态变量与静态方法

问:变量和方法被 static 和 final 两个关键字修饰,为什么这么做

答:static可以直接使用这些方法与变量,final则是变量地址不可变,方法不可覆写,提升稳定性

问:catch 中发生了未知异常,finally 还会执行么

答:会,但是异常会被catch吞掉

final

transient

用来修饰类变量,意思是当前变量是无需进行序列化的

default

修饰之后该方法就代表是一个默认实现,如果其他类继承该接口,就可以不用实现该方法,直接使用这个默认实现

abstract

synchronized

方法重载

指在同一个类中,允许存在一个以上的同名方法,只要它们的参数列表不同即可,与修饰符和返 回值类型无关

重载可以在编译时确定调用的方法 也被称为静态绑定

void test(){  f(1);}// 重载方法的选择:void f(int i){} // 1. 精确匹配void f(long i){} // 2. 基本类型会自动转换成更大的数据类型void f(Integer i){} // 3. 自动装箱拆箱void f(Object i){} // 4. 向上转型进行匹配void f(Integer... i){} // 5. 最终通过可变参数匹配

方法重写

对于子类 其可以改变父类的方法实现

  1. 父类无法调用在父类没有定义的方法
  2. 父类可以调用到子类重写的父类的方法

子类重写的条件:

构造方法

类内方法

外部使用静态成员时 尽量使用 类名.静态成员 来调用

静态方法:

getter 与 setter

为什么使用:

几种情况警惕:

特殊方法

finalize方法

很早之前就已经被弃用了,不仅会导致垃圾回收变慢,甚至会导致死锁等问题产生

一个替代品是从 JDK9 引入的java.lang.ref.Cleaner

public class CleaningExample implements AutoCloseable {    // A cleaner, preferably one shared within a library    private static final Cleaner cleaner = Cleaner.create();    static class State implements Runnable {        State() {            // initialize State needed for cleaning action        }        public void run() {            // cleanup action accessing State, executed at most once            System.out.println("清理操作");        }    }    private final State state;    private final Cleaner.Cleanable cleanable;    public CleaningExample() {        this.state = new State();        this.cleanable = cleaner.register(this, state);    }    public void close() {        cleanable.clean();    }    public static void main(String[] args) {        try (var a = new CleaningExample()){}    }}

这个机制也有缺陷,跟一些第三方框架一样,都是通过虚引用来实现对资源的清理

main方法

同步异步

异步处理的任务是非时间敏感的 异步调用需要通过诸如轮询的方式获取执行结果 轮询会增加机器的压力

流程控制

顺序结构

分支结构

java8 switch 支持的表达式:

循环结构

for(初始化表达式①; 布尔表达式②; 步进表达式④){     循环体③}
初始化表达式①   while(布尔表达式②){         循环体③          步进表达式④ }
初始化表达式①     do{         循环体③         步进表达式④ }while(布尔表达式②)

跳出语句

死循环

嵌套循环

数组

数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致。

定义

int arr = new int[3];int arr = new int[]{1,2,3};

访问

int a = arr[2];int l = arr.length;

== 与 equals

== 运算符比较的是两个对象的地址equals默认实现也是比较地址,如果重写了equals,可以根据相应的逻辑来判断两个对象是否相等

hashCode 与 equals

只要覆写 equals,就必须覆写 hashCode;因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须覆写这两个方法;

如果自定义对象作为 Map 的键,那么必须覆写 hashCode 和 equals。说明:String 已覆写 hashCode 和 equals 方法,所以我们可以愉快地使用 String 对象作为 key 来使用。

有些数据结构比较两个元素相同时是先进行hashcode比较,然后才是equals

final关键字