Java 面试题_基础知识部分

  • 申明:本资源收集于互联网,仅供参考,文中如存在错误,欢迎交流指正。

Java 面试小结

Java基础知识部分

1、接口和抽象类的异同点

相同:
  都不能创建对象。
  都可以定义抽象方法,并且一定要在子类中重写。
  不同:
    接抽象类使用abstract,而接口的关键字是interface
    抽象类中的既可以有抽象方法也可以有普通方法,接口中只能是抽象方法。
    抽象类的方法权限修饰关键字可以是任意的,接口中的方法只能是public
    抽象类只能单继承,而接口可以多实现。

2、重载(overlord)和重写(override)

重载的规则:
  在同一个类中
  方法名相同
  和返回值无关
  参数列表不同(参数个数,参数类型)
重写的规则:
  子类和父类的关系,子类重写了父类的方法。
  方法名,参数列表必须和类方法一致
  返回值类型要么相同,要么子类方法返回值类型父类方法返回值类型子类
  访问修饰符要么和父类相同,要么大于父类方法。
  方法中抛出的异常,要么相同。要么子类方法抛出的异常比父类被重写方法抛出的异常更小或相同!

3、String、StringBuffer、StringBuilder的区别

  String:字符串常量不可变,使用字符串拼接时会开辟新空间。
  StringBuffer:字符串变量可变,线程安全,字符串拼接直接追加在字符串后面。
  StringBuilder:字符串变量可变,非线程安全,字符串拼接直接追加在字符串后面。
1、StringBuilder执行效率高于StringBuffer高于String。
2、String是一个常量,不可变的,对于每一次+=复制都会创建一个新的对象,StringBuilder和StringBuffer都是可变的,当进行字符串拼接是采用append方法,在原来的基础上进行追加,所以性能比string高,StringBuffer是线程安全的,而StringBuilder是非线程安全的,所以StringBuiler的效率高于StringBuffer。
3、对于大量数据的的字符串拼接时,采用StringBuilder和StringBuffer。

4、常见的异常类型

NullPointerException 空指针异常
ClassCastException 类型强制转换异常
IllegalArgumentException 传递非法参数异常
ArithmeticException 算数运算异常
IndexOutOfBoundsException 下标越界异常
NumberFormatException 数字格式异常
ClassNotFindException 加载请求异常

5、Throw和Throws的区别

位置:Throw在方法内部,而Throws在方法名后。
作用:Throw作为对象抛出异常,Throws申明异常,交给调用者处理。
个数:Throw一次抛出一个异常,Throws可以申明多个异常。

6、Final,Finally,finalize的作用

final:用于申明属性,方法和类。分别表示属性不可变,方法不可被重写,类不可被继承。
finally:是异常处理结构语句中的一部分,表示总是执行,不管是否发生异常都会执行,除非虚拟机退出运行。

System.exit(0);//虚拟机退出运行

finalize:是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法可以实现资源回收,释放资源,例如关闭文件等。JVM 不保证此方法总被调用。

7、hashMap和hashTable的区别

hashMap允许空(null)键值(只允许单个空键,但可以多个空值),非线程安全,效率高。在多个线程同时访问时,必须提供同步。
hashTable:不允许键为空,线程安全,但效率低。
HashMap 把 Hashtable的 contains 方法去掉了,改成containsvalue和containsKey。
Hashtable 和 HashMap 采用的 hash/rehash 算法大致一样,所以性能不会有很大的差异。

8、线程与进程的区别
  • 线程:是指程序在执行过程中,能够执行程序代码的一个基本执行单位,每个程序都至少有一个线程,也就是程序本身。
    Java中的线程有四种状态:运行、就绪、挂起、结束。
    进程:是程序的基本执行实体,是线线程的容器。
    进程具有的特征:
    动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
    并发性:任何进程都可以同其他进程一起并发执行;
    独立性:进程是系统进行资源分配和调度的一个独立单位;
    结构性:进程由程序、数据和进程控制块三部分组成。
    区别
    1、 隶属关系:线程是进程中的一部分,一个进程中可以包含若干个线程。进程可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体。
    2、 地址空间和其它资源:进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位。
    3、 进程间通信:线程间可以直接读写进程数据段(如全局变量)来进行通信。
    需要进程同步和互斥手段的辅助,以保证数据的一致性。
    4、 调度和切换:线程上下文切换比进程上下文切换要快得多。
