功力题


基础篇

基本功

  • 面向对象的特征

      答案:封装、继承、多态

  • final, finally, finalize 的区别

  简单区别:

       final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
       finally是异常处理语句结构的一部分,表示总是执行。
       finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,供垃圾收集时的其他资源回收,例如关闭文件等

  • int 和 Integer 有什么区别

        Integer是int的包装类;int是基本数据类型;
        Integer变量必须实例化后才能使用;int变量不需要;
        Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
        Integer的默认值是null;int的默认值是0。

  • 重载和重写的区别

    override(重写)

       1、方法名、参数、返回值相同。

       2、子类方法不能缩小父类方法的访问权限。

       3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。

       4、存在于父类和子类之间。

       5、方法被定义为final不能被重写。

     overload(重载)

      1、参数类型、个数、顺序至少有一个不相同。

      2、不能重载只有返回值不同的方法名。

      3、存在于父类和子类、同类中。

  • 抽象类和接口有什么区别

    (1)抽象类里面可以包含普通成员方法,接口不能包含普通成员方法
    (2)抽象类可以有构造方法,接口中不能有构造方法
    (3)抽象类不可以有默认方法,接口中可以有默认方法
    (4)一个类只能直接继承一个父类(可以是抽象类),一个类可以实现多个接口
    (5)类与类之间只能是单继承关系,接口与接口之间可以多继承
    (6)抽象类可以定义普通的成员变量和常量,接口只能定义public static final 修饰的常量 ----接口肯定是用来实现的,所以必须是public的,
    (7)一个类可以实现多个接口,但只能继承一个抽象类。
  • 说说反射的用途及实现

         反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
        

        一、主要用途和实现 :

        1、反射最重要的用途就是开发各种通用框架。

       反射的实现:

        获取一个对象对应的反射类,在 Java 中有下列方法可以获取一个对象的反射类

  1. 通过 getClass() 方法
  2. 通过 Class.forName() 方法
  3. 使用 类.class
  4. 通过类加载器实现,getClassLoader()
  • 说说自定义注解的场景及实现

  • 登录、权限拦截、日志处理,以及各种 Java 框架,如 Spring,Hibernate,JUnit 提到注解就不能不说反射,Java 自定义注解是通过运行时靠反射获取注解。实际开发中,例如我们要获取某个方法的调用日志,可以通过 AOP(动态代理机制)给方法添加切面,通过反射来获取方法包含的注解,如果包含日志注解,就进行日志记录。反射的实现在 Java 应用层面上讲,是通过对 Class 对象的操作实现的,Class 对象为我们提供了一系列方法对类进行操作。在 JVM 这个角度来说,Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目按严格的顺序紧凑的排列在 Class 文件中,里面包含了类、方法、字段等等相关数据。通过对 Class 数据流的处理我们即可得到字段、方法等数据。
  • HTTP 请求的 GET 与 POST 方式的区别

    GET 和 POST 方法的区别

    1、发送的数据数量

    在 GET 中,只能发送有限数量的数据,因为数据是在 URL 中发送的。

    在 POST 中,可以发送大量的数据,因为数据是在正文主体中发送的。

    2、安全性

    GET 方法发送的数据不受保护,因为数据在 URL 栏中公开,这增加了漏洞和黑客攻击的风险。

    POST 方法发送的数据是安全的,因为数据未在 URL 栏中公开,还可以在其中使用多种编码技术,这使其具有弹性。

    3、加入书签中

    GET 查询的结果可以加入书签中,因为它以 URL 的形式存在;而 POST 查询的结果无法加入书签中。

    4、编码

    在表单中使用 GET 方法时,数据类型中只接受 ASCII 字符。

    在表单提交时,POST 方法不绑定表单数据类型,并允许二进制和 ASCII 字符。

    5、可变大小

    GET 方法中的可变大小约为 2000 个字符。

    POST 方法最多允许 8 Mb 的可变大小。

    6、缓存

    GET 方法的数据是可缓存的,而 POST 方法的数据是无法缓存的。

    7、主要作用

    GET 方法主要用于获取信息。而 POST 方法主要用于更新数据

  • session 与 cookie 区别

    cookie 和session 的区别:

    1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

    2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
       考虑到安全应当使用session。

    3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
       考虑到减轻服务器性能方面,应当使用COOKIE。

    4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

    5、所以个人建议:
       将登陆信息等重要信息存放为SESSION
       其他信息如果需要保留,可以放在COOKIE中

  • session 分布式处理
  • JDBC 流程

    通过JDBC操作数据库——步骤:

      第1步:注冊驱动 (仅仅做一次)

      第2步:建立连接(Connection)

      第3步:创建运行SQL的语句(Statement)

      第4步:运行语句

      第5步:处理运行结果(ResultSet)

      第6步:释放资源

    使用JDBC第一步:载入驱动

      注冊驱动有三种方式:

      1.      Class.forName(“com.mysql.jdbc.Driver”);

               推荐这样的方式,不会对详细的驱动类产生依赖

      2. DriverManager.registerDriver(com.mysql.jdbc.Driver);

               会对详细的驱动类产生依赖

      3. System.setProperty(“jdbc.drivers”, “driver1:driver2”);

               尽管不会对详细的驱动类产生依赖;但注冊不太方便。所以非常少使用

    使用JDBC第二步:建立连接

      通过Connection建立连接,Connection是一个接口类。其功能是与数据库进行连接(会话)。

      建立Connection接口类对象:

      Connection conn =DriverManager.getConnection(url, user, password);

      当中URL的格式要求为:

      JDBC:子协议:子名称//主机名:port/数据库名?属性名=属性值&…

      如:"jdbc:mysql://localhost:3306/test“

      user即为登录数据库的username,如root

      password即为登录数据库的密码,为空就填””

    使用JDBC第三步:创建运行对象

      运行对象Statement负责运行SQL语句。由Connection对象产生。

      Statement st = connection.createStatement();

      Statement接口类还派生出两个接口类PreparedStatement和CallableStatement,这两个接口类对象为我们提供了更加强大的数据訪问功能。

      PreparedStatement能够对SQL语句进行预编译,这样防止了   SQL注入 提高了安全性。

      PreparedStatement  ps=connection.prepareStatement( "update user set id=? where username=?”); ————sql语句中庸 ? 作为通配符,变量值通过参数设入:ps.setObject(1, object);

      而且预编译结果能够存储在PreparedStatement对象中。当多次运行SQL语句时能够提高效率。

      作为Statement的子类,PreparedStatement继承了Statement的全部函数。

      CallableStatement接口

      CallableStatement类继承了PreparedStatement类,他主要用于运行SQL存储过程。

      在JDBC中运行SQL存储过程须要转义。

      JDBC API提供了一个SQL存储过程的转义语法:

      {call[,, ...]}

      procedure-name:是所要运行的SQL存储过程的名字

      [,, ...]:是相相应的SQL存储过程所须要的參数

    使用JDBC第四步:运行SQL语句

      运行对象Statement 或 PreparedStatement 提供两个经常使用的方法来运行SQL语句。

      executeQuery(Stringsql),该方法用于运行实现查询功能的sql语句。返回类型为ResultSet(结果集)。

      如:ResultSet  rs =st.executeQuery(sql);

      executeUpdate(Stringsql),该方法用于运行实现增、删、改功能的sql语句,返回类型为int,即受影响的行数。

      如:int flag = st.executeUpdate(sql);

    使用JDBC第五步:处理运行结果

      ResultSet对象

      ResultSet对象负责保存Statement运行后所产生的查询结果。

      结果集ResultSet是通过游标来操作的。

      游标就是一个可控制的、能够指向随意一条记录的指针。

      有了这个指针我们就能轻易地指出我们要对结果集中的哪一条记录进行改动、删除,或者要在哪一条记录之前插入数据。一个结果集对象中仅仅包括一个游标。

       另外,借助ResultSetMetaData ,可以将数据表的结构信息都查出来。

      ResultSetMetaData rsmd= resultSet.getMetaData();

    使用JDBC 第六步——释放资源

      见随笔:

      数据库资源不关闭,其占用的内存不会被释放,徒耗资源,影响系统。

  • MVC 设计思想

  • MVC的理念就是把数据处理、数据展示(界面)和程序/用户的交互三者分离开的一种编程模式。
  • equals 与 == 的区别

    1.  ==是判断两个变量或实例是不是指向同一个内存空间,equals是判断两个变量或实例所指向的内存空间的值是不是相同 
    2. ==是指对内存地址进行比较 , equals()是对字符串的内容进行比较
    3. ==指引用是否相同, equals()指的是值是否相同

集合

  • List 和 Set 区别

    1、List,Set都是继承自Collection接口
    2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉,(元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
    3.Set和List对比:
    Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

  • List 和 Map 区别

    list是存储单列数据的集合,map是存储键和(key,value)}这样的双列数据的集合,List 中存 储的数据是有顺序,并且允许重复;Map 中存储的数据是没有顺序的,其键是不能重复的, 它的值是可以有重复的。
  • Arraylist 与 LinkedList 区别

    1、数据结构不同

    ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)的数据结构。

    2、效率不同

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

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

    3、自由性不同

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

    4、主要控件开销不同

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

  • ArrayList 与 Vector 区别

      1. ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
      2. Vector与ArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
      3. LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。
      4. vector是线程(Thread)同步(Synchronized)的,所以它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
      5. 如果集合中的元素的数目大于目前集合数组的长度时,vector增长率为目前数组长度的100%,而arraylist增长率为目前数组长度
        的50%.如过在集合中使用数据量比较大的数据,用vector有一定的优势。

      6. 如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是0(1),这个时候使用vector和arraylist都可以。而
        如果移动一个指定位置的数据花费的时间为0(n-i)n为总长度,这个时候就应该考虑到使用Linkedlist,因为它移动一个指定位置的数据
        所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。
        ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,
        都允许直接序号索引元素,但是插入数据要设计到数组元素移动 等内存操作,所以索引数据快插入数据慢,
        Vector由于使用了synchronized方法(线程安全)所以性能上比ArrayList要差
        ,LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入数度较快!

      7. 笼统来说:LinkedList:增删改快
                      ArrayList:查询快(有索引的存在)

  • HashMap 和 Hashtable 的区别

    1 HashMap不是线程安全的

                HashMap是map接口的子类,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而hashtable不允许。

    2   HashTable是线程安全。

    HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

    HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。 HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。 最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差

  • HashSet 和 HashMap 区别

    1.HashSet:

      HashSet实现了Set接口,它不允许集合中出现重复元素。当我们提到HashSet时,第一件事就是在将对象存储在

    HashSet之前,要确保重写hashCode()方法和equals()方法,这样才能比较对象的值是否相等,确保集合中没有

    储存相同的对象。如果不重写上述两个方法,那么将使用下面方法默认实现:

     public boolean add(Object obj)方法用在Set添加元素时,如果元素值重复时返回 "false",如果添加成功则返回"true"


    2.HashMap:

      HashMap实现了Map接口,Map接口对键值对进行映射。Map中不允许出现重复的键(Key)。Map接口有两个基本的实现

    TreeMap和HashMap。TreeMap保存了对象的排列次序,而HashMap不能。HashMap可以有空的键值对(Key(null)-Value(null))

    HashMap是非线程安全的(非Synchronize),要想实现线程安全,那么需要调用collections类的静态方法synchronizeMap()实现。

    public Object put(Object Key,Object value)方法用来将元素添加到map中。

  • HashMap 和 ConcurrentHashMap 的区别

  • HashMap 的工作原理及代码实现

  • ConcurrentHashMap 的工作原理及代码实现

