第二部分 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是在堆中分配两块空间,它们的地址是存放在栈中。sb1与sb2的内在分配和s3,s4一样,但注意StringBuffer没有重写equal方法,而调用的是Object中的equal方法,看一下源码可以知道Object中的equal的实现return (this == obj)其实就是在比较对象的地址。
参考答案:“==”对于基本数据类型,通常用来比较值(基本数据类型是在栈中进行分配的)相等,对于对象通常用来比较对象的地址。equals是Object中的方法,可以根据业务需要进行重写,比如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该对象是可以序列化的,如果不实现序列化接口,在序列化的过程中会抛出异常。 4、JavaAPI提供的序列化方式,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. 重写(override)Object类的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语句之前被执行的,但是finally与return是相互独立的;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中存放数据的地方,与C和C++不同Java自动管理栈和堆,程序员不能直接地设置栈或堆。 栈中存放局部变量(基本类型的变量)和对象的引用地址。栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性;栈是跟随线程的,有线程就有栈。 堆中存放对象,包括对象变量以及对象方法(大学时老师可能都讲过一个类似的笑话,一New一堆,说的就是堆是用来存放对象的)。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。堆是跟随JVM的,有JVM就有堆内存。 |
5.14 Java多线程快速问答
解析:多线程中有很多知识点,面试经常问到,而且会被连续问到,这里简单介绍一下。
1、Java实现多线程的方式有哪些? 答:Java实现多线程的方式通常有实现Runnable接口,或者继承Thread类,或者从线程ExecutorService中获取。 2、你通常用哪种方式来实现线程,为什么? 答:通常使用实现Runnable接口或者从线程池中来获得线程;实现接口是因为接口是支持多实现,我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性,而且Thread也是实现了Runnable接口,所以推荐通过接口实现来实现线程。另一种方式就是从线程池中获取线程,优点是将线程交给线程池去管理,可以减轻大量的精力去维持线程状态的管理,而且手动干预的越多,后期的维护成本越高。 3、run()和start()哪个是线程的启动方法? 答:run()方法,在实现一个线程类时必须重写的方法,但它本身只是一个普通的方法,如果通过对象.run()去调用,它只是一个属于调用线程中的普通方法,可以调用多次,而且是按顺序执行。而start()方法是线程的启动方法,当他把调用时,线程的状态就变成了就绪,一旦获取了时间片,就会立刻执行(执行run()方法,这里的run是线程体,执行完成表示线程执行结束)。 4、多线程状态有哪些? 答:Java线程有五种状态创建、就绪、运行、阻塞和死亡。创建:可以理解我们new了一线程对象;就绪:new的线程对象调用了start()方法,但并没有立即抢到CPU时间片;运行:线程启动后,线程体run方法在执行;阻塞:阻塞状态是指线程因为某些原因放弃CPU,暂时停止运行。当线程处于阻塞状态时,Java虚拟机不会给线程分配CPU,直到线程重新进入就绪状态,它才会有机会获得运行状态;死亡:当线程执行完run()方法中的代码或者调用了stop()方法,又或者遇到了未捕获的异常,就会退出run()方法,此时就进入死亡状态,该线程结束生命周期。 5、多线程的同步方法有哪些? 答:wait():使一个线程处于等待状态,并且释放所持有的对象的lock。sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。notifyAll():唤醒所有处入等待状态的线程。 实现线程同步一个是synchronized关键字,一个是通过对象Lock。 6、你了解死锁吗(如果是笔试可能让你写一段死锁代码)? 答:死锁可以这样认为:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放(例如有a,b两个线程,a等待b让出了某个资源才可以执行;而b同样等待a让出了某个资源才可以继续,ab都在等待对方就是线程同时阻塞,结局就是死锁)。 7、当一个线程进入到一个对象的synchronized方法,那么其他线程是否可以进入该对象的其它方法? 答:当一个线程进入到一个对象的synchronized方法,那么其他线程是可以进入这个对象的非synchronized方法,但不可能进入synchronized方法 |
扩展:多线程面试是Java面试中不可缺少的一部分,也是属于面试中的难点,绝对是面试中的淘汰型问题,需要多花点时间准备。
相关推荐
### 2015Java面试指南知识点概览 #### 一、应聘求职 - **简历篇**:在求职过程中,一份精炼且突出个人优势的简历至关重要。面试者需注意简历的内容应当简洁明了,避免冗长无实质内容的描述,并确保简历中提到的...
为了帮助开发者们在面试中脱颖而出,市面上出现了许多专注于Java面试的指南书籍,其中《Java高分面试指南》以其全面的内容和深入浅出的讲解方式,成为了众多求职者的青睐之作。在这份指南中,不仅覆盖了Java的基础...
「Java面试指南」一份通向理想互联网公司的面试指南,包括 Java基础、Java并发、JVM、MySQL、Redis、Spring、MyBatis、Kafka、计算机操作系统、计算机网络、系统设计、分布式、Java 项目实战等
现在,我们来详细说明本《Java求职面试指南》中的核心知识点: 1. Java基础知识 - “==”与“equals”的区别:前者比较的是两个对象的引用是否相同,即它们是否指向同一个对象的内存地址;而后者比较的是两个对象...
「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,首选 JavaGuide!「「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。准备 Java 面试,首选 ...
Java面试指南是为中高级Java开发者准备的一份详尽参考资料,旨在帮助他们在面试过程中展现出扎实的技术功底。这份指南涵盖了Java编程语言的核心概念、高级特性、并发编程、内存管理、性能优化、框架应用等多个关键...
JavaOOP面试题 Java集合/泛型面试题 Java异常面试题 Java中的IO与NIO面试题 Java反射面试题 Java序列化面试题 Java注解面试题 多线程&并发面试题 JVM面试题 Mysql面试题 Redis面试题 Memcached面试题 MongoDB面试题 ...
第二篇(第2章~第13章)介绍了Java程序员涉及的基础知识,内容包括Java语言基础、异常的处理、I/O控制流、面向对象编程、线程、集合以及数据库技术等基本知识点。 第三篇(第14章~第16章)专门介绍了Java开发...
Java程序员面试指南旨在帮助求职者准备Java开发职位的面试,涵盖了广泛的编程概念和技术知识点。这份指南可能包括了从基础语法到高级特性的深入讨论,以及实际编程问题的解决方案。以下是一些可能涵盖的重要知识点:...
Java概论(面试指南)是一本专门针对有一定Java基础的求职者而准备的书籍,目的在于帮助他们梳理和掌握Java面试中的重点知识点。考虑到应聘者的不同水平,从初级到中高级,本书提供了一个实用的复习框架,重点突出,...
从淘宝上买的《JAVA程序员面试指南》电子书清晰版,贡献给大家。
Java最详细的帮你复习面试指南 回顾所有的Java知识 +笔记 +面试指南+简历帮助 全都是干货
这份"2024 Java面试宝典合集"无疑是准备Java求职面试者的宝贵资源。它涵盖了多个关键领域,包括Spring框架、并发编程、Java核心知识以及面试策略等。下面我们将详细探讨这些知识点。 1. **Spring Boot面试题**:...
总的来说,《Java面试宝典2018版》是一本全面而深入的指南,它将帮助Java开发者系统复习技术要点,提升专业素养,从而在面试中展现出色的技术能力。通过深入阅读并实践书中的知识,你将能够更好地应对各种面试挑战,...
2024 Java offer 收割指南java面试题合集分享给需要的同学.pdf
Java面试准备是每位Java程序员在职场跳槽时不可避免的一个环节。在面试中,除了要展示个人的专业技能和项目经验,还需要掌握一些面试技巧来更好地表达自己。以下根据给定文件信息总结出的Java面试准备知识点: 1. ...