高级Java开发面试常用题的答案(一)

一、数据结构与算法基础
· 说一下几种常见的排序算法和分别的复杂度。
· 用Java写一个冒泡排序算法
/**现在有一个包含1000个数的数组,仅前面100个无序,后面900个都已排好序且都大于前面100个数字,那么在第一趟遍历后,最后发生交换的位置必定小于100,且这个位置之后的数据必定已经有序了,也就是这个位置以后的数据不需要再排序了,于是记录下这位置,第二次只需从数组头部遍历到这个位置即可以了。假如是对于上面的冒泡排序算法2来说,尽管也只排序100次,但是前面的100次排序每次都要对后面的900个数据进行比较,而对于现在的排序算法3,只要要有一次比较后面的900个数据,之后就会设置尾边界,保证后面的900个数据不再被排序。*/
public static void bubbleSort(int [] a, int n){
int j , k; int flag = n ;
//flag来记录最后交换的位置,也就是排序的尾边界
while (flag > 0){
//排序未结束标志
k = flag; //k 来记录遍历的尾边界
flag = 0;
for(j=1; j<k; j++){
if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
//交换a[j-1]和a[j]
int temp;
temp = a[j-1];
a[j-1] = a[j];
a[j]=temp;
//表示交换过数据;
flag = j;//记录最新的尾边界.
}
}
}}

· 形容一下链式存储结构。
它不要求逻辑上相邻的元素在物理位置上也相邻。因而它没有顺序存储结构所具备的弱点,同时也失去了顺序表可随机存取的优点。
其特点主要体现为:
1、比顺序存储结构的存储密度小;
2、插入、删除灵活,结点可以被插入到链表的任何位置,首、中、末都可以,而且不必要移动结点中的指针;
3、链表的大小可以按需伸缩,是一种动态存储结构,其实现的集合在增、删方面性能更高;
4、查找结点时的效率就相对数组较低,只能从第一个结点开始顺着链表一一查找(这是他的缺点)。

· 如何遍历一棵二叉树?
二叉树的遍历分为三种:
前序遍历:按照“根左右”,先遍历根节点,再遍历左子树 ,再遍历右子树
中序遍历:按照“左根右“,先遍历左子树,再遍历根节点,最后遍历右子树
后续遍历:按照“左右根”,先遍历左子树,再遍历右子树,最后遍历根节点
其中前,后,中指的是每次遍历时候的根节点被遍历的顺序

