华为Java工程师面经相关问题个人见解

  1. 简单说说面向对象的特征以及六大原则
  2. 谈谈final、finally、finalize的区别
  3. Java中==、equals与hashCode的区别和联系
  4. 谈谈Java容器ArrayList、LinkedList、HashMap、HashSet的理解,以及应用场景
  5. 谈谈线程的基本状态,其中的wait() sleep()  yield()方法的区别。 

  1. JVM性能调优的监控工具了解那些?
  2. 简单谈谈JVM内存模型,以及volatile关键字
  3. 垃圾收集器与内存分配策略
  4. 垃圾收集算法
  5. MySQL几种常用的存储引擎区别
  6. 数据库的隔离级别 
5亿整数的大文件,怎么排? 

个人见解:

面向对象三个基本特征:
  • 封装:把客观的事务根据其一些共同特点,封装一个“类”别,并且类可以把自己的数据和方法让可信的对象操作,对不可信的对象隐藏,提高重用性和安全性。
  • 继承:无需改变某类的原有内部数据,而通过继承子类的方式对功能进行扩展。
  • 多态:同一个接口使用不同的实现,是基于继承、重写的基础上,通过父类的引用指向子类的实现。
六大原则:
  1. 单一职责,一个类只负责单一的封装
  2. 开放封闭原则,功能升级尽可能扩展子类的方式,不可修改原类
  3. 里氏替换原则,使用基类模块无需修改,子类型必能替换掉基类(实际和上面的开放封闭原则是一回事)
  4. 依赖倒置原则,依赖抽象、接口等,避免依赖于细节
  5. 接口隔离原则,单一职责用于接口设计,客户程序发生变化,影响到其他程序的可能性小
  6. 良性依赖原则,(说实话我对着文绉绉的术语没多少兴趣,不清出怎么个具体解释法)

final

  • 修饰类,该类不能被继承,没有子类,final类中的方法默认是final的
  • 修饰方法,该方法不能被覆盖,但可以被子类继承
  • 修饰成员变量,只能赋值一次,且值不会改变

finally

异常处理的一个关键字,try...catch...finally

finalize

方法名,Object类的方法,finalize()方法在垃圾收集器将对象从内存清理出去之前必要的清理工作。

==

  • 若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的值是否相等
  • 若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同。

equals

Object 的 实例方法,比较两个对象的content是否相同

hashCode

Object 的 native方法 , 获取对象的哈希值,用于确定该对象在哈希表中的索引位置

ArrayList

继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。新增、删除元素时ArrayList需要使用到拷贝原数组

LinkedList

实现List接口与Deque接口双向链表,实现了列表的所有操作,并且允许包括null值的所有元素。LinkedList内部实现是双向链表结构新增、删除元素时LinkedList只需移动指针,查找元素 ArrayList支持随机元素访问,而LinkedList只能一个节点的去遍历

HashMap

基于哈希表的 Map 接口的实现,以 Key-Value 的形式存在,即存储的对象是 Entry (同时包含了 Key 和 Value) 。根据hash算法来计算key-value的存储位置并进行快速存取,最多只允许一条Entry的键为Null(多条会覆盖),但允许多条Entry的值为Null。

HashSet

 HashSet 而言,其采用 Hash 算法决定元素在Set中的存储位置,这样可以保证元素的快速存取。HashSet 底层采用 HashMap 来保存所有元素

线程

线程是指进程中的一个执行流程,一个进程中可以运行多个线程。
一种是继承Thread类,另外一种是实现Runable接口.(其实准确来讲,应该有三种,还有一种是实现Callable接口,并与Future、线程池结合使用很少用
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。

基本状态以下几种:

新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

sleep(long millis)  指定毫秒内当前线程休眠
join()  主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到子线程的join()方法了。
yield() 暂停当前正在执行的线程对象,并执行其他线程。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。
wait() 必须在synchronized(Obj){...}语句块内。从功能上来说wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。直到有其它线程调用对象的notify()唤醒该线程,才能继续获取对象锁,并继续执行。


常见的JVM性能调优工具
  • jps   java virtual machine process status tool    用来输出jvm中运行的进程状态信息  jps [参数] [ip]  
  • jstack  jstack主要用来查看某个Java进程内的线程堆栈信息。语法格式如下:jstack [参数] pid/executable core       jstack可以定位到线程堆栈,根据堆栈信息我们可以定位到具体代码
  • jmap     memary map用来查看堆内存使用情况    jmap [option] pid      jmap -heap pid查看进程堆内存使用情况,包括使用的GC算法、堆配置参数和各代中堆内存使用情况。
  • jhat   用jmap把进程内存使用情况dump到文件中,再用jhat分析查看。  jmap -dump:format=b,file=dumpFileName pid
  • hprof   hprof能够展现CPU使用率,统计堆内存使用情况。java -agentlib:hprof[=options] ToBeProfiledClass
Java内存模型:

垃圾收集器:

下图展示了7种作用于不同分代的收集器,其中用于回收新生代的收集器包括Serial、PraNew、Parallel Scavenge,回收老年代的收集器包括Serial Old、Parallel Old、CMS,还有用于回收整个Java堆的G1收集器。
不同收集器之间的连线表示它们可以搭配使用。

内存的分配与回收策略



全部评论

相关推荐

评论
2
10
分享
牛客网
牛客企业服务