面试题待整理
文章树列

集合相关

  1. java中常见的集合

一、Collection(单列集合)

 

1.List(有序(存储与取出的顺序一致),可重复)

 

1.1. ArrayList

 

底层数组实现,查询快,增删慢,线程不安全,效率高。

 

1.2.Vector

 

底层数据结构是数组实现,查询快,增删慢,线程安全,效率低。

 

1.3. LinkedList

 

底层数据结构是链表实现,查询慢,增删快,线程不安全,效率高。

 

2.Set(无序(存储与取出的顺序不一致),唯一)

 

HashSet

底层数据结构由哈希表(实际上是一个 HashMap 实例)实现,它不保证 set 的迭代顺序。允许使用null 元素,

依赖 hashCode()和equals()方法来区分存入的元素是否相同,来保证存储元素唯一性。

 

LinkedHashSe底层数据结构由哈希表和链表组成,哈希表保证元素的唯一性,链表保证元素有序(存储和取出一致)

 

TreeSet 底层数据结构是红黑树。元素的唯一性:依靠元素比较的返回值是否为0来决定

 

HashMap底层数据结构由哈希表实现,它不保证 set 的迭代顺序。允许使用 null 元素,

依赖hashCode()和equals()方法来区分存入的元素是否相同,来保证存储元素唯一性。

 

LInkedHashMap底层数据结构由哈希表和链表组成。哈希表保证元素的唯一性,链表保证元素有序(存储和取出一致)。

 

Hashtable:线程安全,效率低,不允许null键和null值. HashMap:线程不安全,效率高,允许null键和null值

  1. 如果存取相同的数据,ArrayList 和 LinkedList 谁占用空间更大?

ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 

对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 

对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

 

LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指 向前一

个元素,一个指向下一个元素。也可以参考ArrayList vs. LinkedList。

  1. TreeSet 对存入对数据有什么要求呢?
  2. HashSet 的底层实现呢
  3. HashSet 是不是线程安全的?为什么不是线程安全的?
  4. Java 中有哪些线程安全的 Map?
  5. Concurrenthashmap 是怎么做到线程安全的?
  6. 如何保证线程安全问题?
  7. synchronized、lock
  8. volatile 的原子性问题?为什么 i++ 这种不支持原子性?从计算机原理的设计来讲下不能保证原子性的原因
  9. happens before 原理

微服务

  1. 微服务划分的粒度
1
这里输入代码
  1. 微服务的高可用怎么保证的?
  2. 常用的负载均衡,该怎么用,你能说下吗?
  3. 网关能够为后端服务带来哪些好处?

其它

  1. 反射的机制
  2. hashcode 和 equals 方法常用地方
  3. 对象比较是否相同
  4. hashmap put 方法存放的时候怎么判断是否是重复的
  5. Object toString 方法常用的地方,为什么要重写该方法
  6. 不可重复读会出现在什么场景?
  7. sql having 的使用场景
  8. http 默认端口,https 默认端口
  9. 前端浏览器地址的一个 http 请求到后端整个流程是怎么样?能够说下吗?
  10. DNS 你知道是干嘛的吗?
  11. Linux环境下如何查找哪个线程使用CPU最长
1
2
3
4
5
6
7
8
1)获取项目的pid,jps或者ps -ef | grep java
2)top -H -p pid,顺序不能改变

这样就可以打印出当前的项目,每条线程占用CPU时间的百分比。注意这里打出的是LWP,也就是操作系统原生线程的线程号

使用"top -H -p pid"+"jps pid"可以很容易地找到某条占用CPU高的线程的线程堆栈,从而定位占用CPU高的原因,一般是因为不当的代码操作导致了死循环。

最后提一点,"top -H -p pid"打出来的LWP是十进制的,"jps pid"打出来的本地线程号是十六进制的,转换一下,就能定位到占用CPU高的线程的当前线程堆栈了。