线程

  • 创建线程的方式及实现
  • sleep() 、join()、yield()有什么区别
  • 说说 CountDownLatch 原理
  • 说说 CyclicBarrier 原理
  • 说说 Semaphore 原理
  • 说说 Exchanger 原理
  • 说说 CountDownLatch 与 CyclicBarrier 区别
  • ThreadLocal 原理分析
  • 讲讲线程池的实现原理
  • 线程池的几种方式
  • 线程的生命周期

锁机制

  • 说说线程安全问题
  • volatile 实现原理
  • synchronize 实现原理
  • synchronized 与 lock 的区别
  • CAS 乐观锁
  • ABA 问题
  • 乐观锁的业务场景及实现方式

核心篇

数据存储

  • MySQL 索引使用的注意事项
  • 说说反模式设计
  • 说说分库与分表设计
  • 分库与分表带来的分布式困境与应对之策
  • 说说 SQL 优化之道
  • MySQL 遇到的死锁问题
  • 存储引擎的 InnoDB 与 MyISAM
  • 数据库索引的原理
  • 为什么要用 B-tree
  • 聚集索引与非聚集索引的区别
  • limit 20000 加载很慢怎么解决
  • 选择合适的分布式主键方案
  • 选择合适的数据存储方案
  • ObjectId 规则
  • 聊聊 MongoDB 使用场景
  • 倒排索引
  • 聊聊 ElasticSearch 使用场景

