根据多种资料,整理了一些 Java 相关的知识内容。

1. Java基础

1.1 Java入门

Java语言特点?

  • 简单易学;面向对象(封装、继承、多态);平台无关性(一次编译,到处运行);可靠性;安全性;多线程;网络编程;编译与解释并存。

JVM、JDK、JRE都是什么?

  • JVM:JVM是运行Java字节码的虚拟机,根据系统有不同版本。

    • Java通过将源代码转换为字节码,解决了传统解释型语言效率低的问题,编译一次.java文件生成的字节码文件.class文件可以在各种环境下解释运行。
    • 由于字节码解释运行也比较慢,因此后面还引入了JIT编译器,运行时编译,将常用部分的字节码转换为机器码保存。
    • 由于JIT也比较慢,后面引入了AOT编译模式,直接将字节码转换为机器码,但质量不如JIT

    image-20201122170623472

  • JDK:JDK是Java开发环境,是功能齐全的Java SDK。

    • JDK拥有JRE的一切,还拥有编译器javac,工具(如javadoc和jdb)。能够创建和编译程序。
    • API:应用程序接口,提供功能。
    • SDK:软件开发工具包,提供开发基础。
  • JRE:JRE是Java运行时环境,是运行已编译Java程序所需的所有内容的集合。

    • 包括JVM、Java类库、Java命令和其他基础构件。
    • 但JRE不能用于创建新程序。
    • 只运行不开发通常只需要JRE,但有时候也需要JDK,如需要JSP部署Web应用程序,服务器将JSP转换为Java Servlet,需要用JDK编译Java Servlet

Oracle JDK和OpenJDK有啥区别?

  • OpenJDK是一个开源参考模型,Oracle JDK是OpenJDK的一个实现。
  • Oracle JDK更稳定、更高性能。

Java和C++有啥异同?

  • 都是面向对象语言,支持封装、继承、多态。
  • Java不提供指针来直接访问内存。
  • Java类单继承,C++类可以多继承,Java接口可以多继承。
  • Java有自动内存管理垃圾回收机制GC
  • Java字符串结尾不需要\0,因为字符串相当于对象,有长度属性。

Java主类是什么?

  • Java主类是程序执行的入口。
  • Java应用程序中,主类是包含main()方法的类,不一定是public类。
  • Java小程序中,主类是继承自系统类JAppletJApplet的子类,一定是public类。(?)

Java包和Javax有啥关系?

  • 两者指的是一个东西,都是Java API的组成部分。

为啥说Java语言编译与解释并存?

  • 编译是一次性翻译,解释是逐行解释。
  • Java先编译生成字节码,再解释成机器码,因此两者并存。

1.2 Java语法

字符型和字符串型的区别?

  • 字符型是单引号围起来的一个字符,占2字节空间,可以参与运算。

  • 字符串型是双引号围起来的若干字符。

    image-20201123062401818

Java注释有哪些?

  • 单行注释,多行注释,文档注释。
  • 好的代码是最好的注释。

标识符和关键字的区别?

  • 标识符就是一个名字。
  • 关键字是系统赋予特殊含义的标识符。

Java关键字有哪些(需要注意的)?

  • 访问控制
  • 类、方法和变量修饰符:extends、final、implements、interface、strictfp、synchronized、transient、volatile。
  • 程序控制:instanceof、switch、case、default。
  • 错误处理:finally。
  • 包相关
  • 基本类型
  • 变量引用:super、this、void。
  • 保留字:goto、const。

自增自减运算符是啥?

  • ++、--在前面就先变化再赋值,在后面就是先赋值再变化。

泛型是啥?

  • 泛型是参数化类型,将操作的数据类型作为一个参数。

  • 泛型包括泛型类、泛型接口、泛型方法。

    image-20201123092019605

    image-20201123092031004

    image-20201123092042616

类型擦除是啥?

  • 类型擦除是Java编译期间,所有泛型信息会被擦除,不会在字节码中出现。
  • 类型擦除造成编译时检测可能会存在问题。

常用通配符有啥?

  • ?:不确定类型。
  • E:元素。
  • K:键。
  • V:值。
  • T:具体类型。

==和equals()的区别是啥?

  • ==判断的是是否是同一对象,即内存地址。
  • equals()没有覆盖,和==等价,也是判断是否是同一对象,即内存地址。
  • equals()覆盖了,一般都是

equals()和hashcode()有啥关系?

  • 两个对象相等,则hashcode()获取的哈希码一定相等。
  • 两个对象哈希码相等,两个对象不一定相等。
  • 因此,equals()修改了,hashcode()为了保证满足上面两个性质,也要修改。