什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”?

  • Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚 拟机执行的字节码文件。

  • Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重

  • 写或者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和 其他特性。

    static”关键字是什么意思?Java中是否可以覆盖(override)一个private或者是 static的方法?

  • “static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。

  • Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编 译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。

    是否可以在static环境中访问非static变量?

  • static变量在Java中是属于类的,它在所有的实例中的值是一样的。当类被Java虚拟机载

  • 入的时候,会对static变量进行初始化。如果你的代码尝试不用实例来访问非static的变量, 编译器会报错,因为这些变量还没有被创建出来,还没有跟任何实例关联上。

    Java中,什么是构造函数?什么是构造函数重载?什么是复制构造函数?

  • 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提 供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。

  • Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函 数必须有它自己唯一的参数列表。

  • Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的 情况下,Java不会创建默认的复制构造函数。

    Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于:

  • 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。

  • 类可以实现很多个接口,但是只能继承一个抽象类

  • 类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽 象的。

  • 抽象类可以在不提供接口方法实现的情况下实现接口。

  • Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。

  • Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。

  • 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main 方法的话是可以被调用的。

    什么是值传递和引用传递?

  • 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量.

  • 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 所以对引用对象进行操作会同时改变原对象.一般认为,java内的传递都是值传递.

    为什么集合类没有实现Cloneable和Serializable接口?

  • 克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该 由集合类的具体实现来决定如何被克隆或者是序列化。

    快速失败(fail-­fast)和安全失败(fail-­safe)的区别是什么?

  • Iterator的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util 包下面的所有的集合类都是快速失败的,而java.util.concurrent包下面的所有的类都是安全失败的。快速失败的迭代器会抛出ConcurrentModificationException异常,而安全失败的 迭代器永远不会抛出这样的异常

    hashCode()和equals()方法的重要性体现在什么地方

  • Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相

  • 同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。 所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。

HashMap和Hashtable有什么区别?

  • HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不 同点:

  • HashMap允许键和值是null,而Hashtable不允许键或者值是null。

  • Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable 适合于多线程环境。

  • HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面, Hashtable提供了对键的列举(Enumeration)。一般认为Hashtable是一个遗留的类。

    数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是 ArrayList?

  • Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。

  • Array大小是固定的,ArrayList的大小是动态变化的。

  • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

  • 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数 据类型的时候,这种方式相对比较慢。

ArrayList和LinkedList有什么区别?

  • ArrayList和LinkedList都实现了List接口,他们有以下的不同点:

  • ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的 前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。

  • 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合 任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。

  • LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指 向前一个元素,一个指向下一个元素。也可以参考ArrayList vs. LinkedList。

    Comparable和Comparator接口是干什么的?列出它们的区别。

  • Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对 象。

  • Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时 候,这个方法才返回true。

什么是Java优先级队列(Priority Queue)?

  • PriorityQueue是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue不 允许null值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后, PriorityQueue不是线程安全的,入队和出队的时间复杂度是O(log(n))。

