java后端——面试题整理

自用,如有错误求指出

  • 近期面试的面试题整理
  • 1.问答:
    • ==String的intern()方法有了解过吗==
    • ==final和static的区别==
    • ==java的基本类型数据都会被包装成引用数据类型,是怎么实现的呢==
    • ==Integer和int的区别==
    • ==import static了解过吗==
    • ==StringBuffer和StringBuilder的区别==
    • ==字符串用+会生成新的对象吗==
    • ==ThreadLocal类==
    • ==Future类==
    • ==重写equals方法需要注意什么==
    • ==java中Queue的优先级队列是怎么实现的==
    • ==java有哪些集合==
    • ==简单介绍一下HashMap==
    • ==二叉树、平衡二叉树、红黑树简单介绍一下区别==
    • ==有哪些排序算法==
    • ==几种排序算法中时间复杂度是O(nlogn)的有==
    • ==简单介绍一下冒泡排序算法==
    • ==简单介绍一下快速排序算法==
    • ==简单介绍一下堆排序算法==
    • ==JVM内存介绍一下==
    • ==JDK1.8和JDK1.7JVM内存有什么变化==
    • ==堆还能细分成?==
    • ==类加载机制和类加载过程==
    • ==父子类的加载顺序==
    • ==垃圾回收器有哪些==
    • ==垃圾回收算法能说说吗==
    • ==标记清除算法是怎么标记的呢==
    • ==新生代用的什么GC算法?老年代用的什么GC算法?==
    • ==简单介绍一下动态代理==
    • ==sleep()和wait()的区别==
    • ==怎么实现多线程==
    • ==java的线程池了解吗==
    • ==synchronized和Lock的区别==
    • ==过滤器、监听器和拦截器的区别==
    • ==怎么读取配置文件==
    • ==读取文件的过程是什么==
    • ==进程间如何传输数据的==
    • ==缓存的几种算法,简单介绍一下LRU==
    • ==线程和进程==
    • ==网络是怎么分层的==
    • ==tcp/ip协议是什么==
    • ==tcp和udp的区别==
    • ==同步IO和异步IO的区别==
    • ==ForkJoin框架了解吗==
    • ==mysql中左连接、右连接和内连接的区别==
    • ==mysql的常用存储引擎的索引都用的什么数据结构,主键索引和非主键索引的区别==
    • ==spring两个特性简单介绍一下==
    • ==springAOP的底层和类型==
    • ==常用的设计模式==
  • 2.算法
    • (1)数组
    • (2)链表

大部分是百度上查的答案

近期面试的面试题整理

1.问答:

String的intern()方法有了解过吗

字符串池最初是空的,由类String单独维护。
当调用intern方法时,如果池中已经包含一个与equals(object)方法确定的字符串对象相等的字符串,则返回池中的字符串。否则,此字符串对象将添加到池中,并返回对此字符串对象的引用。
因此,对于任何两个字符串s和t,s.intern()==t.intern()是真的当且仅当s.equals(t)为真时。

return: 与此字符串具有相同内容的字符串,但保证来自唯一字符串池。

参考java官方文档:
public String intern()
Returns a canonical representation for the string object.
A pool of strings, initially empty, is maintained privately by the class String.

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.

It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.

Returns:
a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.

final和static的区别

1.final:
(1)修饰类:无法被继承

(2)修饰方法:
父类的final方法是public不可被子类重写,可被继承
父类的final方法是private,由于private不被继承,子类可以定义一个相同的方法

(3)修饰属性:
成员变量:表示常量,一般和static联合使用,被final修饰值不可变
基本数据类型:初始化后值不可变
引用数据类型:初始化后不能指向其他的对象

2.static:
(1)修饰方法:调用时用类名.方法名

(2)修饰变量:不可修饰局部变量,在对象之间共享值或者方便访问变量时使用static来修饰

(3)静态代码块:在类加载时执行

java的基本类型数据都会被包装成引用数据类型,是怎么实现的呢

Java的基本数据类型、拆装箱(深入版)

Integer和int的区别

(1)Integer是int的包装类,int则是java的一种基本数据类型

(2)Integer变量必须实例化后才能使用,而int变量不需要

(3)Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 。

(4)Integer的默认值是null,int的默认值是0

import static了解过吗

import static静态导入是JDK1.5中的新特性。
一般我们导入一个类都用 import 包名.类名;
而静态导入是这样:import static 包名.类名.*;

这里的多了个static,还有就是类名后面多了个 .* 。意思是导入这个类里的静态成员(静态方法、静态变量)。当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用“类名.方法名()” 的方式来调用。这种方法的好处就是可以简化一些操作,例如一些工具类的静态方法,如果使了静态导入,就可以像使用自己的方法一样使用这些静态方法。

不过在使用静态导入之前,我们必须了解下面几点:

1.静态导入可能会让代码更加难以阅读

2.import static和static import不能替换位置

3.如果同时导入的两个类中又有重命名的静态成员,会出现编译器错误。例如Integer类和Long类的MAX_VALUE。

4.可以导入的静态成员包括静态对象引用、静态常量和静态方法。