package com.tree;import java.util.ArrayList;import java.util.List;public class Tree {
private Node root;
private List list=new ArrayList();
public Tree(){
init(); }
//树的初始化:先从叶节点开始,由叶到根
public void init(){
Node x=new Node(“X”,null,null);
Node y=new Node(“Y”,null,null);
Node d=new Node(“d”,x,y);
Node e=new Node(“e”,null,null);
Node f=new Node(“f”,null,null);
Node c=new Node(“c”,e,f);
Node b=new Node(“b”,d,null);
Node a=new Node(“a”,b,c);
root =a;
}
//定义节点类:
private class Node{
private String data;
private Node lchid;
//定义指向左子树的指针
private Node rchild;
//定义指向右子树的指针
public Node(String data,Node lchild,Node rchild){
this.data=data;
this.lchid=lchild;
this.rchild=rchild;
}
}
/** * 对该二叉树进行前序遍历 结果存储到list中 前序遍历:ABDXYCEF /
public void preOrder(Node node)
{
list.add(node); //先将根节点存入list
//假如左子树不为空继续往左找,在递归调用方法的时候一直会将子树的根存入list,这就做到了先遍历根节点
if(node.lchid != null)
{
preOrder(node.lchid);
}
//无论走到哪一层,只需当前节点左子树为空,那么即可以在右子树上遍历,保证了根左右的遍历顺序
if(node.rchild != null)
{
preOrder(node.rchild);
}
}
/
* * 对该二叉树进行中序遍历 结果存储到list中 /
public void inOrder(Node node)
{
if(node.lchid!=null){
inOrder(node.lchid);
}
list.add(node);
if(node.rchild!=null){
inOrder(node.rchild);
}
}
/
* * 对该二叉树进行后序遍历 结果存储到list中 /
public void postOrder(Node node)
{
if(node.lchid!=null){
postOrder(node.lchid);
}
if(node.rchild!=null){
postOrder(node.rchild);
}
list.add(node);
}
/
* * 返回当前数的深度 * 说明:

  • 1、假如一棵树只有一个结点,它的深度为1。
  • 2、假如根结点只有左子树而没有右子树,那么树的深度是其左子树的深度加1;
  • 3、假如根结点只有右子树而没有左子树,那么树的深度应该是其右子树的深度加1;
  • 4、假如既有右子树又有左子树,那该树的深度就是其左、右子树深度的较大值再加1。 *
  • @return */
    public int getTreeDepth(Node node) {
    if(node.lchid == null && node.rchild == null)
    {
    return 1;
    }
    int left=0,right = 0;
    if(node.lchid!=null)
    {
    left = getTreeDepth(node.lchid);
    }
    if(node.rchild!=null)
    {
    right = getTreeDepth(node.rchild);
    }
    return left>right?left+1:right+1;
    }
    //得到遍历结果
    public List getResult()
    {
    return list; }
    public static void main(String[] args)
    {
    Tree tree=new Tree();
    System.out.println(“根节点是:”+tree.root);
    //tree.preOrder(tree.root);
    tree.postOrder(tree.root);
    for(Node node:tree.getResult()){
    System.out.println(node.data);
    }
    System.out.println(“树的深度是”+tree.getTreeDepth(tree.root));
    }
    }
    二叉树与一般树的区别

一般树的子树不分次序,而二叉树的子树有左右之分.
因为二叉树也是树的一种,所以大部分的树的概念,对二叉树也适用.
二叉树的存贮:每个节点只要要两个指针域(左节点,右节点),有的为了操作简单也会 添加指向父级节点的指针,除了指针域以外,还会有一个数据域用来保存当前节点的信息
二叉树的特点:

性质1:在二叉树的第i层上至多有2^(i-1)个节点(i >= 1)
性质2:深度为k的二叉树至多有2^k-1个节点(k >=1)
性质3:对于任意一棵二叉树T而言,其叶子节点数目为N0,度为2的节点数目为N2,则有N0 = N2 + 1。
性质4:具备n个节点的完全二叉树的深度。
· 倒排一个LinkedList。
根据LinkedList的实现,LinkedList的底层是双向链表,它在get任何一个位置的数据的时候,都会把前面的数据走一遍。用迭代器或者者foreach循环(foreach循环的原理就是迭代器)去遍历LinkedList就可,这种方式是直接按照地址去找数据的,将会大大提升遍历LinkedList的效率。

public static LinkedList reverse(LinkedList linkedList){
if (linkedList == null) return linkedList;
LinkedList temp_linkedlist = new LinkedList();
for (T item: linkedList)
{
temp_linkedlist.addLast(item);
}
return temp_linkedlist;}

· 用Java写一个遍历目录下面的所有文件。
public static void foreachFileList(String filePath) throws IOException {
LinkedList linkedList = new LinkedList();
File file = new File(filePath);
if (file.exists())
{
linkedList.add(file);
while (true) {
file = linkedList.poll();
if (file == null) break;
File[] fileList = file.listFiles();
for (File fileItem : fileList) {
if (fileItem.isDirectory()) {
linkedList.add(fileItem);
continue;//for
}
if (fileItem.isFile())
System.out.println(fileItem.getCanonicalPath());
}
}
}}