finalize()方法什么时候被调用?析构函数(finalization)的目的是什么?

  • 垃圾回收器(garbage colector)决定回收某对象时,就会运行该对象的finalize()方法 但是在Java中很不幸,如果内存总是充足的,那么垃圾回收可能永远不会进行,也就是说filalize() 可能永远不被执行,显然指望它做收尾工作是靠不住的。

  • 那么finalize()究竟是做什么的呢? 它最主要的用途是回收特殊渠道申请的内存。Java程序有垃圾回收器,所以一般情况下内存问题不用程序员操心。

  • finaliztion是个可以被应用层重载的函数,当GC回收一个对象时,它会先调用对象的这个函数然后再处理其它事情。所以应用可以重载这个函数,去做一下想在GC前收尾的工作。但是问题来了,GC本来就是内存回收了,应用还需要在finalization做什么呢? 答案是大部分时候,什么都不用做(也就是不需要重载)。只有在某些很特殊的情况下,比如你调用了一些native的方法(一般是C写的),可以要在finaliztion里去调用C的释放函数。

    如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?

  • 不会,在下一个垃圾回收周期中,这个对象将是可被回收的。

    Java中的两种异常类型是什么?他们有什么区别?

  • Java中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的

  • 异常不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样 的异常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须要用throws语句在方法或者是构造函数上声明。这里有Java异常处理的一些小建议。

    Java中Exception和Error有什么区别?

  • Exception和Error都是Throwable的子类。Exception用于用户程序可以捕获的异常情况。 Error定义了不期望被用户程序捕获的异常。

    throw和throws有什么区别?

  • throw关键字用来在程序中明确的抛出异常,相反,throws语句用来表明方法不能处理的异常。每一个方法都必须要指定哪些异常不能处理,所以方法的调用者才能够确保处理可能发 生的异常,多个异常是用逗号分隔的。

    finally代码块和finalize()方法有什么区别?

  • 无论是否抛出异常,finally代码块都会执行,它主要是用来释放应用占用的资源。finalize()

  • 方法是Object类的一个protected方法,它是在对象被垃圾回收之前由Java虚拟机来调用 的。

    Mysql中有哪几种锁?

  • MyISAM支持表锁,InnoDB支持表锁和行锁,默认为行锁

  • 表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低

  • 行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高

    请对比 Exception 和 Error,另外,运行时异常与一般异常有什么区别?

  • Exception 和 Error 都是继承了 Throwable 类,在 Java 中只有 Throwable 类的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。

  • Exception 和 Error 体现了 Java 平台设计者对不同异常情况的分类。Exception 是程序正常运行中,可以预料的意外情况,可能并且应该被捕获,进行相应处理

  • Error 是指在正常情况下,不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于非正常的、不可恢复状态。既然是非正常情况,所以不便于也不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。

  • Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分

  • 不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。

    谈谈 Java 反射机制,动态代理是基于什么原理?

  • 反射机制是 Java 语言提供的一种基础功能,赋予程序在运行时自省(introspect,官方用语)的能力。通过反射我们可以直接操作类或者对象,比如获取某个对象的类定义,获取类声明的属性和方法,调用方法或者构造对象,甚至可以运行时修改类定义。

  • 动态代理是一种方便运行时动态构建代理、动态处理代理方法调用的机制,很多场景都是利用类似机制做到的,比如用来包装 RPC 调用、面向切面的编程(AOP)。

  • 实现动态代理的方式很多,比如 JDK 自身提供的动态代理,就是主要利用了上面提到的反射机制。还有其他的实现方式,比如利用传说中更高性能的字节码操作机制,类似 ASM、cglib(基于 ASM)、Javassist 等。

    Java 提供了哪些 IO 方式? NIO 如何实现多路复用?

  • 传统的 java.io 包,它基于流模型实现,比如 File 抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。

  • 很多时候,人们也把 java.net 下面提供的部分网络 API,比如 Socket、ServerSocket、HttpURLConnection 也归类到同步阻塞 IO 类库,因为网络通信同样是 IO 行为。

  • 在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层的高性能数据操作方式。

  • 在 Java 7 中,NIO 有了进一步的改进,也就是 NIO 2,引入了异步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。异步 IO 操作基于事件和回调机制,可以简单理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。

    为什么不用工厂模式而使用IOC

  • 因为IOC是通过反射机制来实现的。当我们的需求出现变动时,工厂模式会需要进行相应的变化。但是IOC的反射机制允许我们不重新编译代码,因为它的对象都是动态生成的。

本文原创,商业转载请联系作者获得授权,非商业转载请注明出处。

评论

发送评论 编辑评论


                        

后端技术分类热门文章

标签热门文章排行

☛免责声明 ☛本站使用教程
Theme Argon With Ry-Plus By 清欢
我的第24584位朋友,历经142924次回眸才与你相遇
内容失效/资源代找/交流学习
内容失效/资源代找/交流学习