【剑指 Java】第 1 弹:靠这份 Java 基础知识总结,我拿到了满意的 Offer

2022-06-15 10:39:07 浏览数 (1)

前言

因为博主是 2021 届毕业生,当时为了准备秋招,特意总结的 Java 基础知识面试高频题,最后也算找到了挺满意的工作。因此回馈给大家,希望能对大家起到一定的帮助。

0. 入门常识

0.1 Java 特点

  1. 简单易学
  2. 面向对象(封装、继承、多态)
  3. 平台独立
  4. 安全可靠
  5. 支持多线程
  6. 解释和编译共存
  7. 安全性
  8. 健壮性(Java 语言的强类型机制、异常处理、垃圾的自动收集等)

0.2 Java 和 C

  • 相同点:两者均为 OOP 语言,均支持 OOP 的三大特性(封装、继承、多态);
  • 不同点
    • Java 不存在指针的概念,所以内存更加安全;
    • Java 类是单继承(但是接口可以多继承),C 的类是多继承;
    • Java 中有自动内存管理机制,但是 C 中需要开发者手动释放内存;
    • C/C 中,字符串和字符数组最后均有一个额外的 标志来表示结束,但 Java 中不存在这一概念;

0.3 JRE 和 JDK

  • JRE(Java Runtime Environment),即 Java 运行时环境,是用来运行已经编译过的 Java 程序所需内容的集合(JVM、Java 类库、Java 命令等),不能用来开发新程序;
  • JDK(Java Development Kit),即 Java 开发工具包,是功能齐全的 Java SDK,包含 JRE 拥有的一切,还有编译器和其他工具,如果我们想要创建和编译新程序,就必须使用到它;

0.4 Java 程序编译过程

我们编译的源代码(xxx.java)经 JDK 中的 javac 命令编译后,成为 JVM 能够理解的 Java 字节码(xxx.class),然后经由 JVM 加载,通过解释器 逐行解释执行,这就是为什么能经常听见说 Java 是一门编译和解释共存的语言

其中 JVM 是解释 Java 字节码(xxx.class) 的虚拟机,针对不同系统均有特定实现,方便一次编译,多次运行,即 Java 语言的平台独立性;

1. 数据类型

1.1 基本数据类型

注意:

  1. boolean 一般用 1 bit 来存储,但是具体大小并未规定,JVM 在编译期将 boolean 类型转换为 int,此时 1 代表 true0 代表 false。此外,JVM 还指出 boolean 数组,但底层是通过 byte 数组来实现;
  2. 使用 long 类型时,需要在后边加上 L,否则将其作为整型解析,可能会导致越界;
  3. 浮点数如果没有明确指定 float 还是 double,统一按 double 处理;
  4. char 是用 单引号 ‘’ 将内容括起来,相当于一个整型值(ASCII 值),能够参加表达式运算;而 String 是用 双引号 “” 将内容括起来,代表的是一个地址值;

1.2 引用类型

数据类型

默认值

数组

null

null

接口

null

1.3 封装类

基本数据类型都有其对应的封装类,两者之间的赋值通过 自动装箱自动拆箱 来完成;

  • 自动装箱:将基本数据类型装箱为封装类;
代码语言:javascript复制
// 实际调用 Integer.valueOf(12)
Integer x = 12;
  • 自动拆箱:将封装类拆箱为基本数据类型;
代码语言:javascript复制
Integer x = 12;
// 实际调用 x.intValue()
int y = x;
  • 基本类型与对应封装类的不同
    1. 基本类型只能按值传递,封装类按引用传递;
    2. 基本类型 会在 中创建,效率较高,但可能存在内存泄露问题;封装类对象会在堆中创建,其 引用在栈中创建;

1.4 缓存池

new Integer(123)Integer.valueOf(123) 为例:

  • 通过 new 的方式每次都会创建一个新的对象;
  • 通过 valueOf() 的方式则会优先判断该值是否位于缓存池,如果在的话就直接返回缓存池中的内容,多次调用指向同一个对象的引用;
代码语言:javascript复制
Integer x = new Integer(123);
Integer y = new Integer(123);
// false,通过 new 的方式,每次都会创建一个新对象,指向不同对象
System.out.println(x == y);    
Integer m = Integer.valueOf(123);
Integer n = Integer.valueOf(123);
// true,通过 valueOf() 的方式,先到缓存池中查找,存在时则多次调用也是指向同一对象
System.out.println(m == n);   

2. 字符串 String

2.1 定义

代码语言:javascript复制
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