9、实现多线程的两种方式

1、继承Thread类,重写run方法;

public class ThreadTest {
    public static void main(String[] args) {
        ThreadDemo t1 = new ThreadDemo();
        t1.start();
        ThreadDemo t2 = new ThreadDemo();
        t2.start();
    }
}
class ThreadDemo extends Thread{
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 20; i++) {
            System.out.println(currentThread().getName());
        }
    }
}

2、实现Runnable接口,重写run方法;

class RunnableDemo implements Runnable{
    @Override
    public void run() {
       
    }
10、同步的实现方法有两种:

Wait()使一个线程处于等待状态,并且释放所持有的对象的 lock。
notify():唤醒一个处于等待状态的线程,在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,不是按优先级。用 synchronized 关键字修饰同步方法反对使用 stop(),是因为它不安全。

11、List、Set、Collection、Collections
  • ListSet都是接口,他们都继承于Collection。List是一个有序且元素可重复的集合,而Set是无序、元素不可重复的集合。
    Collection是集合的顶层接口,Collections是封装了众多关于集合操作的静态方法的一个工具类,因为其构造器是私有化的,所以无法实例化。
12、List实现的接口有ArrayList、LinkedList、Vector
  • ArrayList:底层使用数组实现,长度默认是10。如果集合元素的个数超出当前数组大小,则创建新的扩容60%的数组,并将原来的元素拷贝过来。由于数组是按内存位置依次存放,因此查找快,但是增删元素涉及到后面的元素移动,因此增删元素要慢。
    LinkedList:底层使用链表实现。增删元素时,链表只需要增加或删除一个节点,这样的增删效率较高,但查询时需要一个个的遍历,所以查询效率较低。
    Vector: 和ArrayList原理相同。Vector是线程安全的,所以效率略低。ArrayList是线程不安全的,所以效率较高。
13、Set实现的接口主要有:HashSet、TreeSet、LinkedHashSet

HashSet:底层是以哈希表实现的,所有元素是按hashCode的值存放。HashSet是线程不安全,存取速度快。
TreeSet:底层使用红-黑树的数据结构实现。要求元素实现Compareable接口,默认对元素进行自然排序(String)。
LinkedHashSet:底层使用链表技术实现,但是结合了哈希值实现存储。LinkedHashSet的增删效率高,查询效率低。

14、sleep()和wait()的区别

sleep 是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用 sleep 不会释放对象锁。
wait 是 Object 类的方法,对此对象调用 wait 方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出 notify 方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态相同点在于都会造成线程阻塞.

15、error和exception有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。
exception 表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。

16、堆(heap)和栈(stack)有什么区别

Java的内存主要分为两类,一类是栈内存,一类是堆内存。
内存是指程序进入一个方法时,jvm会为这个方法分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法执行结束时,分配给这个方法的栈内存会自动释放,栈中的变量也随之释放。
是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用 new 创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用 final 修饰后,放在堆中,而不是栈中。

17、GC是什么,为什么要有GC?

GC 是垃圾收集的意思(GabageCollection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的 GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。

18、内存泄漏和内存溢出

内存泄露(memoryleak),是指应用程序在申请内存后,无法释放已经申请的内存空间.一次内存泄露危害可以忽略,但如果任其发展最终会导致内存溢出
(outofmemory).如读取文件后流要进行及时的关闭以及对数据库连接的释放。
内存溢出(outofmemory) 是指应用程序在申请内存时,没有足够的内存空间供其使用。如我们在项目中对于大批量数据的导入,采用分段批量提交的方式。

19、Java中如何实现序列化,有什么意义?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。
要实现序列化,需要让一个类实现 Serializable 接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过 writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过 readObject 方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆。

20、空字符串"" 和null的区别

空字符串是"",会创建一个对象,内容是"",有内存空间。
而 null,不会创建对象,没有内存空间
空字符串是 String 类的一个对象,而 null 是指一个引用变量没有引用对象,在值为 null 的引用变量上调用方法或变量,将会导致 NullPointerException。通过以下代码来验证变量 x 是否为 null,x==null,通过”".equals(x)来验证 x 是否为空字符串。

21、得到Class的三种方式是什么?

1、第一种:通过每个对象都具备的方法 getClass 来获取。
2、第二种:每一个数据类型(基本数据类型和引用数据类型)都有一个静态的属性 class。.class 用该属性就可以获取到字节码文件对象虽然不用对象调用,但还是要用具体的类调用静态属性。
3、第三种:使用的 Class 类中的方法,静态的 forName 方法。

22、逻辑运算符:&和&&的区别

&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为 true 时,整个运算结果才为 true,否则,只要有一方为 false,则结果为 false。
&&还具有短路的功能,即如果第一个表达式为 false,则不再计算第二个表达式。
&还可以用作位运算符,当&操作符两边的表达式不是 boolean 类型时,&表示按位与操作

23、ArrayList 和 LinkedList 有什么区别

1)因为 Array 是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的。Array 获取数据的时间复杂度是 O(1),但是要删除数据却是开销很大的,因为这需要重排数组中的所有数据。

