语言基础

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的部分功能有所缺失,但整体相差不大

关键字

标识符

常量与变量

常量

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

数据类型

屏幕截图 2020-09-16 152341

浮点数的表示

屏幕截图 2020-09-13 103503

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

有效数字 = 使用原码存储

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

变量

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

数据类型转换

数据范围从小到大

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

数据溢出

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

ASCII 码表

使用数字表示某些字符

202083111314

运算符

进行特定操作的符号

算术运算符

+ - * / %

加号的三种用法:

自增自减运算符

赋值运算符

比较运算符

> < >= <= == !=

逻辑运算符

&& || !

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

位运算符

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