Java开发面试题整理2019春招

<div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
<div id="content_views" class="htmledit_views">

一、Java基础部分

1. HashMap和Hashtable各有什么特点,它们有什么区别?(必背题,超级重要)

  • HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。
  • HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
  • HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
  • 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
  • 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
  • HashMap不能保证随着时间的推移Map中的元素次序是不变的。

2. HashMap的工作原理?

3. ArrayList和LinkList各自的特点和区别?

1、ArrayList和LinkedList可想从名字分析,它们一个是Array(动态数组)的数据结构,一个是Link(链表)的数据结构,此外,它们两个都是对List接口的实现。前者是数组队列,相当于动态数组;后者为双向链表结构,也可当作堆栈、队列、双端队列

2、当随机访问List时(get和set操作),ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。

3、当对数据进行增加和删除的操作时(add和remove操作),LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。

4、从利用效率来看,ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。

5、ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。

4. RESTFul风格接口的特点?

5. 面向对象的七种设计原则

面向对象七大设计原则:

1、 开闭原则(OCP:Open Closed Principle)

核心:对扩展开放,对修改关闭。即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。

  • 根据开闭原则,在设计一个软件系统模块(类,方法)的时候,应该可以在不修改原有的模块(修改关闭)的基础上,能扩展其功能(扩展开放)。

2、 里氏替换原则(LSP:Liskov Substitution Principle)

核心:在任何父类出现的地方都可以用他的子类来替代(子类应当可以替换父类并出现在父类能够出现的任何地方)

  • 1.子类必须完全实现父类的方法。在类中调用其他类是务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。
  • 2.子类可以有自己的个性。子类当然可以有自己的行为和外观了,也就是方法和属性
  • 3.覆盖或实现父类的方法时输入参数可以被放大。即子类可以重载父类的方法,但输入参数应比父类方法中的大,这样在子类代替父类的时候,调用的仍然是父类的方法。即以子类中方法的前置条件必须与超类中被覆盖的方法的前置条件相同或者更宽松。
  • 4.覆盖或实现父类的方法时输出结果可以被缩小。

3、 单一职责原则(SRP:Single responsibility principle)

核心:和增强内聚性(高内聚,低耦合)

  • 类被修改的几率很大,因此应该专注于单一的功能。如果你把多个功能放在同一个类中,功能之间就形成了关联,改变其中一个功能,有可能中止另一个功能,这时就需要新一轮的测试来避免可能出现的问题。

4、 接口隔离原则(ISP:Interface Segregation Principle)

核心思想:不应该强迫客户程序依赖他们不需要使用的方法。接口分离原则的意思就是:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口当中.

  • 分离接口的两种实现方法:
  • 1.使用委托分离接口。(Separation through Delegation)
  • 2.使用多重继承分离接口。(Separation through Multiple Inheritance)

5、 依赖倒置原则(DIP:Dependence Inversion Principle)

核心:要依赖于抽象,不要依赖于具体的实现

  • 1.高层模块不应该依赖低层模块,两者都应该依赖其抽象(抽象类或接口)
  • 2.抽象不应该依赖细节(具体实现)
  • 3.细节(具体实现)应该依赖抽象。
    三种实现方式:
  • 1.通过构造函数传递依赖对象
  • 2.通过setter方法传递依赖对象
  • 3.接口声明实现依赖对象

6、 迪米特原则(最少知识原则)(LOD:Law of Demeter)

核心思想:一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。(类间解耦,低耦合)意思就是降低各个对象之间的耦合,提高系统的可维护性;在模块之间只通过接口来通信,而不理会模块的内部工作原理,可以使各个模块的耦合降到最低,促进软件的复用
注:

  • 1.在类的划分上,应该创建有弱耦合的类;
  • 2.在类的结构设计上,每一个类都应当尽量降低成员的访问权限;
  • 3.在类的设计上,只要有可能,一个类应当设计成不变;
  • 4.在对其他类的引用上,一个对象对其它对象的引用应当降到最低;
  • 5.尽量降低类的访问权限;
  • 6.谨慎使用序列化功能;
  • 7.不要暴露类成员,而应该提供相应的访问器(属性)

7、 组合/聚合复用原则(CRP:Composite Reuse Principle)