1.3 基本数据类型

自动装箱拆箱是啥?

  • 装箱:将基本类型用对应的引用类型包装起来。
  • 拆箱:将包装类型转换为基本数据类型。

常量池是啥?

  • 常量池是包装类默认创建的缓存数据。

  • Byte、Short、Integer、Long默认创建了[-128, 127]的缓存数据。

  • Character创建了[0, 127]的缓存数据。

  • Boolean创建了True和False。

  • Float、Double没有常量池。

    image-20201123100151164

1.4 方法(函数)

Java为啥只有值传递?

  • Java采用按值调用(call by value),方法得到的是参数值的拷贝,不能修改参数变量的内容。
  • 另一种方法是按引用调用(call by reference),可以修改参数变量内容。
  • Java不能修改基本数据类型参数,但可以修改对象类型的内部参数,如数组内部,但不能修改对象。

重载和重写有啥区别?

  • 重载:一个方法,根据输入数据不同,进行不同处理。
  • 重写:子类继承并覆盖父类方法。
  • 重载发生在编译期,重写发生在运行期。
  • 重写要求范围相同或更小。
  • 重写要求返回、方法、参数都要相同。
  • 重写要求private、final、static的方法和构造方法不能重写。

浅拷贝和深拷贝有啥区别?

  • 浅拷贝:对对引用数据类型进行引用传递。
  • 深拷贝:对引用数据类型,新建一个对象,并复制内容。
  • 两者对基本数据类型都是值传递。

2. Java面向对象

2.1 类和对象

面向过程和面向对象有啥区别?

  • 面向过程:性能更高,不需要实例化类。
  • 面向对象:易复用、易维护、易扩展。具有封装、继承、多态的特性,能开发高复用低耦合的系统。
  • Java性能低于C和它半编译的特性也相关。

构造器能否被重写和重载?

  • 构造器不能重写,但可以重载。

没有参数没有内容的构造方法有啥作用?

  • 执行子类构造方法时,如果子类构造方法没有用super指定特定的父类构造方法,就会默认调用没有参数和没有内容的父类构造方法,帮助子类初始化。因此,父类需要构造这样的方法。

成员变量和局部变量有啥区别?

  • 成员变量:属于类,可以用类修饰符和static修饰符,存在于堆内存,生命周期与对象相同。
  • 局部变量:存在于栈内存,生命周期与方法相同。
  • 用static修饰的成员变量是类变量,没有则是实例变量。
  • 成员变量和局部变量都能用final修饰符。

为啥要写无参构造方法?

  • 没有写构造方法,Java会自动添加无参构造方法。但写了构造方法,Java就不会添加无参构造方法。这时要是不手动添加无参方法,容易出错。因此需要写无参构造方法。

构造方法有啥特性?

  • 名字与类名相同。
  • 可以有修饰符,但不用void修饰符,没有返回值。
  • 构造时自动调用。

对象相等和引用相等,有啥区别?

  • 对象相等:内存存放内容相等。
  • 引用相等:内存地址相等。

封装是啥?

  • 封装是把一个对象的状态信息隐藏在对象内部,外部不能直接访问,但可以通过提供的方法进行访问。

继承是啥?

  • 继承是用已存在的类的定义作为基础,构建新类。
  • 通过继承,可以提高代码重用、程序可维护性、节省时间、提高效率。

多态是啥?

  • 多态是同一个对象根据不同实例执行不同操作,具体体现在父类引用指向子类对象

    image-20201123113345605

  • 引用调用哪个类的方法,只有程序运行期才能确定。

  • 多态不能调用只有子类有,父类没有的方法。

2.3 修饰符

为啥静态方法不能调用非静态成员?

  • 静态方法可以不通过对象进行调用,因此不能调用其他非静态变量和非静态变量成员。