StringBuffer和StringBuilder的区别

我这里就不总结了:StringBuffer和StringBuilder的区别

字符串用+会生成新的对象吗

如果有对象参与相加,编译器没法处理,结果为新的对象
字符串常量直接相加,会先经过编译器处理,调用StringBuffer或StringBuilder的append方法;

ThreadLocal类

ThreadLocal

Future类

Future

重写equals方法需要注意什么

必须重写hashCode,参与equals函数的字段,也必须都参与hashCode 的计算。

java中Queue的优先级队列是怎么实现的

java学习笔记之优先队列实现原理

java有哪些集合

1.单个方式存储元素
java后端——面试题整理_第1张图片

2.键值对存储元素

简单介绍一下HashMap

了解rehash方法吗
rehash在计算索引位置index时,HashTable进行了一个与运算过程(hash & 0x7FFFFFFF),为什么需要做一步操作,这么做有什么好处?

 for (int i = oldCapacity ; i-- > 0 ;) {
            for (IdentityHashtableEntry old = oldTable[i] ; old != null ; ) {
                IdentityHashtableEntry e = old;
                old = old.next;

                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newTable[index];
                newTable[index] = e;
            }
        }

hashtable进行扩容的时候,会进行rehash,通过与运算,旧数组中的元素的hashCode要么和新数组中的hashCode相同,要么在为旧的hashCode+2^n,也就是能尽可能保持原有链表的顺序。

二叉树、平衡二叉树、红黑树简单介绍一下区别

二叉树,平衡二叉树,红黑树,B-树、B+树、B*树的区别

有哪些排序算法

十大经典排序算法最强总结(含JAVA代码实现)

几种排序算法中时间复杂度是O(nlogn)的有

希尔排序、快速排序、归并排序、堆排序

简单介绍一下冒泡排序算法

它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

简单介绍一下快速排序算法

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

简单介绍一下堆排序算法

利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

说一说建堆的过程
1.首先根据序列构建一个完全二叉树
2.在完全二叉树的基础上,从最后一个非叶结点开始调整:比较三个元素的大小–自己,它的左孩子,右孩子。分为三种情况:

自己最大,不用调整
左孩子最大,交换该非叶结点与其左孩子的值,并考察以左孩子为根的子树是否满足大顶堆的要求,不满足递归向下处理
右孩子最大,交换该非叶结点与其右孩子的值,并考察以右孩子为根的子树是否满足大顶堆的要求,不满足递归向下处理

JVM内存介绍一下

java后端——面试题整理_第2张图片

JDK1.8和JDK1.7JVM内存有什么变化

jvm内存模型jdk1.7和jdk1.8的区别

堆还能细分成?

java后端——面试题整理_第3张图片

类加载机制和类加载过程

java类的加载机制

父子类的加载顺序

父类静态属性(成员变量) > 父类静态代码块 > 子类静态属性 > 子类静态代码块 >
父类非静态属性 > 父类非静态代码块 > 父类构造器 >
子类非静态属性 > 子类非静态代码块 > 子类构造器

垃圾回收器有哪些

讲一下垃圾回收器都有哪些?

垃圾回收算法能说说吗

JVM常见垃圾回收算法

标记清除算法是怎么标记的呢

从GC-Root开始进行可达性分析

新生代用的什么GC算法?老年代用的什么GC算法?

新生代:复制算法
老年代:标记-压缩算法

简单介绍一下动态代理

动态代理

sleep()和wait()的区别

1、sleep是线程中的方法,但是wait是Object中的方法。

2、sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。

3、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。

4、sleep不需要被唤醒(休眠之后退出阻塞),但是wait需要(不指定时间需要被别人中断)。

怎么实现多线程

实现多线程的四种方式

java的线程池了解吗

讲解视频

synchronized和Lock的区别

讲解视频
java后端——面试题整理_第4张图片

过滤器、监听器和拦截器的区别

1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调

2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器

3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用

4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能

5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

执行顺序:过滤前 - 拦截前 - Action处理 - 拦截后 -过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程,再向上返回到过滤器的后续操作。

过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。
拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。
监听器(Listener):当一个事件发生的时候,你希望获得这个事件发生的详细信息,而并不想干预这个事件本身的进程,这就要用到监听器。

怎么读取配置文件

java读取properties配置文件的几种方式
1.基于InputStream读取配置文件
2.通过Spring中的PropertiesLoaderUtils工具类进行获取
3.通过 java.util.ResourceBundle 类读取

读取文件的过程是什么

1.读:打开文件 – 产生句柄 – 权限 – 转换成流 – 读取 — 关闭句柄 – 关闭文件du
2.写:打开zhi文件 – 产生句柄 – 权限 – 加锁 — 是否追加写入 – 写流 — 关闭句柄 – 关闭文件

进程间如何传输数据的

进程间通讯的7种方式

缓存的几种算法,简单介绍一下LRU

关于常见的几种缓存算法

线程和进程

  1. 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;

  2. 一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线

  3. 进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信

号等),某进程内的线程在其他进程不可见;

  1. 调度和切换:线程上下文切换比进程上下文切换要快得多

