Java知识点梳理——Java面经(剑指offer)

Java编程思想——万物皆对象


1、 JDK 与 JRE 的关系

  • JDK(Java Development Kit)是Java开发工具包。
  • JRE(Java Runtime Environment)是Java运行环境。

JDK = JRE + 开发工具集
JRE = JVM + Java SE标准类库


1、 “&” 和 “&&” 以及 “|” 和 “||” 的区别

   在逻辑运算符中, “&” 和 “&&” 以及 “|” 和 “||” 的区别:

区分 “&” 和 “&&” :

  • 相同点:都表示 “且” 关系。
  • 不同点: “&” 表示如果符号左边是false,还会继续执行符号右边的操作;而 “&&” 表示如果符号左边是false,则不再继续执行符号右边的操作;开发中,推荐使用 “&&”

区分 “|” 和 “||” :

  • 相同点:都表示 “或” 关系。
  • 不同点: “|” 表示如果符号左边是true,还会继续执行符号右边的操作;而 “||” 如果符号左边是true,则不再继续执行符号右边的操作;开发中,推荐使用 “||” 。

在逻辑运算符中, “&&” 和 “||” 存在 “短路” 现象。
在位运算符中,“&” 表示按位与,“|” 表示按位或。


1、Java中的基本类型有哪些?String 是最基本的数据类型吗?

   Java有两大数据类型,分别为 基本数据类型(内置数据类型)和 引用数据类型

  • 基本数据类型共八种。包括byte、short、int、long、float、double、char、boolean。数据直接存储在栈上。
  • 引用数据类型包括对象、数组、字符串(String)。所有引用类型的默认值都是null。数据存储在堆上,栈上只存储引用地址。(引用类型的变量非常类似于C/C++的指针)

String 是引用数据类型,并且使用 final 修饰,不能被继承。


1、数组有没有 length() 方法? String有没有 length() 方法?

   数组没有 length() 方法,但有 length 属性,用于记录数组长度。
   String有 length() 方法,用来计算字符串的长度。


1、访问控制修饰符有哪些?它们之间的区别?

   Java中修饰符主要用于修饰属性和方法。主要分为 访问控制修饰符非访问控制修饰符

  • 访问控制修饰符 : default(默认), public , protected, private
  • 非访问控制修饰符 : final, abstract, static, synchronized

不同访问控制修饰符的作用域对比:
Java知识点梳理——Java面经(剑指offer)_第1张图片

一个".java"源文件中可以有多个类,但只能有一个 public 的类,并且public的类名必须与文件名相一致。


1、面向对象的三个基本特征

  面向对象的三个基本特征是:封装继承多态

  • 封装:隐藏部分对象的属性和实现细节,对数据的访问只能通过外公开的接口。特性:保护类中数据和代码块。

  • 继承:子类继承父类的特征和行为(主要包括:属性和方法)。特性:使得子类可以拥有父类的属性和方法,即子类可以对父类进行扩展。(缺点:提高了类之间的耦合性,造成代码独立性越差。)

  • 多态:对于同一个行为,不同的子类对象具有不同的表现形式。特性:提高代码灵活性。多态存在的3个条件:1)继承;2)重写;3)父类引用指向子类对象。

Java 不支持多继承,但支持多重继承。(Java提供的接口可以弥补这个缺陷。)
而C++支持多继承。

耦合性(或称耦合度)是一种软件度量,是指一程序中,模块及模块之间信息或参数依赖的程度。
内聚性是一个和耦合性相对的概念,一般而言低耦合性代表高内聚性,反之亦然。
低耦合性是结构良好程序的特性,低耦合性程序的可读性及可维护性会比较好。


1、抽象类(abstract class)和接口(interface)的异同点

   抽象类和接口都不能被实例化。两者区别如下:

  • 实现方式:抽象类的子类使用 extends 来继承;接口使用 implements 来实现。
  • 继承方式:抽象类只能单继承,接口可以多实现。
  • 构造方法的存在:抽象类可以有构造方法,接口中不能有构造方法。
  • 成员变量的存在:抽象类中可以有成员变量,接口中没有成员变量,只能有常量(默认就是 public static final)。

1、关键字 super 和 this 的区别

  • 代表的对象不同。this 代表本身调用这个对象;super 代表父类的对象。
  • 构造方法。this() 表示本类的构造方法;super() 表示父类的构造方法。
  • 使用前提不同。super 只能在继承条件下,提供给子类使用。