上述代码为 Java 8 中 String 的定义,其底层实际上使用的是字符(char)数组,而且由于被声明为 final,代表着它 不能被继承。而且一旦初始化之后就不能再去引用其他数组,这样就保证了 String 的不可变性,也因此 String 是线程安全的。

2.2 不可变性的优点

  1. 用于缓存 hash

由于 Stringhash 值被频繁使用,它的不可变性使得 hash 值也不可变,此时只需要进行一次计算;

  1. 字符串常量池(String Pool)的需要

如果一个 String 对象已经被创建过,那么就会优先从字符串常量池中获取其引用,其不可变性确保了不同引用指向同一 String 对象;

  1. 安全性

我们经常用 String 作为我们方法的参数,其不变性能够保证参数不可变;

  1. 线程安全

String 的不可变性让它天生 具备线程安全,能够在多个线程中方便使用而不用考虑线程安全问题。

2.3 String vs StringBuffer vs StringBuffer

主要从三个方面对三者进行对比:

可变性

线程安全

适用场景

String

不可变

安全

操作少量的数据

StringBuffer

可变

安全,内部使用 synchronized 进行同步

多线程操作字符串缓冲区下操作大量数据

StringBuilder

可变

不安全

单线程操作字符串缓冲区下操作大量数据,性能高于 StringBuffer

2.4 字符串常量池(String Pool)

String Pool 位于 方法区,通常保存着所有 字符串字面量(literal strings),在编译期间就被确定。此外,还可以用 String 中的 intern() 方法在运行过程中添加到 String Pool 中。当一个字符串调用 intern() 时,如果 String Pool 中已经存在字面量相同的字符串,则会返回 String Pool 中的引用;如果不存在,则向 String Pool 中添加一个新的字符串,同时返回新字符串的引用;

代码语言:javascript复制
String s1 = new String("aaa");
String s2 = new String("aaa");
// false 两个字符串指向不同对象
System.out.println(s1 == s2);   

String s3 = s1.intern();
String s4 = s1.intern();
// true,常量池中存在字面量相同的字符串,直接取出
System.out.println(s3 == s4);

在下面的代码中,内存分析如下图:

代码语言:javascript复制
String str1 = "村雨遥";
String str2 = "村雨遥";
String str3 = new String("村雨遥");
String str4 = new String("村雨遥");

// true,两个引用指向常量池中的同一对象
System.out.println(str1 == str2);
// false,两个引用指向堆中不同对象
System.out.println(str3 == str4);

2.5 new String(“xxx”)

使用 new 的方式创建字符串对象,会有两种不同的情况:

  1. String Pool 中不存在 “xxx”

此时会创建两个字符串对象,“xxx” 属于字符串字面量,因此在编译期会在 String Pool 中创建一个字符串对象,用于指向该字符串的字面量 “xxx”;然后 new 会在堆中创建一个字符串对象;

  1. String Pool 中存在 “xxx”

此时只需要创建一个字符串对象,由于 String Pool 中已经存在指向 “xxx” 的对象,所以直接在堆中创建一个字符串对象;

3. 基础语法

3.1 注释

  • 单行注释
代码语言:javascript复制
// 这是单行注释
String name = "村雨遥";
  • 多行注释
代码语言:javascript复制
/*
* 这是多行注释
* name,公众号
*/
String name = "村雨遥";
  • 文档注释
代码语言:javascript复制
/**
* @author : 村雨遥
* @param : name,公众号
*/
String name = "村雨遥";

3.2 常见关键字

3.3 标识符和关键字

  • 标识符:用于给程序、类、对象、变量、方法、接口、自定义数据类型等命名;
  • 关键字:特殊的标识符,被 Java 赋予了特殊含义,只能有特定用途;
  • 标识符命名规则(可以参考《阿里巴巴开发手册》,关注公众号【村雨遥】回复【资源下载】下载 PDF)
    1. 标识符由英文字符大小写(a - z, A - Z)、数字(0 - 9)、下划线(_)和美元符号($)组成;
    2. 不能以数字开头,不能是关键字;
    3. 严格区分大小写;
    4. 包名:多个单词组成是所有单词均小写;
    5. 类名和接口:大写驼峰命名法;
    6. 变量名和函数名:多个单词组成时,第一个单词全小写,其他单词采用大写驼峰命名法;
    7. 常量名:字母全部大写,单词之间用下划线(_)分割;

3.4 访问控制符

作用域

当前类

同一 package 的类

子类

其他 package 的类

public

0 人点赞