二、Java基础
· 接口与笼统类的区别?
一个类可以实现多个接口,但只能继承最多一个笼统类
笼统类可以包含具体的方法;接口所有的方法都是笼统的(不论能否对接口公告都是笼统的)(jdk1.7以前,jdk1.8开始新添加功能接口中有default 方法,有兴趣自己研究)
笼统类可以公告和使用字段;接口则不能,但是可以创立静态的final常量
笼统类中的方法可以是public、protected、private或者者默认的package;接口的方法都是public(不论能否公告,接口都是公开的)
笼统类可以定义构造函数,接口不能。
接口被公告为public,省略后,包外的类不能访问接口
· Java中的异常有哪几类?分别怎样使用?
Throwable包含了错误(Error)和异常(Excetion两类)
Exception又包含了 运行时异常(RuntimeException, 又叫非检查异常) 和 非运行时异常(又叫检查异常)
(1) Error是程序无法解决了, 假如OutOfMemoryError、OutOfMemoryError等等, 这些异常发生时, java虚拟机一般会终止线程 .
-(2) 运行时异常都是RuntimeException类及其子类,如 NullPointerException、IndexOutOfBoundsException等, 这些异常是不检查的异常, 是在程序运行的时候可能会发生的, 所以程序可以捕捉, 也可以不捕捉. 这些错误一般是由程序的逻辑错误引起的, 程序应该从逻辑角度去尽量避免.
(3) 检查异常是运行时异常以外的异常, 也是Exception及其子类, 这些异常从程序的角度来说是必需经过捕捉检查解决的, 否则不能通过编译. 如IOException、SQLException等
· 常用的集合类有哪些?比方List如何排序?
常用的集合分为List(有序排放)、Map(以名和值逐个对应的存放)、Set(既无序也没名).在这三者之中其中List和Set是Collection接口的子接口,而Map不是Collection接口的子接口.

List常用有:ArrayList和LinkedList,Vecotr(线程安全)
Set常用有: TreeSet, HashSet 元素不可重复,内部结构用HashMap,Key为Set的item值,value为一个固定的常量。java.util.Collections.newHashSetFromMap(),内部其实质还是通过ConcurrentHashMap实现线程安全的。
Map: TreeMap和LinkedHashMap,HashMap,HashTable(线程安全)
sort()方法排序的本质其实也是借助Comparable接口和Comparator接口的实现,一般有2种用法:

直接将需要排序的list作为参数传入,此时list中的对象必需实现了Comparable接口,而后sort会按升序的形式对元素进行排序;
传入list作为第一个参数,同时追加一个Comparator的实现类作为第二个参数,而后sort方法会根据Comparator接口的实现类的逻辑,按升序进行排序;
· ArrayList和LinkedList内部的实现大致是怎么的?他们之间的区别和优缺点?
Linkedlist集合的优势:增加元素时可以指定位置,比ArrayList集合增加元素要快很多。
Linkedlist在get很慢,LinkedList在get任何一个位置的数据的时候,都会把前面的数据走一遍。尽量不使用,而使用foreach LinkedList的方式来直接获得数据。
这两种方式各有优缺,为更好的使用可以将这两者进行联合使用,使用Linkedlist集合进行存储和增加元素,使用Arraylist集合进行get获取元素。
· 内存溢出是怎样回事?请举一个例子?
内存溢出(out of memory)浅显了解就是内存不够,在计算机程序中浅显的了解就是开拓的内存空间得不到释放。
OOM有堆溢出,栈溢出,方法区溢出(主要是动态生成class的解决过多)
· 和equals的区别?
号在比较基本数据类型时比较的是值,而用号比较两个对象时比较的是两个对象的地址值
Object类中equals()方法底层依赖的是
号,那么,在所有没有重写equals()方法的类中,调用equals()方法其实和使用==号的效果一样,然而,Java提供的所有类中,绝大多数类都重写了equals()方法,重写后的equals()方法一般都是比较两个对象的值
· hashCode方法的作用?
hashCode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用来在散列存储结构中确定对象的存储地址的;
假如两个对象相同,就是适用于equals(Java.lang.Object) 方法,那么这两个对象的hashCode肯定要相同;
假如对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,肯定要和equals方法中使用的一致,否则就会违背上面提到的第2点;
两个对象的hashCode相同,并不肯定表示两个对象就相同,也就是不肯定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”。
· NIO是什么?适用于何种场景?
JDK引入了一种基于通道和缓冲区的 I/O 方式,它可以使用 Native 函数库直接分配堆外内存,而后通过一个存储在 Java 堆的 DirectByteBuffer 对象作为这块内存的引用进行操作,避免了在 Java 堆和 Native 堆中来回复制数据。
NIO 是一种同步非阻塞的 IO 模型。同步是指线程不断轮询 IO 事件能否就绪,非阻塞是指线程在等待 IO 的时候,可以同时做其余任务。同步的核心就是 Selector,Selector 代替了线程本身轮询 IO 事件,避免了阻塞同时减少了不必要的线程消耗;非阻塞的核心就是通道和缓冲区,当 IO 事件就绪时,可以通过写道缓冲区,保证 IO 的成功,而无需线程阻塞式地等待。
· HashMap实现原理,如何保证HashMap的线程安全?
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。HashMap底层就是一个数组结构,数组中的每一项又是一个链表。