缓存使用

  • Redis 有哪些类型
  • Redis 内部结构
  • 聊聊 Redis 使用场景
  • Redis 持久化机制
  • Redis 如何实现持久化
  • Redis 集群方案与实现
  • Redis 为什么是单线程的
  • 缓存奔溃
  • 缓存降级
  • 使用缓存的合理性问题

消息队列

  • 消息队列的使用场景
  • 消息的重发补偿解决思路
  • 消息的幂等性解决思路
  • 消息的堆积解决思路
  • 自己如何实现消息队列
  • 如何保证消息的有序性

框架篇

Spring

  • BeanFactory 和 ApplicationContext 有什么区别
  • Spring Bean 的生命周期
  • Spring IOC 如何实现
  • 说说 Spring AOP
  • Spring AOP 实现原理
  • 动态代理(cglib 与 JDK)
  • Spring 事务实现方式
  • Spring 事务底层原理
  • 如何自定义注解实现功能
  • Spring MVC 运行流程
  • Spring MVC 启动流程
  • Spring 的单例实现原理
  • Spring 框架中用到了哪些设计模式
  • Spring 其他产品(Srping Boot、Spring Cloud、Spring Secuirity、Spring Data、Spring AMQP 等)

Netty

  • 为什么选择 Netty
  • 说说业务中,Netty 的使用场景
  • 原生的 NIO 在 JDK 1.7 版本存在 epoll bug
  • 什么是TCP 粘包/拆包
  • TCP粘包/拆包的解决办法
  • Netty 线程模型
  • 说说 Netty 的零拷贝
  • Netty 内部执行流程
  • Netty 重连实现