1、阐述异常处理机制

   Java采用的异常处理机制,是将有可能产生异常的程序代码集中在一起,与正常的程序代码分开,使得程序易于维护。
   主要的处理方式有两种,分别为:

  • 捕获异常(try-catch-finally)
  • 声明抛出异常类型(throws)

1、 Error 和 Exception 的区别

   Error 和 Exception 都是 Throwable 的子类,都表示程序出现了不正常的情况。Error 和 Exception 的区别:

  • 异常 (Exception) :一般是 可控 ,可由程序员计代码进行捕捉或抛出。例如读取电脑中不存在的文件。
  • 错误 (Error) :一般是 不可控 ,系统性错误。例如栈溢出。

1、throw 和 throws 的区别

   throw 和 throws 都用于异常处理,具体区别:

  • throw : 作用在 方法内,由方法体内的语句处理;一定会抛出异常。
  • throws : 作用在 方法的声明上,由调用者来进行异常处理; 可能出现异常,不一定会发生异常。

1、“==” 和 equals()方法的区别

  • “==” :是运算符。用于比较基础数据类型变量的 和引用数据类型变量的 地址
  • equals()方法 :是Object 类中的方法。只用于比较对象,在没被重写之前,等同于 “==” 。但是在实际的开发中,equals()方法通常被重写,用于比较两个对象的值是否相同。

1、 Override(重写)与Overload(重载)的区别

   方法的重载和重写都是实现多态的方式。

  • 重写发生在父类与子类之间,要求方法名,参数列表,返回类型必须相同;访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private);不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。
  • 重载发生在一个类中,要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)。

1、 String和StringBuilder、StringBuffer的区别

   String和StringBuilder、StringBuffer都用于存放字符串,底层都使用 char[] 数组存储。StringBuilder、StringBuffer 都是可变的字符序列。三者区别如下:

  • String : 不可变 的字符序列。
  • StringBuffer : 可变 的字符序列;线程安全(方法使用synchronized修饰),效率低。
  • StringBuilder : 可变 的字符序列;线程不安全的,效率高。开发中推荐使用。

1、阐述final、finally、finalize的区别

   final、finally、finalize都是Java的关键字,然而它们之间并没有关系,只是长得相识而已。

  • final : 是Java中修饰符,表示 “最终的” 。一旦被final修饰,该变量值不能改变;该方法不能被子类重写;该类不能被子类继承。
  • finally : 用于异常处理机制,通常与 try-catch 一起使用,其作用是程序无论是否发生异常,finally 代码块中的代码总会被执行。
  • finalize : 是Object 类中的方法,用于保证对象在被垃圾收集前完成特定资源的回收。在 JDK-9 之后就被弃用。

关键字 (keyword) 被Java语言赋予了特殊含义,用做专门用途的字符串(或单词)。包括:定义数据类型、修饰符、用于流程控制等等关键字。

一个类不能同时被声明为 abstract 和 final 。


1、迭代器 ( Iterator 接口 ) 的作用

   迭代器的作用是便于处理集合中的元素。提供以下常用的方法:

  • next() 方法:获得集合中的下一个元素;
  • hasNext() 方法:检查集合中是否还存在下一个元素;
  • remove() 方法:将指定元素删除,并将值返回。

1、阐述Collection和Collections的区别

  • Collection是最基本的集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如 List、Set 等。
  • Collections 是一个包装类,提供了一系列对集合元素进行排序、查询和修改等操作的静态方法。

1、List、Set、Map三者的区别

   JDK提供的集合API位于java.util包内,Java 集合框架可分为 Collection 和 Map 两大体系:

  • Collection接口:用于存储一个一个的数据,也称单列数据集合
    • List子接口:用来存储有序、可以重复的数据(主要用来替换数组,"动态"数组)。其实现类:ArrayList、LinkedList、Vector
    • Set子接口:用来存储无序、不可重复的数据。其实现类:HashSet、LinkedHashSet、TreeSet
  • Map接口:用于存储具有映射关系“key-value对”的集合,即一对一对的数据,也称双列数据集合。其实现类: HashMap、LinkedHashMap、TreeMap、Hashtable、Properties

1、ArrayList 、 LinkedList 和 Vector 的区别

   ArrayList 、 LinkedList 和 Vector 都是 Collection 接口的List子接口的实现类。
   ArrayList 和 LinkedList 的对比:

  • 底层结构:ArrayList 底层基于动态数组实现,LinkedList 底层基于双向链表实现。
  • 随机访问效率:ArrayList 的随机访问效率高。
  • 增加和删除效率:LinkedList增加和删除效率高。

   Vector 和 ArrayList 几乎一致,唯一的区别是 Vector 在方法上使用了 synchronized 来保证线程安全。