=使用 java.util.Hashtable 类,此类是线程安全的。Hashtable是通过每个方法用synchronized来解决,性能不及ConcurrentHashMap
使用 java.util.concurrent.ConcurrentHashMap,此类是线程安全的。采用了分段锁实现同步。
使用 java.util.Collections.synchronizedMap() 方法包装 HashMap object,得到线程安全的Map,并在此Map上进行操作。
· JVM内存结构,为什么需要GC?
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存,简化代码开发。

· NIO模型,select/epoll的区别,多路复用的原理
(过长,没有答复)

· Java中一个字符占多少个字节,扩展再问int, long, double占多少字节
Java char: utf-16:2个字节, int-4, long-8,double-9

· 创立一个类的实例都有哪些办法?
关键字 new。工厂模式是对这种方式的包装;
类实现克隆接口,克隆一个实例。原型模式是一个应用实例;
用该类的加载器,newinstance。java的反射,反射使用实例:Spring的依赖注入、切面编程中动态代理商等获得
通过IO流反序列化读取一个类,取得实例。
· final/finally/finalize的区别?
final:假如一个类被final修饰,意味着该类不能派生出新的子类,不能作为父类被继承。因而一个类不能被公告为abstract,又被公告为final。将变量或者方法公告为final。可以保证他们在使用的时候不被改变。其初始化可以在两个地方:一是其定义的地方,也就是在final变量在定义的时候就对其赋值;二是在构造函数中。这两个地方只能选其中的一个。被公告为final的方法也只能使用,不能重写。
finally:在异常解决的时候,提供finally块在成功或者失败都可以执行任何的清理操作。
finalize:finalize是方法名,java技术允许使用finalize()方法在垃圾收集器将对象从内存中清理出去之前做必要的清除工作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的,可以从Object.finalize()继承下来。
· Session/Cookie的区别?
cookie是用户端的会话状态的一种储存机制。一般限制4k以内。session是一种服务器端的信息管理机制。
session产生的session_id放在cookie里面,假如客户把cookie禁止掉,可以通过在url中保留session_id
· String/StringBuffer/StringBuilder的区别,扩展再问他们的实现?
StringBuilder:线程非安全的,StringBuffer:线程安全的,三者在执行速度方面的比较:StringBuilder > StringBuffer > String

· Servlet的生命周期?
Servlet 通过调用 init () 方法进行初始化。
Servlet 调用 service() 方法来解决用户端的请求。
Servlet 通过调用 destroy() 方法终止(结束)。
最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
· 如何用Java分配一段连续的1G的内存空间?需要注意些什么?
使用ArrayList来分配,注意堆内存不足造面OOM