        2)相对于 ArrayList,LinkedList 插入是更快的。因为 LinkedList 不像 ArrayList 一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是 ArrayList 最坏的一种情况,时间复杂度是 O(n),而 LinkedList 中插入或删除的时间复杂度仅为 O(1)。ArrayList 在插入数据时还需要更新索引(除了插入数组的尾部)。

        3)类似于插入数据,删除数据时,LinkedList 也优于 ArrayList。

        4)LinkedList 需要更多的内存,因为 ArrayList 的每个索引的位置是实际的数据,而 LinkedList 中的每个节点中存储的是实际的数据和前后节点的位置。

24、面向对象的特征有哪些方面?

1)抽象:
抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。
抽象包括两个方面,一是过程抽象,二是数据抽象。
2)继承:
继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。
对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
3)封装:
封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。
面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
4)多态:
多态是指允许不同类的对象对同一消息作出响应。
多态包括参数化多态性和包含多态性。
多态语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

25、静态类型有什么特点?

(1)静态的属性:随着类的加载而加载,该属性不在属于某个对象,属于整个类
(2)静态的方法:直接用类名调用,静态方法里不能访问非静态成员变量
(3)静态类:不能直接创建对象,不可被继承

26、说一下多态的表现形式?

(1)重载,重写,重载 Overload 表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同

       (2)重写 Override 表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是 private 类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法

27、线程通常有五种状态

1) 创建状态。在生成线程对象,并没有调用该对象的 start 方法,这是线程处于创建状态

       2) 就绪状态。当调用了线程对象的 start 方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。
在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。

       3)运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行 run 函数当中的代码。

       4) 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生 (比如说某项资源就绪)之后再继续运行。sleep,suspend,wait 等方法都可以导致线程阻塞。

       5) 死亡状态。如果一个线程的 run 方法执行结束或者调用 stop 方法后,该线程就会死亡。对于已经死亡的线程,无法再使用 start 方法令其进入就绪

28、Java中的I/O体系

按流向区分:
        输出流以OutputStream和Writer作为基类
        输入流以InputStream和Reader作为基类。
按照处理数据单元划分:
        字节流:
                字节输入流InputStream基类
                字节输入流OutputStream基类
        字符流:
                字符输入流Reader基类
                字符输出流Writer基类

在这里插入图片描述

29、Class.ForName的作用?为什么要用?

按参数中指定的字符串形式的类名去搜索并加载相应的类,如果该类字节码已经被加载过,则返回代表该字节码的 Class 实例对象,否则,按类加载器的委托机制去搜索和加载该类,如果所有的类加载器都无法加载到该类,则抛出 ClassNotFoundException。加载完这个 Class 字节码后,接着就可以使用 Class 字节码的 newInstance 方法去创建该类的实例对象了。
有时候,我们程序中所有使用的具体类名在设计时(即开发时)无法确定,只有程序运行时才能确定,这时候就需要使用 Class.forName 去动态加载该类,这个类名通常是在配置文件中配置的,例如,Spring 的 ioc 中每次依赖注入的具体类就是这样配置的,jdbc 的驱动类名通常也是通过配置文件来配置的,以便在产品交付使用后不用修改源程序就可以更换驱动类名。

30、异常的体系结构:

在这里插入图片描述

31、构造函数的特点和作用

方法名和类名相同
没有返回值,连 void 也没有
初始化对象

32、synchronized 关键字的用法?

synchronized 关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用 synchronized(对象){…}定义同步代码块,或者在声明方法时将 synchronized 作为方法的修饰符。
同步代码块同步方法