静态方法和实例方法有啥不同?

  • 静态方法:可以用类名.方法名或`对象名.方法名两种方式调用。只能访问静态成员。
  • 实例方法:只能用对象名.方法名方式调用。可以访问任何成员。

2.4 接口和抽象类

接口和抽象类有啥不同?

  • 接口:JDK7中,接口只能有常量变量和抽象方法。JDK8中,接口可以有默认方法和静态方法。JDK9中,接口可以有私有方法和私有静态方法。接口变量只能有static和final变量。接口是一种行为规范。
  • 抽象类:抽象类可以有非抽象方法。抽象类是一种模板设计。

2.5 其他重要知识点

String、StringBuffer和StringBuilder有啥区别?

  • String:对象不可变,因为用final修饰字符数组存储内容。常量,所以线程安全。
  • StringBuffer:对象可变,没有用final修饰字符数组。没有同步锁,线程不安全。
  • StringBuilder:对象可变,没有用final修饰字符数组。有同步锁,线程安全。
  • 少量数据String合适,单线程大量数据StringBuilder合适,多线程大量数据StringBuffer合适。

Object类有啥方法?

  • Object类是所有类的父类。主要包含11个方法。

    public final native Class getClass()//native方法,用于返回当前运行时对象的Class对象,使用了final关键字修饰,故不允许子类重写。
    
    public native int hashCode() //native方法,用于返回对象的哈希码,主要使用在哈希表中,比如JDK中的HashMap。
    
    public boolean equals(Object obj)//用于比较2个对象的内存地址是否相等,String类对该方法进行了重写用户比较字符串的值是否相等。
    
    protected native Object clone() throws CloneNotSupportedException//naitive方法,用于创建并返回当前对象的一份拷贝。一般情况下,对于任何对象 x,表达式 x.clone() != x 为true,x.clone().getClass() == x.getClass() 为true。Object本身没有实现Cloneable接口,所以不重写clone方法并且进行调用的话会发生CloneNotSupportedException异常。
    
    public String toString()//返回类的名字@实例的哈希码的16进制的字符串。建议Object所有的子类都重写这个方法。
    
    public final native void notify()//native方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
    
    public final native void notifyAll()//native方法,并且不能重写。跟notify一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
    
    public final native void wait(long timeout) throws InterruptedException//native方法,并且不能重写。暂停线程的执行。注意:sleep方法没有释放锁,而wait方法释放了锁 。timeout是等待时间。
    
    public final void wait(long timeout, int nanos) throws InterruptedException//多了nanos参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上nanos毫秒。
    
    public final void wait() throws InterruptedException//跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
    
    protected void finalize() throws Throwable { }//实例被垃圾回收器回收的时候触发的操作

transient关键字有啥用?

  • transient用于避免序列化,即存储在内存中。transient只能修饰变量,不能修饰类和方法。

获取键盘输入有啥好方法?

  • Scanner:

    image-20201123164824769

  • BufferedReader:

    image-20201123164835435

3. Java核心技术

3.1 反射机制

Java反射机制是啥?

  • 反射机制是,运行期间,类可以获取所有实时属性和方法,对象可以调用所有实时属性和方法。
  • 反射机制属于动态编译,运行时确定类型,绑定对象。
  • 反射机制能够提高代码灵活性。
  • 反射机制相当于一系列解释操作,性能降低。反射机制还可能造成安全问题。

反射机制用在啥地方?

  • 模块化开发,调用对应字节码应用了反射机制。
  • 动态代理设计模式应用了反射机制。
  • 框架如Spring、Hibernate等应用了反射机制。具体而言,Spring的IOC创建对象和AOP都应用了反射机制。

3.2 异常

Java异常类结构是啥?

  • java.lang包内的Throwable类是所有异常类的祖先。
  • Throwable有两个子类:Error错误子类,Exception异常子类。
  • Error子类:存放程序无法处理的错误,主要是JVM故障。
  • Exception子类:存放程序错误,主要是程序设计存在问题。

Throwable类有啥常用方法?

  • 常用方法包括:

try-catch-finally是啥套路?

  • try:用于捕获异常,后面可跟若干个catch块,可以跟finally块。如果没有catch块,则要跟一个finally块。
  • catch:用于处理try捕获到的异常。
  • finally:无论是否捕获到,finally都会执行。如果catch中有return,finally会接着return执行,还可以修改return值。

finally啥时候不执行?

  • finally第一句出现异常。
  • 前面的代码System.exit(int)关闭程序。
  • 程序所在线程死亡。
  • CPU关闭。

try-with-resources又是啥套路?

  • try-with-resources是Java 7后推荐使用的方法,比try-catch-finally能捕获更多有用的信息。

  • try-with-resources中,任何catch或finally块在声明的资源关闭后运行。多个资源需要关闭时可以用分号分隔开。

    image-20201124205936960

3.3 多线程

程序、进程和线程有啥关系?

  • 程序:程序是含有指令和数据的文件,存储在存储设备中,是静态的代码。
  • 进程:进程是程序的一次执行过程,是系统运行程序的基本单位,是动态的。进程按顺序执行指令,占用一定系统资源。进程相互独立。
  • 线程:线程是比进程更小的单位,由进程创建,多个线程共享一个内存空间和系统资源。线程切换影响比进程小。

线程有啥基本状态?

  • 线程包括6种基本状态:

    image-20201124211213417

    image-20201124211158998

  • NEW -> start() -> READY -> time -> RUNNING -> wait() -> WAITING -> TIME_WAITING -> BLOCKED -> run() -> TERMINATED

3.4 文件与I\O流

Java中的I\O流都有啥?

  • I\O流包括:输入流、输出流;字节流、字符流;节点流、处理流。
  • I\O流类包括:InputStream/Reader、OutputStream/Writer,分别是输入流、输出流基类,前后分别是字节流和字符流。

字节流和字符流有啥区别?

  • 字节流:更适合传递媒体文件
  • 字符流:更适合传递文字。需要字节转换步骤,耗时易出错,不适合处理媒体文件。

BIO、NIO、AIO有啥区别?

  • BIO:同步阻塞IO模型,数据读写必须阻塞在一个线程内。适用于低负载、低并发应用程序。
  • NIO:同步非阻塞IO模型。适用于高负载、高并发应用程序。
  • AIO:NIO的改进版,异步非阻塞IO模型,但目前应用不广泛。

4. Java基础难点

4.1 Java基础

equals()为啥容易出错?

  • equals()容易抛出空指针异常。如:

    image-20201125061057606

    改正:

    image-20201125061118003

  • 使用java.util.Object.equals()可以有效避免抛出空指针异常。因为里面自带了前面字符串判断null逻辑。

    image-20201125061142864

  • 可以用==!=来比较null值,不能用其他方法。null == null 判定是true。

整型包装类对象怎么比较?

  • 必须用equals()方法。而且包装类方法已经被重写过,比较的是值而不是内存地址。

BigDecimal有啥用?

  • BigDecimal主要防止浮点数运算中的精度丢失。

    image-20201125091941537

  • BigDecimal主要方法:

    • equals()。
    • compareTo():-1、0、1分别表示小于、等于、大于。
    • setScale():保留几位小数及保留规则。
  • 阿里巴巴开发手册要求,BigDecimal必须用String类型赋值,或用valueOf()方法赋值。绝不能用double赋值。

    • new BigDecimal("0.1");
    • BigDecimal.valueOf(0.1);

基本数据类型和包装数据类型啥时候用?

  • 基本数据类型:局部变量。
  • 包装数据类型:POJO类(简单实体类)属性、RPC方法(远程过程调用)的返回值和参数。
  • 包装数据类型的null和0是不同含义,而基本数据类型不能体现null的含义,所以要注意区别。

4.2 集合

Arrays.asList()方法咋用?

  • Arrays.asList()可以将list数组转换为ArrayList数组,但不能实现add()、remove()、clear()功能。

  • 传入对象必须是对象数组,也就是包装类数组。

咋将数组转换为ArrayList?

  • 最简便的方法:

    List list = new ArrayList<>(Arrays.asList("a", "b", "c"))
  • Java8 Stream方法:

    Integer [] myArray = { 1, 2, 3 };
    List myList = Arrays.stream(myArray).collect(Collectors.toList());
    //基本类型也可以实现转换(依赖boxed的装箱操作)
    int [] myArray2 = { 1, 2, 3 };
    List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList());
  • Guava方法:

    List il = ImmutableList.of("string", "elements");  // from varargs
    List il = ImmutableList.copyOf(aStringArray);      // from array
    List l1 = Lists.newArrayList(anotherListOrCollection);    // from collection
    List l2 = Lists.newArrayList(aStringArray);               // from array
    List l3 = Lists.newArrayList("or", "string", "elements"); // from varargs
  • Java9 List.of()方法:

    Integer[] array = {1, 2, 3};
    List list = List.of(array);
    System.out.println(list); /* [1, 2, 3] */
    /* 不支持基本数据类型 */

Collection.toArray()方法咋用?

  • 该方法是泛型方法,应该有参数。可以给数组的第一个值作为参数,这个参数的用处是说明返回值类型,如:

    String [] s= new String[]{
      "dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"
    };
    List list = Arrays.asList(s);
    Collections.reverse(list);
    s = list.toArray(new String[0]);//没有指定类型的话会报错,String[0]用来说明返回值类型

for-each为啥不能进行remove/all操作?

  • 只有迭代器能进行remove/all操作,其他遍历不能进行remove/all操作,否则会触发fail-fast机制,抛出ConcurrentModificationException错误。

  • Java 8 后,可以用Collection.removeIf()方法进行remove:

    List list = new ArrayList<>();
    for (int i = 1; i <= 10; ++i) {
      list.add(i);
    }
    list.removeIf(filter -> filter % 2 == 0); /* 删除list中的所有偶数 */
    System.out.println(list); /* [1, 3, 5, 7, 9] */
  • 迭代器remove操作,如:

    image-20201126061951711

    image-20201126062000297

5. 常用单词

Java 中一些常用单词。

  • JDK:Java Development Kit:Java 开发工具包。
  • JRE:Java Runtime Environment:Java 运行时环境。
  • JVM:Java Virtual Machine:Java 虚拟机。
  • bit:比特。
  • byte:字节。
  • compile:编译。
  • Java SE:Java Standard Edition:Java 标准版。
  • Java EE:Java Enterprise Edition:Java 企业版。
  • Java ME:Java Micro Edition:Java 小型版。
  • GC:Garbage Collection:垃圾收集机制。
  • arithmetic:算数,算法。
  • relational operator/database/expression:关系运算符,关系型数据库,关系表达式。
  • util:utility:实用的,通用的。
  • score:分数。
  • avg:average:平均值。
  • ArrayIndexOutOfBoundsException:数组下标越界异常。
  • NullPointerException:空指针异常。
  • actual parameter:实参。
  • formal parameter:形参。
  • command line parameter:命令行参数。
  • OOP:Object Oriented Programming:面向对象编程。
  • oriented:导向的。
  • programming:编程。
  • rectangle:矩形。
  • variable:变量。
  • statement:语句。
  • arguments:参数。
  • declare:声明。
  • this:当前对象。
  • constructor:构造函数,构造器。
  • encapsulation:封装。
  • pass by reference:按引用传递。
  • pass by value:按值传递。
  • override:覆盖。
  • inherit:继承。
  • instanceof:实例。
  • casting, overcasting, downcasting:转型,向上转型,向下转型。
  • ClassCastException:类型转换异常。
  • polymorphism:多样性。
  • dependency:依赖。
  • association:关联。
  • aggregation:聚合。
  • composite:组合。
  • generalization:泛化,继承。
  • interface:接口。
  • implements:实现。
  • singleton:单例。
  • proxy:代理人。
  • annotation:注释。
  • suppress:抑制。
  • SuppressWarnings:抑制警告。
  • anonymous:匿名的。
  • ordinal:顺序的。
  • retention:保留。
  • metadata:元数据。
  • RuntimeException:运行时异常。
  • NumberFormatException:数字格式化异常。
  • JavaBean:对象。
  • parse:解析。
  • trim:削减。
  • substring:子串。
  • split:分离。
  • uppercase, lowercase:大小写。
  • concat:合并数组或字符串。
  • sqrt:square root:开平方。
  • abs:取绝对值。
  • pow:乘幂。
  • ceil, floor, round:三种取整。
  • date:日期。
  • calendar:日历。
  • format:格式化。
  • wrapper:包装类。
  • boxing:装箱。
  • octal:八进制。
  • hex:十六进制。
  • decimal:小数的。
  • equalsIgnoreCase:忽视大小写比较是否相等。
  • current:当前的。
  • remainder:余数。
  • locale:区域。
  • leap year:闰年。
  • instant:立即的。
  • offset:偏移。
  • temporal:时间的。
  • concurrent:并发的。
  • parallel:并行的。
  • ConcurrentModificationException:并发修改异常。
  • property:属性。
  • generic:泛化。
  • wildcard:通配符。
  • canonical:规范化。
  • suffix:后缀,下标。
  • preffix:前缀。
  • buffer:缓冲。
  • serialize:串行化,序列化。
  • transient:暂时的,瞬态的。
  • charset:字符集。
  • UID:Unique IDentifier:唯一标识符。
  • RandomAccessFile:支持随机访问文件。
  • allocate:分配。
  • flip:翻转。
  • rewind:回滚。
  • interrupted:中断的。
  • resume:恢复。
  • IP:Internet Protocal:互联网协议。
  • TCP:Transmission Control Protocal:传输控制协议。
  • UDP:User Datagram Protocal:用户数据报协议。
  • datagram:数据报。
  • HTTP:Hyper Text Transport Protocal:超文本传输协议。
  • URL:Uniform Resource Locator:全球资源定位器。
  • invoke:调用。
  • new instance:新实例。
  • primitive type:base data type:primary data type:atomic data type:基本数据类型。
  • reference type:引用数据类型。
  • generic superclass / interface:泛化父类 / 接口。
  • getDeclaredMethod:返回泛化的 Method 对象。
  • supplier:供应商。
  • predicate:断言。
  • unary:一元的。

参考资料

  1. JavaGuide项目的Java基础
  2. 尚硅谷Java课程