· Java有自己的内存回收机制,但为什么还存在内存泄漏的问题呢?
主要是没有释放对象引用造成的内存泄漏,比方下例:

class MyList{ /* * 此处只为掩饰效果,并没有进行封装之类的操作 * 将List集合用关键字 static 公告,这时这个集合将不属于任MyList 对象,而是一个类成员变量 */
public static List list = new ArrayList();}
class Demo{
public static void main(String[] args)
{
MyList list = new MyList();
list.list.add(“123456”);
// 此时即使我们将 list指向null,依然存在内存泄漏,由于MyList中的list是静态的,它属于类所有而不属于任何特定的实例
list = null;
}
}

· 什么是java序列化,如何实现java序列化?(写一个实例)?
序列化就是一种用来解决对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。Java的序列化需要实现Serializable接口。看到这里的都是妥妥的铁粉无疑了,底下是我的个人微信找到我的可是有大把源码,学习路线啥的,多的我就不透露,1253431195看大家自己的积极性了啊~

//序列化后生成指定文件路径 File file = new File(“D:” + File.separator + “person.ser”) ;
ObjectOutputStream oos = null ;//装饰流(流)oos = new ObjectOutputStream(new FileOutputStream(file)) ;
//实例化类 Person per = new Person(“张三”,30) ;oos.writeObject(per) ;
//把类对象序列化oos.close() ;

· String s = new String(“abc”);创立了几个 String Object?
两个对象,一个是“abc”对象,在常量池中创立;一个是new关键字创立的s对象指向“abc”。
互联网一线大厂面试题库

百度篇:链接:https://pan.baidu.com/s/140KuFVKGWcV6E6n52MdNXQ
提取码:b0p5

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当涉及到Java高级开发面试题时,以下是些常见的问答案: 1. 什么是Java的反射机制? Java的反射机制允许程序在运行时动态地获取类的信息并操作类的成员。通过反射,可以在运行时创建对象、调用方法、访问字段等。 2. 什么是Java的泛型? Java的泛型是一种参数化类型的概念,它允许在编译时指定类或方法可以操作的数据类型,提高代码的重用性和类型安全性。 3. 什么是Java的注解? Java的注解是一种元数据,它可以用于给程序中的代码添加额外的信息。注解可以用于编译时进行静态检查、运行时进行动态处理,或者生成额外的代码。 4. 什么是Java的多线程? Java的多线程是指在一个程序中同时执行多个线程,每个线程都有自己的执行路径。多线程可以提高程序的并发性和响应性。 5. 什么是Java的异常处理机制? Java的异常处理机制允许程序在出现错误或异常情况时进行处理,以保证程序的正常执行。通过try-catch语句块,可以捕获并处理异常,避免程序崩溃。 6. 什么是Java的IO流? Java的IO流是用于处理输入和输出的机制。它提供了一组类和接口,用于读取和写入数据。IO流可以用于文件操作、网络通信等。 7. 什么是Java的集合框架? Java的集合框架是一组用于存储和操作数据的类和接口。它提供了各种数据结构,如列表、集合、映射等,以及对这些数据结构进行操作的方法。 8. 什么是Java的设计模式? Java的设计模式是一套被广泛应用于软件开发中的解决问的经验总结。它提供了一些常见的设计思想和模式,如单例模式、工厂模式、观察者模式等。 9. 什么是Java的JVM? Java的JVM(Java Virtual Machine)是Java虚拟机的缩写,它是Java程序运行的环境。JVM负责将Java字节码转换为机器码,并提供内存管理、垃圾回收等功能。 10. 什么是Java的并发编程? Java的并发编程是指在多线程环境下编写程序,以实现并发执行和共享资源的安全访问。Java提供了一些并发编程的工具和类,如锁、条件变量、线程池等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值