数据的存储结构决定数据的增、删、改、查效率。


1、HashMap 和 Hashtable 的区别

  • HashMap : 线程不安全;效率高;允许键和值为null
  • Hashtable : 线程安全;效率低;不允许键和值为null

开发中推荐使用HashMap


1、 hashCode() 和 equals() 的关系

   Set接口是Collection的子接口,Set 集合不允许包含相同的元素。如果试图把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
   Set 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法得到的哈希值相等,并且两个对象的 equals() 方法返回值为true。
  两个对象的 hashCode() 相同,则 equals() 不一定为 true ;而当两个对象的 equals() 为 true 时,则 hashCode() 一定相同。

equals()方法 :是Object 类中的方法。在没被重写之前,用于比较两个对象的地址。但是在实际的开发中,equals()方法通常被重写,用于比较两个对象的内容是否相同。

了解hashCode之前,有必要先理解哈希存储。哈希存储(也称:散列存储)将数据元素存放在一块连续的存储区域中。数据元素的存放位置是通过一个哈希函数计算而得的。哈希函数将数据元素作为自变量,计算得到的函数值是数据元素的存储地址。

重写equals方法的时候一般都需要同时复写hashCode方法。


1、Thread 类中 start() 方法和调用 run() 方法的区别

   start() 方法来启动线程,真正实现了多线程运行。 run () 方法供 start() 方法调用,存放线程所要执行的内容。
   在主线程通过执行 start() 方法启动一个线程,而 start() 方法启动线程将自动调用 run() 方法,执行 run() 方法里线程的内容,当 run() 方法执行完毕,此线程也就终止。


1、线程中 sleep() 方法和 yield() 方法的区别

   线程中 sleep() 方法和 yield() 方法都用于释放CPU执行权。
   Sleep() 方法可以让当前正在执行的线程在指定的时间内暂停执行,进入超时等待(TIMED_WAITING)状态。该方法既可以让其他同优先级或者高优先级的线程得到执行的机会,也可以让低优先级的线程得到执行机会。
   Yield() 方法可以让出CPU执行权,进入就绪(READY)状态。然而 yield() 方法只能让同优先级或者更高优先级的线程有执行的机会。


1、sleep()方法和wait()方法的区别

来源:sleep() 方法来自 Thread 类,wait() 方法来自 Object 类 。
释放同步锁: sleep() 不会让线程释放同步锁的。而 wait() 会释放同步锁,让其他线程进入 synchronized 代码块执行。
恢复:两者会暂停当前线程,sleep() 时间到会自动恢复。而一旦某个对象调用了 wait() 方法,必须要采用 notify() 或 notifyAll() 方法唤醒。
使用范围:sleep() 可以在任何地方使用。wait() 只能在同步控制方法或者同步控制块里面使用。


1、 synchronized 和 Lock 的区别

  • Lock 是一个接口;synchronized 是 Java 中的关键字。
  • Lock 在发生异常时,如果没有主动通过 unLock() 去释放锁,很可能会造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁;synchronized 不需要手动获取锁和释放锁,在发生异常时,会自动释放锁,因此不会导致死锁现象发生。
  • Lock 的使用更加灵活,可以响应中断;而 synchronized 却不行,使用 synchronized
    时,等待的线程会一直等待下去,直到获取到锁。

1、死锁的检测和预防

   产生死锁的四个必要条件:

  • 互斥条件
  • 请求和保持条件
  • 不可剥夺条件
  • 循环等待条件(也称:环路等待条件)

   预防死锁的方式就是打破四个必要条件中的任意一个即可。


1、Java 中 IO 流的划分

  • 按数据的流向不同分为:输入流输出流
  • 按操作数据单位的不同分为:字节流(1B)和 字符流(2B)。

IO流分类


1、什么是反射?

  所谓反射,是Java提供的一套 API ,使用这套 API 可以在运行时动态的获取指定对象所属的类,创建运行时类的对象,调用指定的结构(属性、方法等)。


1、阐述垃圾收集机制

   Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题: 给对象分配内存回收分配给对象的内存。垃圾回收机制的引入可以有效的防止内存泄露、保证内存的有效使用,使得开发者在编写程序的时候不再需要考虑内存管理,提高开发效率。


1、JDK-8之后的新特性

  • Lambda 表达式 : Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
  • Stream API :新添加的 Stream API 把真正的函数式编程风格引入到Java中。
  • Date Time API :加强对日期与时间的处理。
  • Optional 类 : Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

未完待续…
欢迎关注+点赞+收藏~~~

你可能感兴趣的:(java,jvm,开发语言)