Java基础

1 面向对象

  • 面向过程:更注重事情的每一个步骤及顺序
  • 面向对象:更注重事情的参与者有哪些,及每个参与者需要做什么
  • 面向过程比较直接高效,面向对象易于复用、扩展和维护

提到面向对象,不得不提封装、继承、多态


2 JDK、JRE、JVM的联系和区别

请看这篇文章:JDK、JRE、JVM的联系和区别


3 == 和 equals

  • == :== 对比的是栈中的值(基本数据类型是变量值,引用数据类型是堆中的地址)
  • equals: Object 中默认也是采用 == 比较,通常会重写
// Object
public boolean equals(Object obj) {
    return (this == obj);
}

4 final

  • 修饰类:表示类不能被继承
  • 修饰方法:表示方法不能被子类重写,但是可以重载
  • 修饰变量:表示变量一旦被赋值就不能再更改它的值
  1. 修饰成员变量
  • 类变量:只能在静态初始化块中指定初始值或者声明时给该变量时赋初始值
  • 成员变量:可以在非静态初始化块声明时或者构造函数中给变量赋初始值
  1. 修饰局部变量
    可以在声明的时候就赋值,后面不能再修改该初始值;也可以声明的时候先不赋值,但是在第一次使用之前必须要赋初始值,且赋完之后不可修改。

  2. 修饰基本数据类型和引用数据类型

  • 基本数据类型:赋值后,该值不能再修改;
  • 引用数据类型:赋初值之后不能再指向另外一个对象,但是**引用对象的值(属性)**是可以改变的。

5 String StringBuilder StringBuffer

  • String 是 final 修饰的,不可变,每次操作都会产生新的 String 对象
  • StringBuilder 和 StringBuffer 都是在原对象上操作
  • StringBuilder 是线程不安全的,StringBuffer 是线程安全的

6 重载和重写的区别

  • 重载:发生在一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法的返回值和修饰符可以不同,编译时检查。
  • 重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类、抛出异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法的访问修饰符为 private ,则子类不能重写该方法。

7 接口和抽象类的区别

  • 抽象类中可以存在普通成员函数,接口里没有普通成员函数,但是有 public asbtract 方法、静态方法(static)和默认方法(default)
  • 抽象类中的成员遍历可以是各个类型的,而接口中的成员变量只能是 public static final 类型的
  • 一个类只能继承自一个(抽象)类,但是可以实现多个接口
  • 抽象类是模板,is a 的关系,包含并实现了子类的通用特性, 比如 BMW is a Car
  • 接口是规范,是对行为(方法)的抽象
  • 使用场景:当关注一个事物本质的时候,用抽象类;当关注一个操作的时候,用接口。

8 List 和 Set 的区别

  • List:有序,按对象存入的顺序保存对象,可重复,允许有多个 null 对象,可以使用 iterator 对象遍历,也可以下标获取 get(int index) 。
  • Set:无序,不可重复,只允许有一个 null 值,可以使用 iterator 遍历,由于是无序的,所以无法通过索引获取元素。

9 hashCode 与 equals

10 ArrayList 和 LinkedList

  • ArrayList:基于动态数据,连续内存存储,适合下标访问(随机访问),扩容机制:因数组长度固定,超出长度再插入数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及到元素的移动(往后复制一份,插入新元素),使用尾插法并指定初始容量可以极大地提升性能,甚至能超过 LInkeList(需要创建大量的 node 对象)
  • LinkedList:基于链表,可以存储在分散的内存中,适合做数据插入及删除操作,不适合查询:需要逐一遍历。另外 不建议直接使用 for 循环对 LinkedList 进行遍历,而是要使用 iterator 进行遍历,这是因为 for 循环每次通过 get(i) 获取值时都会对 LinkedList 进行重新遍历,消耗性能。也不建议使用 indexOf 返回 LinkedList 中元素的索引,并利用其进行遍历,使用 indexOf 对 LinkedList 进行遍历,当结果为空时会遍历整个列表。

