面试攻略

[TOC]

基本篇

基本功

  1. 面向对象的特征 ==继承 封装 多态==
  2. final 、finally、finalize的区别
    final:用来修饰类,方法和变量(成员变量或局部变量)
    修饰类:意味着不能再派生出新的子类,不能作为父类而被子类继承。因此一个类不能既被abstract声明,又被final声明
    修饰方法:只能使用,即不能方法重写
    修饰变量:可以保证他们在使用的时候不被改变。其初始化可以在两个地方:一是其定义的地方,也就是在final变量在定义的时候就对其赋值;二是在构造函数中。这两个地方只能选其中的一个,要么在定义的时候给值,要么在构造函数中给值
  3. int 和 Integer 有什么区别
    (1)Integer是int的包装类;int是基本数据类型
    (2)Integer变量必须实例化后才能使用;int变量不需要
    (3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; (4)Integer的默认值是null;int的默认值是0
    原始类型:boolean,char,byte,short,int,long,float,double
    包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
  4. 重载(Overloading)和重写(Override)的区别
    方法重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同
    方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型
    ps:(1)子类中不能重写父类中的final方法 (2)子类中必须重写父类中的abstract方法
  5. 抽象类和接口有什么区别
    抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
    抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
    接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
    一个类只能继承一个抽象类,而一个类却可以实现多个接口
  6. 说说反射的用途及实现
    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
  • 反射提供的功能:
    在运行时判断任意一个对象所属的类
    在运行时构造任意一个类的对象
    在运行时判断任意一个类所具有的成员变量和方法(通过反射设置可以调用 private)
    在运行时调用任意一个对象的方法
    ==反射最重要的用途就是开发各种通用框架==
    很多框架(比如 Spring)都是配置化的(比如通过 XML文件配置JavaBean,Action之类的),为了保证框架的通用性,他们可能根据配置文件加载不同的对象或类,调用不同的方法,这个时候就必须用到反射——运行时动态加载需要加载的对象
  1. 说说自定义注解的场景及实现

  2. HTTP 请求的 GET 与 POST 方式的区别
    GET在浏览器回退时是无害的,而POST会再次提交请求。
    GET产生的URL地址可以被Bookmark,而POST不可以
    GET请求会被浏览器主动cache,而POST不会,除非手动设置
    GET请求只能进行url编码,而POST支持多种编码方式
    GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
    GET请求在URL中传送的参数是有长度限制的(1024k),而POST没有限制
    对参数的数据类型,GET只接受ASCII字符,而POST没有限制
    GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
    GET参数通过URL传递,POST放在Request body中

  3. session 与 cookie 区别
    cookie数据存放在客户的浏览器上,session数据放在服务器上发
    cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
    单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie
    可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中
    session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

  4. session 分布式处理
    处理方案

  5. Jdbc流程
    第一步:加载Driver类,注册数据库驱动;
    第二步:通过DriverManager,使用url,用户名和密码建立连接(Connection);
    第三步:通过Connection,使用sql语句打开Statement对象;
    第四步:执行语句,将结果返回resultSet;
    第五步:对结果resultSet进行处理;
    第六步:倒叙释放资源resultSet-》preparedStatement-》connection

  6. MVC 设计思想

    1. MVC英文即Model-View-Controller,即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层
    2. 视图(View)代表用户交互界面,对于Web应用来说,可以概括为HTML界面,但有可能为XHTML、XML和Applet
    3. 模型(Model):就是业务流程/状态的处理以及业务规则的制定。业务流程的处理过程对其它层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的核心
    4. 控制(Controller)可以理解为从用户接收请求, 将模型与视图匹配在一起,共同完成用户的请求
  1. spring mvc 架构原理
    1、发起请求到前端控制器(DispatcherServlet),该控制器中就会过滤出你哪些请求可以访问该servlet哪些不可以,就是url-pattern的作用,并且会加载springmvc.xml配置文件
    2、前端控制器会找到HandlerMapping(处理器映射器),通过HandlerMapping完成url到controller映射的组件,通俗点讲,就是将在springmvc.xml中配置的或者注解的url与对应的处理类找到并进行存储,实际上是用一个map集合来保存这种映射关系,map<url,handler>; 这样,就将所有的这种映射关系都记录保存了下来
    3、通过HandlerMapping有了这些映射关系,并且找到了url对应的处理器,HandlerMapping就会将其处理器(图中红色标明的handler)返回,在其返回之前,在加上很多的拦截器,其作用后面进行讲解,这里知道在返回的处理器前会有很多的拦截器即。
    4、DispatcherServlet拿到了handler之后,找到HandlerAdapter(处理器适配器),通过它来访问处理器,并且执行处理器。这里会有人会有疑惑,为什么需要处理器适配器,我们都获得了处理类了,直接调用不就行了吗?
    不行,因为我们只知道处理类在哪里,并不知道执行处理类中的哪个方法,其实也就是不知道处理类是通过哪种方式创建出来的,实现HttpRequestHandler?还是注解方式,或者是其他方式,我们不知道,所以需要HandlerAdapter来帮我们确认调用哪个方法。
    5、执行处理器
    6、处理器会返回一个ModelAndView对象给HandlerAdapter
    7、通过HandlerAdapter将ModelAndView对象返回给前端控制器(DispatcherServlet
    8、前端控制器请求视图解析器(ViewResolver)去进行视图解析,根据逻辑视图名解析成真正的视图(jsp),其实就是将ModelAndView对象中存放视图的名称进行查找,找到对应的页面形成视图对象
    9、返回视图对象到前端控制器。
    10、视图渲染,就是将ModelAndView对象中的数据放到request域中,用来让页面加载数据的。
    11、通过第8步,通过名称找到了对应的页面,通过第10步,request域中有了所需要的数据,那么就能够进行视图渲染了。最后将其返回即可
    link
  2. equals 与 == 的区别
    == 比较的是地址
    equlas 先比较地址,然后比较值

集合

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

  2. Arraylist 与 LinkedList 区别

    1. ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构
    2. 对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针
    3. 对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢
    4. Vector跟ArrayList一样,只是使用了synchronized方法-线程安全
  3. HashMap 和 Hashtable 的区别
    1.两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字
    2.HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key
    3.HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口
    4.HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
    5.HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1即:capacity2+1
    6.HashMap和Hashtable的底层实现都是数组+链表结构实现
    7.两者计算hash的方法不同:
    Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模:

    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % tab.length;
    

    HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸:

     static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }
    
  4. HashMap 的工作原理及代码实现 ConcurrentHashMap 的工作原理及代码实现
    参考链接

线程

  1. 创建线程的方式及实现
    1.继承Thread类创建线程
    2.实现Runnable接口创建线程 多实现
    3.使用Callable和Future创建线程 有返回结果,实现call方法
    4.使用线程池例如用Executor框架
  2. sleep() 、join()、yield()有什么区别
    1.sleep:Thread类的方法,必须带一个时间参数。会让当前线程休眠进入阻塞状态并释放CPU,提供其他线程运行的机会且不考虑优先级,但如果有同步锁则sleep不会释放锁即其他线程无法获得同步锁
    2.yield:Thread类的方法,类似sleep但无法指定时间并且只会提供相同或更高优先级的线程运行的机会,不推荐使用
    3.join:一种特殊的wait,当前运行线程调用另一个线程的join方法,当前线程进入阻塞状态直到另一个线程运行结束
  3. 说说 CountDownLatch 原理
    CountDownLatch主要有两个方法,当一个或多个线程调用await方法时,这些线程会阻塞。其它线程调用countDown方法会将计数器减1(调用countDown方法的线程不会阻塞),当计数器的值变为0时,因await方法阻塞的线程会被唤醒,继续执行。
    ==实现原理==:计数器的值由构造函数传入,并用它初始化AQS的state值。当线程调用await方法时会检查state的值是否为0,如果是就直接返回(即不会阻塞);如果不是,将表示该节点的线程入列,然后将自身阻塞。当其它线程调用countDown方法会将计数器减1,然后判断计数器的值是否为0,当它为0时,会唤醒队列中的第一个节点,由于CountDownLatch使用了AQS的共享模式,所以第一个节点被唤醒后又会唤醒第二个节点,以此类推,使得所有因await方法阻塞的线程都能被唤醒而继续执行。
    CountDownLatch是通过“共享锁”实现的。在创建CountDownLatch中时,会传递一个int类型参数count,该参数是“锁计数器”的初始状态,表示该“共享锁”最多能被count给线程同时获取。当某线程调用该CountDownLatch对象的await()方法时,该线程会等待“共享锁”可用时,才能获取“共享锁”进而继续运行。而“共享锁”可用的条件,就是“锁计数器”的值为0!而“锁计数器”的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时,才将“锁计数器”-1;通过这种方式,必须有count个线程调用countDown()之后,“锁计数器”才为0,而前面提到的等待线程才能继续运行
  4. 说说 CyclicBarrier 原理
    ==实现原理==:在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用CyclicBarrier的await方法时,将剩余拦截的线程数减1,然后判断剩余拦截数是否为0,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁,接着先从await方法返回,再从CyclicBarrier的await方法中返回
  5. 说说 Semaphore 原理
    Semaphore内部主要通过AQS(AbstractQueuedSynchronizer)实现线程的管理。Semaphore有两个构造函数,参数permits表示许可数,它最后传递给了AQS的state值。线程在运行时首先获取许可,如果成功,许可数就减1,线程运行,当线程运行结束就释放许可,许可数就加1。如果许可数为0,则获取失败,线程位于AQS的等待队列中,它会被其它释放许可的线程唤醒。在创建Semaphore对象的时候还可以指定它的公平性。一般常用非公平的信号量,非公平信号量是指在获取许可时先尝试获取许可,而不必关心是否已有需要获取许可的线程位于等待队列中,如果获取失败,才会入列。而公平的信号量在获取许可时首先要查看等待队列中是否已有线程,如果有则入列。
  6. 说说 Exchanger 原理
    == 原理==:Exchanger(交换者)是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。它提供一个同步点,在这个同步点两个线程可以交换彼此的数据。这两个线程通过exchange方法交换数据, 如果第一个线程先执行exchange方法,它会一直等待第二个线程也执行exchange,当两个线程都到达同步点时,这两个线程就可以交换数据,将本线程生产出来的数据传递给对方。因此使用Exchanger的重点是成对的线程使用exchange()方法,当有一对线程达到了同步点,就会进行交换数据。因此该工具类的线程对象是成对的。
    ==应用场景==:Exchanger可以用于遗传算法,遗传算法里需要选出两个人作为交配对象,这时候会交换两人的数据,并使用交叉规则得出2个交配结果
    Exchanger也可以用于校对工作。比如我们需要将纸制银流通过人工的方式录入成电子银行流水,为了避免错误,采用AB岗两人进行录入,录入到Excel之后,系统需要加载这两个Excel,并对这两个Excel数据进行校对,看看是否录入的一致。
  7. 说说 CountDownLatch 与 CyclicBarrier 区别
    CountDownLatch的作用是允许1或N个线程等待其他线程完成执行;而CyclicBarrier则是允许N个线程相互等待。
    CountDownLatch的计数器无法被重置;CyclicBarrier的计数器可以被重置后使用,因此它被称为是循环的barrier。
  8. ThreadLocal 原理分析
  9. 讲讲线程池的实现原理
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 13,900评论 4 56
  • Java继承关系初始化顺序 父类的静态变量-->父类的静态代码块-->子类的静态变量-->子类的静态代码快-->父...
    第六象限阅读 6,535评论 0 9
  • 在一个方法内部定义的变量都存储在栈中,当这个函数运行结束后,其对应的栈就会被回收,此时,在其方法体中定义的变量将不...
    Y了个J阅读 9,918评论 1 14
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 33,627评论 18 399
  • 开学已经上了四节美术课了,跟小朋友也慢慢熟络起来。对小朋友之间的脾气以及家长也慢慢有点了解,很庆幸大家喜欢玉米老师...
    玉米的空间阅读 3,899评论 0 3

友情链接更多精彩内容