`
dycsos123ok
  • 浏览: 81687 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java面试指南一(2)

阅读更多

第二部分 CoreJava基础(1)

第05章 Java基础知识

5.1“==”与“equals”区别

       解析:这是一个很简单的题,很多人都能答上来“==”通常用来比较地址,而且equals则是比较内容;如果仅仅这样回答,通常面试只能得到60分,可以通过下面的两个例子来看一下。

String s1 = "s";

String s2 ="s" ;

String s3 = new String("s");

String s4 = new String("s");

StringBuffer sb1 = new StringBuffer("s");

StringBuffer sb2 = new StringBuffer("s");

System.out.println(s1==s2) ;

System.out.println(s3==s4) ;

System.out.println(sb1==sb2) ;

System.out.println(s1.equals(s2)) ;

System.out.println(s3.equals(s4))

System.out.println(sb1.equals(sb2)) ;

       读者可以自己判断一下结果;对于s1,s2会指向同一个地址,因为这里的s1会保存在常量池中,s2会先读取常量池,发现里面已经存在”s”了,不会再进行重新开辟空间。对于s3,s4是在堆中分配两块空间,它们的地址是存放在栈中。sb1sb2的内在分配和s3,s4一样,但注意StringBuffer没有重写equal方法,而调用的是Object中的equal方法,看一下源码可以知道Object中的equal的实现return (this == obj)其实就是在比较对象的地址。 

参考答案:“==”对于基本数据类型,通常用来比较值(基本数据类型是在栈中进行分配的)相等,对于对象通常用来比较对象的地址。equalsObject中的方法,可以根据业务需要进行重写,比如String中重写了equals的方法,常用来比较两个字符串内容是否相等。

说明:重写equal的风险也很大的,上面也提到过重写的规则,所以根据需要进行重写。

 

5.2 接口和抽象类的区别

  解析:这是一个很简单的题,面试时一定要想清楚再回答,这样的题答错,估计机会也就失去了。

参考答案:

含有abstract修饰符的class 即为抽象类,abstract类不能创建实例对象,含有abstract的方法的类必须定义为abstract class abstract class 里的方法不必是抽象的,抽象类中定义抽象方法必须放在具体子类中实现,所以,不能有抽象的构造方法或抽象的静态方法,如果子类没有实现抽象父类中的所有方法,那么,子类也必须定义为抽象类。

接口(interface)可以说成是抽象类的特例。接口中的所有方法都必须是抽象的,接口中的方法定义默认为public abstract 。接口中的变量是全局常量,即public static final修饰的。概括如下:

 1、抽象类里可以有构造方法,而接口内不能有构造方法。

 2、抽象类中可以有普通成员变量,而接口中不能有普通成员变量。

 3、抽象类中可以包含非抽象的普通方法,而接口中所有的方法必须是抽象的,不能有非抽象的普通方法。

 4、抽象类中的抽象方法的访问类型可以是public protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

 5、抽象类中可以包含静态方法,接口内不能包含静态方法。

 6、抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static类型,并且默认为public static类型。

 7、一个类可以实现多个接口,但只能继承一个抽象类。

 以上答案网上都是可以找的到的,也很有条理,如果能回答出五条左右就可以满分了。除此外,下面就是加分项了,在设计上接口的作用侧重于模块划分,比如:用户管理接口,信息管理接口,里面都相关用户的增删改查操作。而抽象类则是侧重于功能的划分,比如事先知道需要实现某个功能,但设计时却还没有想到如何实现则先抽象出一个方法,或者把子类中重复实现的功能放到抽象中去实现等。

 

 5.3 运行时异常和一般异常的区别

解析:异常的优点是可以提高程序的健壮性,可读性,可维护性,但异常的设计初衷是用于不正常的情形,一般的JVM是不会试图对它进行优化,所以异常使用不当也会给系统带来负面影响。在谈异常之前,往往还会谈一下Error,它们都是基于Throwable实现;但Error的出现通常是JVM层次无法自动恢复的严重例外,比如JVM内存泄露,一般都会造成系统荡机,所以对于Error进行继承设计的没有意义的。而Exception是可以处理的,合理的使用可以使用系统更健壮。

 

参考答案:运行异常(RuntimeException)和一般异常(CheckedException)都是从Exception继续来的,都是可以捕捉到,可以恢复的例外。

一般异常(CheckedException):是JVM强制让我们处理的异常,在现在通常的开发IDE会提示我们必须用try{}catch(..){}捕捉,常见的文件读写的IO导常,Socket通信时的网络异常,数据操作的JDBC异常等。

运行异常(RuntimeException):JVM不强制我们去捕捉,异常一旦发生,会有JVM接管,一直往上抛,直到遇到异常处理的代码;如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。

异常处理的目的就是使程序从异常中恢复,不会中止线程退出系统,所以对于常的Exception要做一些合理的处理,但由于异常机制比较复杂而且往往得不到JVM的优化,会造成性能下降下,所以异常的使用最好对可能出现的异常位置进行捕捉,最好同时进行异常日志记录,便于系统维护。

5.4 序列化和反序列化

       解析:对于经常接口开发的的来说,序列化这个词一定不会默生,对象本身是不能直接在网络中传输的,传递的都是一些字节流,而将对象转换成字节流的过程就叫做对象的序列化。这个考点的命中率属于一般,一般多出现于后台接口开发相关的职位面试中,但序列化与反序列化的使用却在开发中无处不在,需要深入了解。

 参考答案:

 1、序列化与反序列化的定义:把对象转换为字节序列的过程称为对象的序列化,把字节序列恢复为对象的过程称为对象的反序列化。

 2、对象序列化的作用,比如远程接口调用,对象网络传输;深度克隆时,复杂对象的的复制;缓存对象的硬盘存储;Session的硬盘序列化等。至于反序列化的作用,就是把序列化的对象重新加载到内存中使用。

 3、序列化的实现,首先必须实现Serializable或者Externalizable,而Serializable是超级接口,Externalizable是其实现,Serializable接口中什么也没有定义,它只是对对象生成一个唯一的ID标识,告诉JVM该对象是可以序列化的,如果不实现序列化接口,在序列化的过程中会抛出异常。

 4JavaAPI提供的序列化方式,java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。对于实现了Externalnalizable接口的类,且类必须实现readExternal(ObjectInput in)writeExternal(ObjectOutput out)方法,按照以下方式进行序列化与反序列化。ObjectOutputStream调用该类生成对象的writeExternal(ObjectOutput out))的方法进行序列化。ObjectInputStream会调用对象的readExternal(ObjectInput in)的方法进行反序列化。

扩展:Java实现序列化带来了很多好处,但实际开发中要根据项目类型和业务场景慎重实现,因为实现序列化也会付出一定的“代价”,首先会降低类的灵活性,其实会增加出现BUG和漏洞的可能。

 

5.5  Java实现浅克隆与深克隆

  解析:这个面试命中的概率不算太高,此题目是笔者在某家公司的面试的原题,而笔者之前的工作中研究过克隆的使用,在这里总结一下供大家参考(里面用到序列化的一些知识,参考上面)。

 

参考答案:

所谓的浅克隆,顾名思义就是很表面的很表层的克隆,如果我们要克隆Administrator对象,只需要克隆他自身以及他包含的所有对象的引用地址。而深克隆,就是非浅克隆。克隆除自身以外所有的对象,包括自身所包含的所有对象实例。至于深克隆的层次,由具体的需求决定,也有“N层克隆”一说。但是,所有的基本(primitive)类型数据,无论是浅克隆还是深克隆,都会进行原值克隆。毕竟他们都不是对象,不是存储在堆中。(Java中所有的对象都是保存在堆中,而堆是供全局共享的。也就是说,如果同一个Java程序的不同方法,只要能拿到某个对象的引用,引用者就可以随意的修改对象的内部数据。)

潜克隆实现:1. 让该类实现java.lang.Cloneable接口;2. 重写(overrideObject类的clone()方法。(并且在方法内部调用父对象的clone()方法)。

       对于复杂对象,比如数组、集合通过浅克隆是不能修改对象的引用的,这里要彩用深度克隆,一般是通过序列和反序列的方式来实现浓度克隆:



 
  如上面的代码,对序列化的对象写到内存或者研盘上,然后在需要的地方再从内存或者硬盘上反序列化成对象。

 

 5.6 枚举可以序列化吗

       解析:这个是笔者参加某一个著名的互联网公司的面试题,冷不丁上来这个小问题,如果你平时没太关注,很容易认为是陷阱,大江大河都淌过的人很容易死在小水塘里;而且在两家的互联网开发设计规范中都提到多使用Enum,所以像这样的小知识点平时还是要多留意。

 

参考答案:因为Enum实现了序列化接口Serializable,所以枚举是可以被序列化的。

 

5.7 Java创建对象的方式

       解析:这个没什么深意,面试官多是想了解一下你的知识面,一般人都应该至少能回答出来两种。

 

 

参考答案:

 (1) new语句创建对象,这是最常见的创建对象的方法。

 (2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。

 (3) 调用对象的clone()方法。

 (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

5.8 能否自己定义一个java.lang.String类

  解析:这个是考察面试人员对类加载机制的了解,问题不难,但需要真正了解JVM对类的加载原理,这个在下面JVM相关部分还会详细提及,这里就简答一下。

 

 

参考答案:

一般情况下是不可以的,类的APP加载器会根据双亲代理机制委托父类加载器去加载此类,而在父亲加载器中已经加载过此类(因为java.lang.String类是JVM定义的类),会报该类已经存。处理方法,自定义加载器加载,指定一个其它路径。

5.9 Java线程池的了解

  解析:这里还是多线程考察的延续,在互联网职位、高并发分布式相关的职位中几乎必然会面试多线程题目,而且有资格面试这块的面试官一般都是设计、架构级别的资深人士,难度中偏上,是面试有效筛选题目类型;线程池在jdk1.5之前的版本并不是特别成熟,但在Jdk1.5的版本中作了很大的优化,在jdk1.6的版本中更是引入了java.util.concurrent包,有兴趣的读者可以详细研究一下这个包;而回答此问题可以从线程池的作用、为什么要使用线程池及线程池的优越性、线程池的实现原理和使用等几方面回答。

 

参考答案:

 1、线程池的作用:在没用使用线程池的情况下,开发人员通常自己来开发管理线程,很容易将线程开启过多或者过少;过多将造成系统拥堵,过少又浪费系统资源。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

 2、由于手动维护线程成本很高(大家都知道多线程的开发难度大,对程序员要求高,而且代码不易调试维护),所以我们应尽可能用JDK提供的比较成熟的线程池技术,它减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。可以根据系统的承受能力,调整线程池中工作线线程的数目,以达到系统性能最优。

 3、线程池的父接口是Executor,它只定义了一个Execute方法,而通过使用的是它的扩展接口ExecutorService,它有几个常用的实现类AbstractExecutorService, ScheduledThreadPoolExecutor, ThreadPoolExecutor(详见API)。而在实际开发中,通过使用的是一个java.util.concurrent中的一个工具类Executors,里面提供了一些静态工厂,生成常用的线程池(下面这些作为了解,说出一两个就可以了)

i. newSingleThreadExecutor

创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

ii.newFixedThreadPool

创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

iii. newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,

那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

iv.newScheduledThreadPool

创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

5.10 Return和finally语句块的顺序

       解析:这个面试题就是考查基本功的,而且出现频率较高,面试官大部分也不会深问,但希望读者关注一下拓展中的问题,在面试笔试中都有很高的命中率。

参考答案:Finally是在return语句之前被执行的,但是finallyreturn是相互独立的;return语句位置会影响到返回值的结果,finally中的计算将影响到其后return结果,不会影响到try里面return的结果。

  扩展:Finally做为try{}catch(..){}finally{}一部分,如果finally删掉可以吗?catch()删掉呢?只留try{}可以吗?try{}finally{}连用呢?请诸位试一下,这里也是一个考点,这里就不详细说明了。

5.11 Java静态变量与实例变量的区别

  解析:这个属于java面向对象中语法级别的考查,是一种基本的面试题,也是不容许失分的题目。

  参考答案:Java成员变量中静态变量用static修饰,而没有static修饰的变量称为实例变量。

 Java静态变量也叫类变量,在类加载时被分配空间(从java内存分配上可以知道,它是存放在静态域中),由于它是属于类的,为所有实例共享,它的特性是一改全改(任何一个实例中修改了这个属性,其它实例都能看到修改的结果),调用方式通过类名.变量名。

 Java实例变量属于对象的,在对象被实例化的时候(new的时候)分配空间,每个实例化的对象都有一套自己的实例变量,调用方法通常通过生成的set/get方法,或者通过this.实例变量名。

 

 

5.12 同步与异步区别及使用场景

  解析:同步一定是发生在多线程条件下,对共同资源不安全的访问进行控制一种手段;异步是要求减少请求方时间的等待。

 

  参考答案:如果数据将在线程间共享.例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效。

 使用场景:同步,最简单最常见的就是火车票销售,不可能多个窗口下允许出现卖两张完全一样的票。异步,在注册页面,当我们写其它信息时,我希望后台已经完成了对我姓名是否重复的验证,而不是我完全写完提交后再去验证。

5.13 Java堆和栈的区别

       解析:要想详细了解堆和栈的区别,就要了解JavaVM的内存分配机制,一般会涉及以下几个区域寄存器、堆、栈、静态域、常量池、非RAM存储(这些概念性的东西,理解就好),静态域主要是存放一些static静态成员、常量池存放常量,下面主要说一下堆、栈。

 

 参考答案:栈与堆都是Java用来在Ram中存放数据的地方,与CC++不同Java自动管理栈和堆,程序员不能直接地设置栈或堆。

  栈中存放局部变量(基本类型的变量)和对象的引用地址。栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性;栈是跟随线程的,有线程就有栈

  堆中存放对象,包括对象变量以及对象方法(大学时老师可能都讲过一个类似的笑话,一New一堆,说的就是堆是用来存放对象的)。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。堆是跟随JVM的,有JVM就有堆内存

5.14 Java多线程快速问答

   解析:多线程中有很多知识点,面试经常问到,而且会被连续问到,这里简单介绍一下。

 

 1Java实现多线程的方式有哪些?

  答:Java实现多线程的方式通常有实现Runnable接口,或者继承Thread类,或者从线程ExecutorService中获取。

 2、你通常用哪种方式来实现线程,为什么?

 答:通常使用实现Runnable接口或者从线程池中来获得线程;实现接口是因为接口是支持多实现,我们知道一个类只能有一个父类,但是却能实现多个接口,因此Runnable具有更好的扩展性,而且Thread也是实现了Runnable接口,所以推荐通过接口实现来实现线程。另一种方式就是从线程池中获取线程,优点是将线程交给线程池去管理,可以减轻大量的精力去维持线程状态的管理,而且手动干预的越多,后期的维护成本越高。

3run()start()哪个是线程的启动方法?

  答:run()方法,在实现一个线程类时必须重写的方法,但它本身只是一个普通的方法,如果通过对象.run()去调用,它只是一个属于调用线程中的普通方法,可以调用多次,而且是按顺序执行。而start()方法是线程的启动方法,当他把调用时,线程的状态就变成了就绪,一旦获取了时间片,就会立刻执行(执行run()方法,这里的run是线程体,执行完成表示线程执行结束)。

 4、多线程状态有哪些?

答:Java线程有五种状态创建、就绪、运行、阻塞和死亡。创建:可以理解我们new了一线程对象;就绪:new的线程对象调用了start()方法,但并没有立即抢到CPU时间片;运行:线程启动后,线程体run方法在执行;阻塞:阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才会有机会获得运行状态;死亡:当线程执行完run()方法中的代码或者调用了stop()方法,又或者遇到了未捕获的异常,就会退出run()方法,此时就进入死亡状态,该线程结束生命周期。

 5、多线程的同步方法有哪些?

答:wait():使一个线程处于等待状态,并且释放所持有的对象的locksleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。notifyAll():唤醒所有处入等待状态的线程。

实现线程同步一个是synchronized关键字,一个是通过对象Lock

 6、你了解死锁吗(如果是笔试可能让你写一段死锁代码)?

  答:死锁可以这样认为:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放(例如有a,b两个线程,a等待b让出了某个资源才可以执行;而b同样等待a让出了某个资源才可以继续,ab都在等待对方就是线程同时阻塞,结局就是死锁)。

7、当一个线程进入到一个对象的synchronized方法,那么其他线程是否可以进入该对象的其它方法?

答:当一个线程进入到一个对象的synchronized方法,那么其他线程是可以进入这个对象的非synchronized方法,但不可能进入synchronized方法

  扩展:多线程面试是Java面试中不可缺少的一部分,也是属于面试中的难点,绝对是面试中的淘汰型问题,需要多花点时间准备。

 

 

分享到:
评论

相关推荐

    2015Java面试指南

    2015J最新Java面试指南,邀请你一起挑战Java高薪

    Java面试小抄面试指南

    「Java面试指南」一份通向理想互联网公司的面试指南,包括 Java基础、Java并发、JVM、MySQL、Redis、Spring、MyBatis、Kafka、计算机操作系统、计算机网络、系统设计、分布式、Java 项目实战等

    Java面试指南.pdf

    Java面试指南,里面包含大厂的的一些面试题,让面试的你不再发愁,面试题很有帮助,很有用,希望大家可以踊跃下载。

    Java程序员面试指南

    资源名称:Java程序员面试指南内容简介:本书涵盖了Java面试中会经常出现的问题,并指导读者快速、巧妙地解决问题。全书共分18章,内容涵盖了面试前必须要知道的几件事、Java程序基础、Java语言中的符号、数据类型及...

    java程序员面试指南(代码

    java程序员面试指南(代码 java程序员面试指南(代码 java程序员面试指南(代码 java程序员面试指南(代码 java程序员面试指南(代码

    Java面试指南

    本指南适用于应聘初级、中级、中高级职位,有一定的Java基础,想换...笔者及其好友前前后后面试20多家公司,OFFER通过率达到80%,通过不断的总结分析完成了《Java求职面试指南》的第一版本,希望对大家有一定参考作用。

    java面试指南

    java面试指南,适合高中级面试,他人总结,用于共享

    “java高分面试指南”-25分类227页1000+题50w+字解析.pdf

    “java高分面试指南”-25分类227页1000+题50w+字解析.pdf

    「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识

    「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,首选 JavaGuide!「「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,首选 ...

    这里是一整套的java面试指南

    来这里,最详细全面的java面试指南 提升自己,打铁还需自身硬。这里是一套非常完整的java面试指南,对标阿里P6P7,备好八股面试全有,实力是最重要的考核标准,有能力还怕啥 此处不留我自由留我处,加油吧 加油同学...

    JAVA程序员面试指南

     第二篇(第2章~第13章)介绍了Java程序员涉及的基础知识,内容包括Java语言基础、异常的处理、I/O控制流、面向对象编程、线程、集合以及数据库技术等基本知识点。  第三篇(第14章~第16章)专门介绍了Java开发...

    Java面试准备指南 Java面试准备指南

    Java面试准备指南

    10万字总结java面试题和答案(八股文之一)Java面试题指南

    JavaOOP面试题 Java集合/泛型面试题 Java异常面试题 Java中的IO与NIO面试题 Java反射面试题 Java序列化面试题 Java注解面试题 多线程&并发面试题 JVM面试题 Mysql面试题 Redis面试题 Memcached面试题 MongoDB面试题 ...

    电子书《JAVA程序员面试指南》

    从淘宝上买的《JAVA程序员面试指南》电子书清晰版,贡献给大家。

    Java面试准备指南_PDF

    Java面试准备指南, 跳槽必看,Java程序员面试中你需要注重的技巧

    Java热门面试题、Java面试指南

    我们的Java面试资料是专门为Java开发者准备的全面指南,旨在帮助您在面试过程中脱颖而出,展示您的技术能力和经验。以下是我们Java面试资料的亮点和好处: 全面而深入的覆盖:我们的Java面试资料涵盖了Java编程语言...

    Java学习面试指南干货分享.txt

    Java最详细的帮你复习面试指南 回顾所有的Java知识 +笔记 +面试指南+简历帮助 全都是干货

    java常见面试题指南.pdf

    java常见面试题指南

Global site tag (gtag.js) - Google Analytics