线程和进程关系示意图

网络是怎么分层的

1.应用层为 文件传输,电子邮件,文件服务,虚zhi拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet

2.传输层 提供端对端的接dao口 TCP,UDP

3.网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP

4.数据链路层, 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU

5.物理层 以二进制数据形式在物理媒体上传输数据

tcp/ip协议是什么

TCP/IP 是互联网相关各类协议族的总称。
TCP/IP 的分层管理:
TCP/IP协议里最重要的一点就是分层。TCP/IP协议族按层次分别为 应用层,传输层,网络层,数据链路层,物理层。当然也有按不同的模型分为4层或者7层的。

tcp和udp的区别

tcp和udp的区别

同步IO和异步IO的区别

同步IO和异步IO的区别

ForkJoin框架了解吗

ForkJoin

mysql中左连接、右连接和内连接的区别

1.内连接只显示两表中有关联的数据

2.左连接显示左表所有数据,右表没有对应的数据用NULL补齐,多了的数据删除

3.右连接显示右表所有数据,左表没有对应的数据用NULL对齐,多了的数据删除

mysql的常用存储引擎的索引都用的什么数据结构,主键索引和非主键索引的区别

Mysql数据库存储引擎及索引的数据结构

spring两个特性简单介绍一下

深入理解Spring的两大特征(IOC和AOP)

springAOP的底层和类型

1.AOP的底层是动态代理

追问:有几种实现方式

有两种:
(1)JDK动态代理:要求对象必须实现接口

为什么?Java动态代理为什么要求必须实现顶级接口

(2)CGLIB动态代理

注意什么:只要可继承的类都可以实现,所以被final修饰的不能实现该动态代理

2.类型有五种

  • 前置通知(Before):在目标方法被调用之前调用通知功能。
  • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么。
  • 返回通知(After-returning):在目标方法成功执行之后调用通知。
  • 异常通知(After-throwing):在目标方法抛出异常后调用通知。
  • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

说说执行顺序:可以通过order来指定执行顺序 ,数字越小优先级越高

java后端——面试题整理_第5张图片

常用的设计模式

2.算法

(1)数组

给定一个数组和一个数字n,找出数组中两个数字和为n的组合,一组即可

1.辅助空间,hash表

    public static int[] method1(int[] arr, int number){
        int len = arr.length;
        if (len == 0 ||len == 1) return new int[]{};
        Map<Integer, Integer> tempMap = new HashMap<>();
        for (int i = 0; i < len; i++){
            tempMap.put(arr[i] , i);
        }
        for (int i = 0; i < len; i++){
            if (tempMap.containsKey(number - arr[i]) && tempMap.get(number - arr[i]) != i){
                return new int[]{arr[i] , number - arr[i]};
            }
        }
        return new int[]{};
    }

2.给数组排序

    public static int[] method2(int[] arr, int number){
        int len = arr.length;
        if (len == 0 ||len == 1) return new int[]{};
        Arrays.sort(arr);
        for (int i = 0, j = len - 1; i < j;){
            if (arr[i] + arr[j] > number){
                j--;
            }else if (arr[i] + arr[j] < number){
                i++;
            }else {
                return new int[]{arr[i] , arr[j]};
            }
        }
        return new int[]{};
    }

(2)链表

给定一个单链表,在链表中把第 L 个节点到第 R 个节点这一部分进行反转。
输入描述:
null
输出描述:
null
备注
示例1:
输入 [1,2,3,4,5],1,3 输出 {3,2,1,4,5}
class ListNode{
    int value;
    ListNode next;

    public ListNode() {
    }

    public ListNode(int value) {
        this.value = value;
    }
}
public class List {

    public static ListNode InverseheadByIndex(ListNode head,int left,int right){
        ListNode temp = head;
        ListNode preLeft = null;//左边下标的前一个
        ListNode afterRight = null;//右边下标的后一个
        int len;
        for (len = 1; temp != null; len++){
            if (len + 1 == left) preLeft = temp;
            if (len - 1 == right) afterRight = temp;
            temp = temp.next;
        }
        if (left > right || right > len || left < 1) return null;
        temp = preLeft == null ? head : preLeft.next;
        ListNode tempNext = temp.next;
        temp.next = afterRight;
        ListNode node = null;
        while (tempNext != afterRight){
            node = tempNext.next;
            tempNext.next = temp;
            temp = tempNext;
            tempNext = node;
        }
        if (preLeft != null){
            preLeft.next = temp;
            return head;
        }
        return temp;
    }

    public static void main(String[] args) {
        ListNode node = new ListNode(1);
        ListNode node1 = new ListNode(2);
        node.next = node1;
        ListNode node2 = new ListNode(3);
        node1.next = node2;
        ListNode node3 = new ListNode(4);
        node2.next = node3;
        ListNode node4 = new ListNode( 5);
        node3.next = node4;

        ListNode result = InverseheadByIndex(node,2,3);
        while (result != null){
            System.out.println(result.value);
            result = result.next;
        }
    }
}

反转部分单向链表——思路

你可能感兴趣的:(知识点,java,面试,数据结构,算法)