Java面试知识总结
常用算法考察
选择排序
public class SelectionSort { // 我们的算法类不允许产生任何实例 private SelectionSort(){} public static void sort(int[] arr){ int n = arr.length; for( int i = 0 ; i < n ; i ++ ){ // 寻找[i, n)区间里的最小值的索引 int minIndex = i; for( int j = i + 1 ; j < n ; j ++ ) if( arr[j] < arr[minIndex] ) minIndex = j; swap( arr , i , minIndex); } } private static void swap(int[] arr, int i, int j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } public static void main(String[] args) { int[] arr = {10,9,8,7,6,5,4,3,2,1}; SelectionSort.sort(arr); for( int i = 0 ; i < arr.length ; i ++ ){ System.out.print(arr[i]); System.out.print(' '); } System.out.println(); } }
冒泡排序
public void maopao(int array[]){ for(int i=1;i<array.length;i++) for(int j=0;j<array.length-i;j++){ if(array[j]>array[j+1]){ int temp=array[j]; array[j]=array[j+1]; array[j+1]=temp; } } }
冒泡排序动画演示
快速排序
http://blog.51cto.com/ahalei/1365285
void quicksort(int left,int right) { int i,j,t,temp; if(left>right) return; temp=a[left]; //temp中存的就是基准数 i=left; j=right; while(i!=j) { //顺序很重要,要先从右边开始找 while(a[j]>=temp && i<j) j--; //再找右边的 while(a[i]<=temp && i<j) i++; //交换两个数在数组中的位置 if(i<j) { t=a[i]; a[i]=a[j]; a[j]=t; } } //最终将基准数归位 a[left]=a[i]; a[i]=temp; quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程 }
插入排序
希尔排序
https://www.cnblogs.com/chengxiao/p/6104371.html
归并排序
https://www.cnblogs.com/chengxiao/p/6194356.html
堆排序
https://www.cnblogs.com/chengxiao/p/6129630.html
桶排序
http://blog.51cto.com/ahalei/1362789
动态规划
https://blog.csdn.net/baidu_28312631/article/details/47418773
最长公共子序列
http://www.cnblogs.com/huangxincheng/archive/2012/11/11/2764625.html
最长公共子串
https://blog.csdn.net/u012102306/article/details/53184446
最长回文子串
https://blog.csdn.net/qq_32354501/article/details/80084325
数组的最大k个值
数字的最大连续子数组之和
左旋转字符串
字符串匹配算法:KMP算法
二分查找
链表
单链表逆序
两个有序单链表合并
两个单链表是否相交
相交处的节点
单链表倒数第K个数
单链表排序
栈和队列
两个队列实现栈
两个栈实现队列
一个数组实现栈和队列
树
前序、中序、后续遍历
求二叉树的深度
按层次遍历二叉树
判断二叉树是否为完全二叉树
判断二叉树是否镜面对称
判断两颗树是否相等
卡特兰数
出栈顺序
n个节点构成的二叉树个数
括号化
设计模式
Java源码中有哪些设计模式
http://www.iteye.com/news/18725
常见的设计模式类图
http://blog.sina.com.cn/s/blog_8cc6ff5c0101d4cp.html
常见的设计模式的示例:
http://www.jb51.net/article/27973.htm
数据库
数据库的crud语句的书写
数据库优化策略、如何优化
海量数据优化
事务
事务中锁分类
事务特性
数据库表锁
行列锁
临时表
索引
存储空间
视图
Linux常用命令(最好实战)
http://www.php100.com/html/webkaifa/Linux/2009/1106/3485.html
linux上搭建服务器
http://www.cnblogs.com/dudu/archive/2012/12/09/linux-apache-git.html
常用的网络端口
http://www.360doc.com/content/11/1202/09/8209768_169068538.shtml
Nosql、redis等的熟悉、了解
http://www.yiibai.com/redis/redis_quick_guide.html
海量数据的处理
Bit-map、分而治之、hash映射、分布式处理(Hadoop)、Trie树、双层桶排序等
Java基础
Java集合框架综述
https://www.cnblogs.com/xiaoxi/p/6089984.html
https://www.cnblogs.com/xiohao/p/4309462.html
HashMap的存储机制(很重要,必看)http://www.cnblogs.com/CarpenterLee/p/5440428.html
https://www.cnblogs.com/zx-bob-123/archive/2017/12/26/8118074.html
Set、map区别
Set、list区别
Arraylist、LinkedList区别
(1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (2)对于随机访问get和set,ArrayList绝对优于LinkedList,因为LinkedList要移动指针。 (3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。 这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。
String、Stringbufer、StringBuilder区别
HashSet、LinkedHashSet区别
HashMap、TreeMap、LinkedHashMap
熟悉Java集合类的框架图
HashMap、ArrayList、StringBuffer、String等源码的熟悉
Iterator和ListIterator区别
我们在使用List,Set的时候,为了实现对其数据的遍历,我们经常使用到了Iterator(迭代器)。使用迭代器,你不需要干涉其遍历的过程,只需要每次取出一个你想要的数据进行处理就可以了。但是在使用的时候也是有不同的。List和Set都有iterator()来取得其迭代器。对List来说,你也可以通过listIterator()取得其迭代器,两种迭代器在有些时候是不能通用的,Iterator和ListIterator主要区别在以下方面: (1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能 (2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。 (3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。 (4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。 因为ListIterator的这些功能,可以实现对LinkedList等List数据结构的操作。其实,数组对象也可以用迭代器来实现。
线程和进程
线程的特性
线程的状态
多线程并发的实现
线程的创建方式
线程池的使用
Java作用域
final、static、native、等特殊关键字的使用
Java按值传递的过程
重构和重载
抽象类和接口
内部类的使用:匿名内部类、静态内部类等
Java多线程并发、生产者消费者的实现
Java连接数据库的过程
动态代理与静态代理区别 https://blog.csdn.net/ikownyou/article/details/53081426
http://www.cnblogs.com/V1haoge/p/5860749.html
JVM内存管理和存储机制
http://blog.csdn.net/lengyuhong/article/details/5953544
JVM垃圾回收机制,垃圾回收算法
http://jbutton.iteye.com/blog/1569746
JVM加载类过程
http://www.cnblogs.com/sunada2005/p/3577799.html
JVM内存调优
http://www.cnblogs.com/jackyrong/archive/2010/01/21/1653163.html
http://blog.csdn.net/cutesource/article/details/5907418
框架相关
对框架的熟悉:SSH (面试过程中问的很少,像jsp、servlet基本不问)
spring框架组成、AOP、IOC 、用到的设计模式
hibernate运行机制、缓存的使用、最好看看源码
熟悉和了解JavaScript和jQuery
java中IO、NIO
Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
IO流包括字节流和字符流:
字节流:对应抽象类为InputStream(输入流)和 OutputStream(输出流)。 FileInputStream、FileOutputStream
字符流:对应抽象类为Reader(输入流)和Writer(输出流)。BufferedReader、InputStreamReader、 StringReader
java中异常的分类及结构
Java中的异常类,包括内置的异常类以及自定义的异常类,都直接或者间接地继承至java.lang.Throwable类。在java.lang包中,Throwable类有两个直接子类:Error类和Exception类,Error类及其子类描述了java运行时系统的内部错误和资源耗尽错误。出现这样的错误的,除了通知用户,并接尽力使程序安全地终止之外,没有更好的办法。Exception类的层次结构又分为两个分支:一个分支由RuntimeException派生,另外一个分支包含除RuntimeException类之外的异常类。
运行时异常、非运行时异常
运行时异常:RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException、classCastException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
非运行时异常:RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,不处理程序不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常。
动态代理机制
动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。动态代理主要包含以下角色:动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。代理接口 是代理类实现的一个接口。代理实例 是代理类的一个实例。每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。
try catch finally的使用
1. finally 里 始终会被执行到, System.exit(0); 除这种被执行外。
2. 即使try中有return ,也是先执行 return 后面的语句完了之后,不立马return,而是去执行finally中的语句。
3. 当try中与finally里,同时出现return , 则只会返回 finally 中的return 结果。
4. finally中的值不能影响try中 即将返回的结果值。
注意: 若finally中没有return在try或catch中有return,那么在执行return跟着语句之后,会把语句的结果新开辟一内存空间,直接把结果的存放此内存空间中。所以,finally中的值不能影响try或catch中即将return的结果。
静态成员、非静态成员
(1)类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。
(2)在一个类的静态成员中去访问其非静态成员之所以会出错是因为在类的非静态成员不存在的时候类的静态成员就已经存在了,访问一个内存中不存在的东西当然会出错
抽象类遵循的原则:
(1)abstract关键字只能修饰类和方法,不能修饰字段。
(2)抽象类不能被实例化(无法使用new关键字创建对象实例),只能被继承。
(3)抽象类可以包含属性,方法,构造方法,初始化块,内部类,枚举类,和普通类一样,普通方法一定要实现,变量可以初始化、不初始化但不能初始化后在抽象类中重新赋值或操作该变量(只能在子类中改变该变量)。
(4)抽象类中的抽象方法(加了abstract关键字的方法)不能实现。
(5)含有抽象方法的类必须定义成抽象类。
扩展:抽象类和接口的区别:
(1)接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的。
(2)abstractclass 在Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface,实现多重继承。接口还有标识(里面没有任何方法,如Remote接口)和数据共享(里面的变量全是常量)的作用。
(3)在abstractclass 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法默认都是 public abstract 类型的。
(4)abstractclass和interface所反映出的设计理念不同。其实abstractclass表示的是”is-a”关系,interface表示的是”has-a”关系。
(5)实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到具体类实现。抽象类中可以有非抽象方法。接口中则不能有实现方法。
(6)接口中定义的变量默认是publicstatic final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。抽象类中的变量默认是friendly 型,其值可以在子类中重新定义,也可以在子类中重新赋值。