11 HashMap 和 HashTable的区别?底层实现

  1. 区别:
  • HashMap 方法没有 synchronized 修饰,线程不安全,而 HashTable 线程安全;
  • HashMap 允许 key 和 value 为 null,而 HashTable 不允许
  1. 底层实现: 数组 + 链表
    jdk8 开始,如果链表的高度到8、数组长度超过64,链表转变为红黑树,元素以内部类 Node 节点存在
  • 计算 key 的 hash 值, 二次 hash 然后对数组长度取模,对应到数组下标;
  • 如果没有产生 hash 冲突(下标位置没有元素),则直接创建 Node 存入数组;
  • 如果产生 hash 冲突,先进行 equal 比较,相同则取代该元素,不同,则判断链表高度插入链表,链表高度达到8,并且数组长度到64则转变为红黑树,长度低于6则将红黑树转回链表
  • key 为 null,存在下标0的位置

12 ConcurrentHashMap原理, jdk7 和 jdk8版本的区别

如何实现一个IOC容器

  1. 配置文件配置包扫描路径
  2. 递归包扫描获取 .class 文件
  3. 反射、确定需要交给IOC管理的类
  4. 对需要注入的类进行依赖注入
  • 配置文件中指定需要扫描的包路径
  • 定义一些注解,分别表示访问控制层、业务服务层、数据持久层、依赖注入注解、获取配置文件注解
  • 从配置文件中获取需要扫描的包路径,获取到当前路径下的文件信息及文件夹信息,我们将当前路径下所有以 .class 结尾的文件添加到一个 Set 集合中进行存储
  • 遍历这个 Set 集合,获取在类上有指定注解的类,并将其交给IOC容器,定义一个安全的 Map 来存储这些对象
  • 遍历这个IOC容器,获取到每一个类的实例,判断里面是否有依赖其他类的实例,然后进行递归注入

13 什么是字节码?才用字节码的好处是什么?

  • 虚拟机能够处理的代码叫字节码(扩展名为 .class 的文件)
    JVM通过解释器将字节码文件翻译为特定机器能够识别的机器码,然后在特定机器上运行。
    在这里插入图片描述
  • 采用字节码的好处:一次编译,到处运行。不同机器上装着不同的JVM,但是这些JVM都能识别字节码文件(.class文件),所以只需将源代码一次编译成字节码后,可以拿到别的安装了JVM的操作系统上运行,只不过运行的时候,不同系统上的JVM会把字节码翻译成本系统能够读懂运行的机器码。

14 Java类加载器

JDK 自带有三个类加载器:Bootstrap ClassLoader,ExtClassLoader,AppClassLoader

  • Bootstrap ClassLoader:是 ExtClassLoader 的父类加载器,默认负责加载 %JAVA_HOME% 下的 jar 包和 class 文件。
  • ExtClassLoader: 是 AppClassLoader 的父类加载器,负责加载 %JAVA_HOME%/lib/ext 文件夹下的jar 包和 class 文件。
  • AppClassLoader:是自定义类加载器的父类,负责加载 classpath 下的类文件。系统类加载器,线程上下文加载器

15 双亲委派机制

在这里插入图片描述

  • 向上委派:查找缓存
  • 向下查找:查找路径

双亲委派的好处:

  • 安全性,避免用户自己编写的累动态替换 Java 的一些核心累,比如 String
  • 避免类的重复加载,因为 JVM 中区分不同类,不仅仅是根据类名,相同的 class 文件被不同的 ClassLoader 加载就是不同的两个类

GC 如何判断对象可以被回收

  • 引用计数法:每个对象都一个引用计数属性,新增一个引用时该计数加1,引用释放时计数减1,计数为0时可以回收。
  • 可达性分析法:从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就怕判断是可回收对象。
  1. 引用计算法,可能会出现 A 引用了 B,B 又引用了 A,如果某一时刻即使他们都不再使用了,但是因为相互引用,计算器一直为1,导致他们永远无法被回收。
  2. 可达性分析并不是第一次发现没有鱼与 GC Roots 相连接就清除的,而是先加入到虚拟机自动建立的 Finalizer 队列中,
    在这里插入图片描述

GC Roots 对象有:

  • 虚拟机栈(栈桢中的本地变量表)中引用的对象
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中 JNI(即一般所说的 Native 方法)引用的对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值