微服务篇

微服务

  • 前后端分离是如何做的
  • 微服务哪些框架
  • 你怎么理解 RPC 框架
  • 说说 RPC 的实现原理
  • 说说 Dubbo 的实现原理
  • 你怎么理解 RESTful
  • 说说如何设计一个良好的 API
  • 如何理解 RESTful API 的幂等性
  • 如何保证接口的幂等性
  • 说说 CAP 定理、 BASE 理论
  • 怎么考虑数据一致性问题
  • 说说最终一致性的实现方案
  • 你怎么看待微服务
  • 微服务与 SOA 的区别
  • 如何拆分服务
  • 微服务如何进行数据库管理
  • 如何应对微服务的链式调用异常
  • 对于快速追踪与定位问题
  • 微服务的安全

分布式

  • 谈谈业务中使用分布式的场景
  • Session 分布式方案
  • 分布式锁的场景
  • 分布是锁的实现方案
  • 分布式事务
  • 集群与负载均衡的算法与实现
  • 说说分库与分表设计
  • 分库与分表带来的分布式困境与应对之策

安全问题

  • 安全要素与 STRIDE 威胁
  • 防范常见的 Web 攻击
  • 服务端通信安全攻防
  • HTTPS 原理剖析
  • HTTPS 降级攻击
  • 授权与认证
  • 基于角色的访问控制
  • 基于数据的访问控制

性能优化

  • 性能指标有哪些
  • 如何发现性能瓶颈
  • 性能调优的常见手段
  • 说说你在项目中如何进行性能调优

工程篇

需求分析

  • 你如何对需求原型进行理解和拆分
  • 说说你对功能性需求的理解
  • 说说你对非功能性需求的理解
  • 你针对产品提出哪些交互和改进意见
  • 你如何理解用户痛点

设计能力

  • 说说你在项目中使用过的 UML 图
  • 你如何考虑组件化
  • 你如何考虑服务化
  • 你如何进行领域建模
  • 你如何划分领域边界
  • 说说你项目中的领域建模
  • 说说概要设计

设计模式

  • 你项目中有使用哪些设计模式
  • 说说常用开源框架中设计模式使用分析
  • 说说你对设计原则的理解
  • 23种设计模式的设计理念
  • 设计模式之间的异同,例如策略模式与状态模式的区别
  • 设计模式之间的结合,例如策略模式+简单工厂模式的实践
  • 设计模式的性能,例如单例模式哪种性能更好。

业务工程

  • 你系统中的前后端分离是如何做的
  • 说说你的开发流程
  • 你和团队是如何沟通的
  • 你如何进行代码评审
  • 说说你对技术与业务的理解
  • 说说你在项目中经常遇到的 Exception
  • 说说你在项目中遇到感觉最难Bug,怎么解决的
  • 说说你在项目中遇到印象最深困难,怎么解决的
  • 你觉得你们项目还有哪些不足的地方
  • 你是否遇到过 CPU 100% ,如何排查与解决
  • 你是否遇到过 内存 OOM ,如何排查与解决
  • 说说你对敏捷开发的实践
  • 说说你对开发运维的实践
  • 介绍下工作中的一个对自己最有价值的项目,以及在这个过程中的角色

软实力

  • 说说你的亮点
  • 说说你最近在看什么书
  • 说说你觉得最有意义的技术书籍
  • 工作之余做什么事情
  • 说说个人发展方向方面的思考
  • 说说你认为的服务端开发工程师应该具备哪些能力
  • 说说你认为的架构师是什么样的,架构师主要做什么
  • 说说你所理解的技术专家