核心思想:尽量使用对象组合,而不是继承来达到复用的目的。该原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分:新的对象通过向这些对象的委派达到复用已有功能的目的。

复用的种类:

  • 1.继承
  • 2.合成聚合

注:在复用时应优先考虑使用合成聚合而不是继承

6. 谈谈堆和栈的区别!

a.堆栈空间分配

  • 栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表

b.堆栈缓存方式

  • 栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
  • 堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

c.堆栈数据结构区别

  • 堆(数据结构):堆可以被看成是一棵树,如:堆排序。
  • 栈(数据结构):一种先进后出的数据结构。

7. 谈谈你所了解的设计模式,并简单描述其特点和用法,或简单写一个某某设计模式!

1. 单例设计模式
2. 工厂设计模式
3. 代理模式
4. 观察者设计模式
5. 适配器模式
6. 策略模式
7. 门面模式
8. 桥接模式

来一个参考链接

注:设计模式有很多,这里列举几种常用的!读者需要自行将这几种设计模式理解清楚!前五种是常用也是常考的!

8. 熟悉HTTP基本的状态码!

一些常见的状态码为:

9. List、Set和Map的特点和区别(重点)

List

  • 1.可以允许重复的对象。
  • 2.可以插入多个null元素。
  • 3.是一个有序容器,保持了每个元素的插入顺序,输出的顺序就是插入的顺序。
  • 4.常用的实现类有 ArrayList、LinkedList 和 Vector。ArrayList 最为流行,它提供了使用索引的随意访问,而 LinkedList 则对于经常需要从 List 中添加或删除元素的场合更为合适。

Set

  • 1.不允许重复对象
  • 2.无序容器,你无法保证每个元素的存储顺序,TreeSet通过 Comparator 或者 Comparable 维护了一个排序顺序。
  • 3.只允许一个 null 元素
  • 4.Set 接口最流行的几个实现类是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基于 HashMap 实现的 HashSet;TreeSet 还实现了 SortedSet 接口,因此 TreeSet 是一个根据其 compare() 和 compareTo() 的定义进行排序的有序容器。

Map

  • 1.不是collection的子接口或者实现类。Map是一个接口。
  • 2.Map 的 每个 Entry 都持有两个对象,也就是一个键一个值,Map 可能会持有相同的值对象但键对象必须是唯一的。
  • 3.TreeMap 也通过 Comparator 或者 Comparable 维护了一个排序顺序。
  • 4.Map 里你可以拥有随意个 null 值但最多只能有一个 null 键。
  • 5.Map 接口最流行的几个实现类是 HashMap、LinkedHashMap、Hashtable 和 TreeMap。(HashMap、TreeMap最常用)

10.监听器、过滤器、拦截器、servlet的区别

11. 当在浏览器输入一个网址,所要经过的全部在过程,请详细描述!

浏览器访问某地址的详细过程:

  • 在服务器上输入一个地址:例如www.baidu.com后,回车:浏览器会根据输入的URL到DNS服务器查询对应的IP地址和域名;返回到客户端,客户端再根据所查到的的域名和IP,请求建立TCP连接,连接到对应的百度服务器,向服务器发送HTTP Request(请求),服务端接收到请求包并进行处理,并调用自身服务,返回HTTP Response(响应)。客户端接到响应的时候开始渲染这个Response包里的主体(body),等接收完所有内容后自动断开该TCP连接。
  • 详细过程图:

在这里插入图片描述

12. 简单描述Spring的特点:

  • spirng就是一个容器 ,它通过控制反转IOC和依赖注入(DI)实现高内聚、低耦合的应用。除此之外她还能整合很多第三方框架,它提供了面向切面编程AOP的能力,使其对数据库事务管理极为方便。
  • 简介:Spring就是一个轻量级的开源的Java SE 和Java EE 的开发应用框架。目的在于简化企业级应用的开发。

二、数据库基础部分

1. 详细描述几种你所熟悉的优化数据库的方式。

1、选取最适用的字段属性
2、使用连接(JOIN)来代替子查询(Sub-Queries)
3、使用联合(UNION)来代替手动创建的临时表
4、事务
5、锁定表
6、使用外键
7、使用索引
8、优化的查询语句