33、启动一个线程是调用 run()还是 start()方法?

启动一个线程是调用 start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行,这并不意味着线程就会立即运行。
run()方法是线程启动后要进行回调(callback)的方法。

34、Swtich 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

在 Java5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

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

数组没有 length()方法,有 length 的属性。String 有 length()方法。JavaScript 中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

36、构造器(constructor)是否可被重写(override)?

构造器不能被继承,因此不能被重写,但可以被重载。

37、阐述静态变量和实例变量的区别

静态变量是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。
注:在 Java 开发中,上下文类和工具类中通常会有大量的静态成员

38、JDKJREJVM 的区别

JDK【JavaDevelopmentToolKit】就是 java 开发工具箱,JDK 是整个 JAVA 的核心里边包含了 jre,它除了包含 jre 之外还包含了一些 javac 的工具类,把 java 源文件编译成 class 文件,java 文件是用来运行这个程序的,除此之外,里边还包含了 java 源生的 API,java.lang.integer 在 rt 的 jar 包里边【可以在项目中看到】,通过 rt 这个 jar 包来调用我们的这些 io 流写入写出等
JDK 有以下三种版本:

  • J2SE,standardedition,标准版,是我们通常用的一个版本
  • J2EE,enterpsiseedtion,企业版,使用这种 JDK 开发 J2EE 应用程序
  • J2ME,microedtion,主要用于移动设备、嵌入式设备上的 java 应用程序

JRE【JavaRuntimeEnviromental】是 java 运行时环境,那么所谓的 java 运行时环境,就是为了保证 java 程序能够运行时,所必备的一基础环境,也就是它只是保证 java 程序运行的,不能用来开发,而 jdk 才是用来开发的,所有的 Java 程序都要在 JRE 下才能运行。
包括 JVM 和 JAVA 核心类库和支持文件。与 JDK 相比,它不包含开发工具——编译器、调试器和其它工具。
JRE 里边包含 jvm
Jvm:【JavaVirtualMechinal】因为 jre 是 java 运行时环境,java 运行靠什么运行,而底层就是依赖于 jvm,即 java 虚拟机,java 虚拟机用来加载类文件,java 中之所以有跨平台的作用,就是因为我们的 jvm
关系:
J2se 是基于 JDK和 JRE,
JDK 是整个 JAVA 的核心里边包含了 JRE,
JRE 里边包含 jvm

39、XML 和 Json 的特点

Xml 特点:
1、 有且仅有一个根节点;
2、 是独立与软件和硬件的信息传输工具(传输量较大)
3、 所有的标签都需要自定义
4、 仅仅是纯文本文件
Json(JavaScriptObjectNotation)特点:
json 分为两种格式:json 对象(就是在{}中存储键值对,键和值之间用冒号分隔,键值对之间用逗号分隔),json 数组(就是[]中存储多个 json 对象,json 对象之间用逗号分隔)(两者间可以进行相互嵌套)数据传输的载体之一
区别:
xml 的传输数据量比 json 的要大,流行的是基于 json 的数据传输。
共同点:
Xml 和 json 都是传输数据的载体,并且具有跨平台跨语言的特性。

40、JDK 常用的包
  • java.lang:这个是系统的基础类,比如 String、Math、Integer、System 和 Thread,提
    供常用功能。在 java.lang 包中还有一个子包:java.lang.reflect 用于实现 java 类…
  • java.io:这里面是所有输入输出有关的类,比如文件操作等
  • java.net:这里面是与网络有关的类,比如 URL,URLConnection 等。
  • java.util:这个是系统辅助类,特别是集合类 Collection,List,Map 等。 ◆java.sql:这个是数据库操作的类,Connection,Statememt,ResultSet 等
41、什么是值传递和引用传递?

值传递:形参类型是基本数据类型,方法调用时,实际参数把它的值传递给对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形参值得改变不影响实际参数的值
引用传递:形参类型是引用数据类型参数,也称为传地址,方法调用时,实际参数是对象(或数组),这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留下来,所以方法执行中形式参数的改变将会影响实际参数。

42、空字符串(“”)和 null 的区别

空字符串是"",会创建一个对象,内容是"",有内存空间。
而 null,不会创建对象,没有内存空间
空字符串是 String 类的一个对象,而 null 是指一个引用变量没有引用对象,在值为 null 的引用变量上调用方法或变量,将会导致 NullPointerException。

public static void main(String[] args) {
    String str1="";
    String str2=null;
    System.out.println(str1.toString());
    System.out.println(str2.toString());
}

可以看到,当String=null的时候,报了Exception in thread “main” java.lang.NullPointerException异常。
在这里插入图片描述

43、列举 java 中 string 类常用方法

charAt(intindex)返回指定索引处的 char 值。
concat(Stringstr)将指定字符串连接到此字符串的结尾。
equals(ObjectanObject)比较字符串的内容是否相等。
length()返回此字符串的长度。
trim()返回字符串的副本,忽略前导空白和尾部空白。去掉字符串中的前后空格
substring(intbeginIndex)截取子串从beginindex开始。
substring(intbeginIndex,intendIndex)截取子串从哪到哪。
split(Stringregex)分割字符串切割字符串
valueOf(floatf)返回float参数的字符串表示形式。
Float可以是任何java提供类型。
toLowerCase转成小写的与toUpperCase转成大写
compareTo(StringanotherString)按字典顺序比较两个字符串。
contains(CharSequences)一个字符串中包不包含子串
indexOf(intch)返回索引值第一次出现的位置
replace(charoldChar,charnewChar)用newchar替换此字符串中出现的所有

44、什么是迭代器(Iterator)?

Iterator提供了统一遍历操作集合元素的统一接口,Collection接口实现Iterable接口,每个集合都通过实现Iterable接口中iterator()方法返回Iterator接口的实例,然后对集合的元素进行迭代操作.有一点需要注意的是:在迭代元素的时候不能通过集合的方法删除元素,否则会抛出ConcurrentModificationException异常.但是可以通过Iterator接口中的remove()方法进行删除.

45、char 型变量中能不能存贮一个中文汉字?为什么?

char 型变量是用来存储 Unicode 编码的字符的,unicode 编码字符集中包含了汉字,所以,char 型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在 unicode 编码字符集中,那么,这个 char 型变量中就不能存储这个特殊汉字。补充说明: unicode 编码占用两个字节,所以,char 类型的变量也是占用两个字节。

46、Java 中 compareTo 和 compare 的区别?

compareTo 是 Compareable 接口的一个方法,主要用于规定创建对象的大小关系,该对象要实现 compareable 接口,当 a.compareTo(b)>0 时,则 a>b,当 a.compareTo(b)<0 时,a<b.
compare 方法是 java.util 中的 Comparator 接口的一个方法,compare 方法内主要靠定义 compareTo 规定的对象大小关系来确定对象的大小。

47、Set 里的元素是不能重复的,那么用什么方法来区分重复与否呢?是用==还是 equals()?它们有何区别?

Set 里的元素是不能重复的,那么用 iterator()方法来区分重复与否。equals()是判读两个 Set 是否相等。
equals()和==方法决定引用值是否指向同一对像 equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值。

48、下面这条语句一共创建的多少个对象:StringS=“a”+ “b”+”c”+”d”;

代码被编译器编译优化后,相当于直接定义了一个“abcd”的字符串,所以该语句只创建了一个对象,如图;
在这里插入图片描述

49、什么情况下 finally 中的代码不会执行?

如果在 try 块或者 catch 块中调用了退出虚拟机的方法(即 System.exit();)那么 finally 中的代码不会执行,不然无论在 try 块、catch 块中执行任何代码,出现任何情况,异常处理的 finally 中的代码都要被执行的。

410、为什么 HashMap 链表长度超过 8 会转成树结构?

HashMap 在 JDK1.8 及以后的版本中引入了红黑树结构,若桶中链表元素个数大于等于 8 时,链表转换成树结构;若桶中链表元素个数小于等于 6 时,树结构还原成链表。因为红黑树的平均查找长度是 log(n),长度为 8 的时候,平均查找长度为 3,如果继续使用链表,平均查找长度为 8/2=4,这才有转换为树的必要。链表长度如果是小于等于 6,6/2=3,虽然速度也很快的,但是转化为树结构和生成树的时间并不会太短。

还有选择 6 和 8,中间有个差值 7 可以有效防止链表和树频繁转换。假设一下,如果设计成链表个数超过 8 则链表转换成树结构,链表个数小于 8 则树结构转换成链表,如果一个 HashMap 不停的插入、删除元素,链表个数在 8 左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值