参考链接:

2. 数据库的视图和索引都有什么特点,有什么区别?

视图:

  • 概念:视图是从一个或多个表中导出来的表,是一种不是一种真正存在的概念。
  • 视图操作sql:
create view viewName(参数列表/可以不写这样就是默认和下面的select一样) as select * create table viewdemo(id primary key,name (10),score as select* drop view drop view view2;

 

索引 :

  • 概念:可以理解为是一本书的目录,它记录了数据在数据库中存放的位置,就像一本书的目录,记录了,某一页在这本书的那个位置。相同地,索引是一个单独的、存储在磁盘上的数据库结构,它们包含着对数据库表里所有记录的引用指针。
  • 视图操作sql:
ALTER TABLE table_name ADD [UNIQUE|FULLTEXT] [INDEX| [inex_name] (col_name [length ],...) [ASC|DESC]

 

ALTER TABLE book ADD INDEX indexName( bookname(30 ALTER TABLE book ADD INDEX BkAndInfoIdx( authors(20),info(50 前提是这个表的存储引擎为 MyISAM)

 

使用 create index 创建索引:

语法:

CREATE [UNIQUE|FULLTEXT] [INDEX| ON table_name ( col_name[ length ],... ) [ASC | 4 DROP INDEX index_name ON table_name ;

后续还会有补充,姑且先写到这吧!

我有一个微信公众号,经常会分享一些Java技术相关的干货;

如果你喜欢我的分享,可以用微信搜索“Java团长”或者“javatuanzhang”关注。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

Java开发面试题整理(2019春招)

相关推荐


在 Java 语言中,提高程序的执行效率有两种实现方法,一个是使用线程、另一个是使用线程池。而在生产环境下,我们通常会采用后者。为什么会这样呢?今天我们就来聊聊线程池的优点,以及池化技术及其应用。 1.池化技术 池化技术指的是提前准备一些资源,在需要时可以重复使用这些预先准备的资源。 池化技术的优点
在 Java 中停止线程的实现方法有以下 3 种: 自定义中断标识符,停止线程。 使用线程中断方法 interrupt 停止线程。 使用 stop 停止线程。 其中 stop 方法为 @Deprecated 修饰的过期方法,也就是不推荐使用的过期方法,因为 stop 方法会直接停止线程,这样就没有给
在多线程编程中,wait 方法是让当前线程进入休眠状态,直到另一个线程调用了 notify 或 notifyAll 方法之后,才能继续恢复执行。而在 Java 中,wait 和 notify/notifyAll 有着一套自己的使用格式要求,也就是在使用 wait 和 notify(notifyAll
在 Java 语言中,并发编程都是通过创建线程池来实现的,而线程池的创建方式也有很多种,每种线程池的创建方式都对应了不同的使用场景,总体来说线程池的创建可以分为以下两类: 通过 ThreadPoolExecutor 手动创建线程池。 通过 Executors 执行器自动创建线程池。 而以上两类创建线
sleep 方法和 wait 方法都是用来将线程进入休眠状态的,并且 sleep 和 wait 方法都可以响应 interrupt 中断,也就是线程在休眠的过程中,如果收到中断信号,都可以进行响应,并抛出 InterruptedException 异常。那 sleep 和 wait 的区别都有哪些呢
在 Java 中,线程的创建方法有 7 种,分为以下 3 大类: 继承 Thread 类的方式,它有 2 种实现方法。 实现 Runnable 接口的方式,它有 3 种实现方法。 实现 Callable 接口的方式,它有 2 种实现方法。 接下来我们一个一个来看。 1.继承Thread类 继承 Th
所谓的线程池的 7 大参数是指,在使用 ThreadPoolExecutor 创建线程池时所设置的 7 个参数,如以下源码所示: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
在 Java 语言中,线程分为两类:用户线程和守护线程,默认情况下我们创建的线程或线程池都是用户线程,所以用户线程也被称之为普通线程。 想要查看线程到底是用户线程还是守护线程,可以通过 Thread.isDaemon() 方法来判断,如果返回的结果是 true 则为守护线程,反之则为用户线程。 我们
聊到线程池就一定会聊到线程池的执行流程,也就是当有一个任务进入线程池之后,线程池是如何执行的?我们今天就来聊聊这个话题。线程池是如何执行的?线程池的拒绝策略有哪些? 线程池执行流程 想要真正的了解线程池的执行流程,就得先从线程池的执行方法 execute() 说起,execute() 实现源码如下:
单例模式是面试中的常客了,它的常见写法有 4 种:饿汉模式、懒汉模式、静态内部类和枚举,接下来我们一一来看。 1.饿汉模式 饿汉模式也叫预加载模式,它是在类加载时直接创建并初始化单例对象,所以它并不存在线程安全的问题。它是依靠 ClassLoader 类机制,在程序启动时只加载一次,因此不存在线程安
线程安全是指某个方法或某段代码,在多线程中能够正确的执行,不会出现数据不一致或数据污染的情况,我们把这样的程序称之为线程安全的,反之则为非线程安全的。在 Java 中,解决线程安全问题有以下 3 种手段: 使用线程安全类,比如 AtomicInteger。 加锁排队执行 使用 synchronize
在 Java 语言中,保证线程安全性的主要手段是加锁,而 Java 中的锁主要有两种:synchronized 和 Lock,我们今天重点来看一下 synchronized 的几种用法。 用法简介 使用 synchronized 无需手动执行加锁和释放锁的操作,我们只需要声明 synchronize
在 Java 语言中,有两个线程池可以执行定时任务:ScheduledThreadPool 和 SingleThreadScheduledExecutor,其中 SingleThreadScheduledExecutor 可以看做是 ScheduledThreadPool 的单线程版本,它的用法和
从公平的角度来说,Java 中的锁总共可分为两类:公平锁和非公平锁。但公平锁和非公平锁有哪些区别?孰优孰劣呢?在 Java 中的应用场景又有哪些呢?接下来我们一起来看。 正文 公平锁:每个线程获取锁的顺序是按照线程访问锁的先后顺序获取的,最前面的线程总是最先获取到锁。 非公平锁:每个线程获取锁的顺序
单例模式的实现方法有很多种,如饿汉模式、懒汉模式、静态内部类和枚举等,当面试官问到“为什么单例模式一定要加 volatile?”时,那么他指的是为什么懒汉模式中的私有变量要加 volatile? 懒汉模式指的是对象的创建是懒加载的方式,并不是在程序启动时就创建对象,而是第一次被真正使用时才创建对象。
读写锁(Readers-Writer Lock)顾名思义是一把锁分为两部分:读锁和写锁,其中读锁允许多个线程同时获得,因为读操作本身是线程安全的,而写锁则是互斥锁,不允许多个线程同时获得写锁,并且写操作和读操作也是互斥的。总结来说,读写锁的特点是:读读不互斥、读写互斥、写写互斥。 1.读写锁使用 在
很多场景下,我们需要等待线程池的所有任务都执行完,然后再进行下一步操作。对于线程 Thread 来说,很好实现,加一个 join 方法就解决了,然而对于线程池的判断就比较麻烦了。 我们本文提供 4 种判断线程池任务是否执行完的方法: 使用 isTerminated 方法判断。 使用 getCompl
在 Java 中,线程池的状态和线程的状态是完全不同的,线程有 6 种状态:NEW:初始化状态、RUNNABLE:可运行/运行状态、BLOCKED:阻塞状态、WAITING:无时限等待状态、TIMED_WAITING:有时限等待状态和 TERMINATED:终止状态。而线程池的状态有以下 5 种:
volatile 是 Java 并发编程的重要组成部分,也是常见的面试题之一,它的主要作用有两个:保证内存的可见性和禁止指令重排序。下面我们具体来看这两个功能。 内存可见性 说到内存可见性问题就不得不提 Java 内存模型,Java 内存模型(Java Memory Model)简称为 JMM,主要
1.第一范式 第一范式规定表中的每个列都应该是不可分割的最小单元。比如以下表中的 address 字段就不是不可分割的最小单元,如下图所示: 其中 address 还可以拆分为国家和城市,如下图所示: 这样改造之后,上面的表就满足第一范式了。 2.第二范式 第二范式是在满足第一范式的基础上,规定表中