在做基础面试题的时候,会有很多区别性的问题,题干给出两个意思相近的单词,然后写出他们的区别,这里简单整理的一些基础面试题的区别问题。
目录
5.Override 和Overload的区别是什么?Overload的方法是否可以改变返回值的类型?
1.ArrayList、Vector 和 LinkedList有什么特点? HashMap和HashTable有什么区别?
4.List<? extends T> 和 List<? super T>之间有什么区别?
1.jsp和servlet有哪些相同点和不同点?它们之间的联系是什么?
1.检查异常与运行时异常的区别?error与Exception的区别。
(一)基础语法部分
1.接口与抽象类的区别?
相同点:都不能被实例化。
接口的实现类或抽象类的子类都只有实现了接口或抽象类中的方法后才能被实例化。
不同点:
接口只有定义,不能有方法的实现,而抽象类可以有定义与实现,即方法可以在抽象类中被实现。
实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。
接口的设计理念是“has-a” 抽象类的设计理念是“is-a”。
接口中定义的成员变量默认的修饰符石 public static final, 只能有静态的不能被修改的数据成员,而且,必须给其赋初始值,其所有的成员方法都是 public abstract 的,而且只能被这两个关键字修饰。而抽象类可以有自己的数据成员变量,也可以有非抽象方法,而且诶,抽象类中的成员变量默认为default,当然也可以被定义为private、protected和public,这些成员变量可以再子类中被重新定义,也可以被重新赋值,在jdk(1.8)之前接口中的抽象方法不能用private、static。Synchronized访问修饰符,同时方法必须以分号结尾,并且不能带花括号{}。所以,当功能需要积累的时候,使用抽象类,不需要积累的时候,使用接口。
接口被用于实现比较常用的功能,便于日后的维护或者添加方法,而抽象类更倾向于充当公共类的角色,不适用与日后重新对里面的代码进行修改。
2.int与Integer 的区别?
Int是Java语言提供的八种原始数据类型之一,当作为对象的属性的时候,默认值为0
Integer是Java为int提供的包装类,默认值为null。
Int是基本类型,在使用的时候采用的是值传递。
Integer采用的是引用传递。
当往容器里存放整数的时候,无法直接存放int 而是将int类型转换为Integer存放。
3. String与StringBuffer的区别?
String用于字符串操作,属于不可变类,而StringBuffer也是用于字符串操作,不同之处是StringBuffer属于可变类。
String是不可变类,也就是说,String对象一但被创建,其值不可以被改变,而StringBuffer是可变类,当对象被创建后,仍然可以对其值进行修改。如果一个字符串经常需要修改的时候,使用StringBuffer有更高的效率。
String 和StringBuilder都是线程不安全的。
StringBuffer是线程安全的。
单线程大量操作的时候才需要用StringBuilder。
4.final finally finalize 的区别?
final 用于声明变量。方法和类,分别表示属性不可变。方法不可覆盖。类不可被继承。
finally用于异常处理,只能用在try/catch语句中,并且附带着一个语句块,表示这段话最终一定会被执行,经常用于需要释放资源的情况下。
finalize 是Object类的一个方法,在垃圾收集器执行过的时候会调用被回收对象的finalize方法。可以覆盖此方法来实现对其他资源的回收。
5.Override 和Overload的区别是什么?Overload的方法是否可以改变返回值的类型?
Overload(重载)和Override(覆盖)是java多态性的不同表现,其中,重载是在一个类中多态性的一宗表现,是指在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型。在使用重载时,需要注意:
1重载时通过不同的方法参数来区分的,
2 不能通过方法的访问权限,返回值类型和抛出的异常来进行重载。
3对于继承类来说,如果基类方法的访问权限是private,那么就不能在派生类中对其进行重载,如果派生类也定义了一个同名函数,这只是一个新的方法,不会达到重载的作用。
Override 是指派生类函数覆盖基类函数,覆盖一个方法并对其进行重写,以达到不同的作用。
在使用覆盖的时候需要注意。
派生类的覆盖方法必须和基类中的覆盖方法有相同的函数名和参数。
派生类中的覆盖方法的返回值必须和基类中的被覆盖方法的返回值相同。
派生类的覆盖方法所抛出的异常,必须和基类中被覆盖方法所抛出的异常一致或者是他的子类。
重载与覆盖之间的区别主要有以下几个方面:
1覆盖是子类和父类之间的关系,是垂直关系。重载时同一个类中方法之间的关系。是水平关系。
覆盖只能由一个方法或只能由一对方法产生关系;方法的重载是多个方法之间的关系。
覆盖要求参数类表相同,重载要求参数列表不同。
覆盖关系中,调用方法体是根据对象的类型(对象对应的存储空间类型)来决定的;而重载关系是根据调用时的实际参数与形参列表来选择方法体的。
如果一个类中定义的多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为重载方法。Overload的方法是可以改变返回值的类型,但是Override 的方法不能改变返回值的类型。
(二)集合类部分
1.ArrayList、Vector 和 LinkedList有什么特点? HashMap和HashTable有什么区别?
ArrayList和Vector都是基于数组实现的,他们会在内存中开辟一块连续的空间来存储,由于数据存储是连续的,因此它们支持使用序号(下标,索引)来访问元素,同时,索引数据的速度比较快。但是在插入元素的时候需要移动容器中的元素,所以,对数据的插入操作执行速度比较慢。ArrayList和Vector都有一个初始化的内存容量大小,当里面存储的元素超过这个大小的时候,就需要动态地扩充他们的容量。为了提高程序的效率,每次扩充容量的时候,不是简单一次扩充一个单元,而是一次就会增加很多个存储空间 Vector默认扩充为原来大小的2倍,ArrayList默认为1.5倍。
ArrayList与Vector的最大区别就是synchronization的使用,没有一个ArrayList 的方法是同步的,而Vector 的绝大多数方法都是直接或间接同步的,Vector是线程安全的,ArrayList不是线程安全的。 Vector的性能逊于ArrayList。
LinkedList采用双向链表的方法来实现。对数据的索引需要从表头开始遍历,因此,随机访问的效率很低,但是插入元素后不需要对数据进行移动,故插入效率较高,同时 LinkedList是线程不安全的。
HashMap和HashTable的区别如下。
在java.util.Map接口中,它有三个实现类,HashMap、 HashTable、 TreeMap。 Map是用键值对来存储数据的集合,在数组中通过数组下标来对其中的内容进行索引,而在Map中,则是通过对象来进行索引,来进行索引,用来进行索引的对象叫做Key,其对应的对象叫做Value
HashMap是一个最常用的Map,它根据键的HashCode值来存储数据,根据键可以直接获取它的值,具有很快的访问速度。由于HashMap与HashTable都采用的Hash方法进行索引,因此,二者具有很多相似之处,它们主要有如下的一些区别:
HashMap是HashTable的轻量级实现,它们都实现了Map接口,主要区别在于HashMap允许空(null)键值(KEY)(但需要注意,HashMap只允许一条空键值key,) 而Hashtable
不允许(null)键值key。
HashMap把HashTable的contains方法去掉了,改成了containsValue和containsKey。因为contains方法容易引起误解。Hashtable继承自Dictionary类,而HashMap是实现的Map interface的一个接口。
Hashtable的方法是线程安全的,HashMap由于不支持多线程同步,所以它不是线程安全的。
Hashtable采用Eunmeration遍历, HashMap采用Iterator进行遍历。
Hashtable和HashMap采用的 hash/rehash算法几乎一样,所以,性能不会有很大的差异。
Hashtable中的暑促默认大小为11,增加的方式是old*2+1,在HashMap中,Hash数组的默认大小是16而且一定是2的指数。
Hash值不同,Hashtable直接使用对象的HashCode。
三种类型汇总,使用最多的是,HashMap。HashMap里面存入的键值对在取出的时候没有固定的顺序,是随机的,一般而言在Map中插入,删除和定位元素,HashMap是最好的选择。由于TreeMap实现了SortMap接口,能够把它保存的记录根据键值排序,所以取出来的元素是排序后的键值对。
LinkedHashMap是HashMap的一个子类,如果需要输出的顺序和输入的顺序相同,那么可以用LinkedHashMap实现,它还可以按读取顺序来排列。
2.Collection 与Collections的区别?
Collection 是 接口 List Set Queue的父接口。
Collections 是 类 用于操作 List Set Map 等集合。
一些Collections 的方法:
void reverse(List list)反转指定List集合中元素的顺序。
void shuffle(List list)对List集合中的元素随机排序。
void sort(List list)根据元素的自然顺序,对List元素进行排序。
void sort(List list,Comparator c) 根据Comparator产生的顺序对List元素进行排序。
3.Comparable与 Comparator的区别?
上面提到了Comparator排序,很多面试题里都问到 Comparable 与Comparator的区别。
个人总结这两个接口之间的区别:
Comparable 是自然排序。让元素自身具备“比较性”。覆盖int compareTo(T o)方法。
Comparator 是定制排序。提供一个比较器,一些集合调用比较器来比较集合中俩个元素。要覆盖int compare(T o1,T o2)方法。
Comparable之所以称之“自然排序”是因为很多java.lang的常用类都实现了这个接口。
基础数据类型包装类 排序规则 :按他们对应数值的大小进行排序
Character 按字符转换的Unicode数值进行排序。
Boolean 中 true 对应的数值大于false对应的。
String 按字符串转化成的Unicode数值进行排序。
Date Time 后面的时间比前面的时间大。
TreeSet中两者的区别明显。
4.List<<? extends T>> 和 List<<? spure T>>之间有什么区别?
这里使用的是泛型通配符。
<? extends T>表示的是 list里面储存的是类型是T或者是T的子类,是类型的上限。
用来读取数据。可以读出类的对象可以放在T类里,或者是T的父类里。不能用来写数据。
<? spuer T>表示的是list里面储存的是类型T或者T的父类,是类型的下限。
用来往里面写数据。可以往里面写入T和T类型的子类,不能用来读数据。
(三)网络编程
1.jsp和servlet有哪些相同点和不同点?它们之间的联系是什么?
JSP可以被看作是一个特殊的Servlet,它不过是对Servlet的扩展,只要是JSP可以完成的工作,使用Servlet都可以完成,例如,生成动态页面。由于JSP页面最终要被转换成Servlet来运行,因此,处理请求实际上是编译后的Servlet。
不同点: Servlet 的实现方式是在JAVA语言中嵌入Html代码,编写和修改HTML
非常不方便,所以它比较适合做流程控制和业务逻辑处理,而jsp实现方式为在HTML中潜入Java代码,比较适合页面的显示。
Servlet中没有内置对象,Servlet中的内置对象都必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet来得到。
2.forward和redirect的区别是什么?
Forward是服务器内部的重定向,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,而客户端并不知道,因此,在客户端浏览器的地址栏里不会显示转向后的地址,还是原来的地址。由于整个定向的过程中用的是同一个Request,因此,forward会将Request的信息带到被定向的JSP或者是Servelet中使用。
Redirect则是客户端重新定向,是完全的跳转,即客户端浏览器会获取跳转后的地址,然后重新发送请求,因此,浏览器中会显示跳转后的地址。同时由于这种方式比forward方式多了一次网络请求,所以,forward效率更高。
(四)异常
1.检查异常与运行时异常的区别?error与Exception的区别。
(请给出java异常的继承体系结构,以及java异常的分类,且为每种类型的异常各举几个例子。)
Java语言中提供了两种错误的处理类,分别为error和Exception 且他们都有共同的父类:Throwable。
Error 表示i程序在运行期间出现的系统错误,这属于jvm层次的错误,这种错误将会导致程序终止运行。此外编译器不会检查Error是否被处理,因此,在程序中不推荐去捕获Error类型的异常。 OutOfMemoryError、ThreadDeath 和NoClassDeFoundError等都属于错误。
Exception表示可恢复的异常,是编译器可以捕捉到的。它包含两种类型:运行时异常Runtime Exception 和检查异常 Checked Exception、
检查异常是在程序运行中最经常碰到的异常,比如最常见的IO异常和SQL异常,对于这种异常,都发生在编译阶段,java编译器强制程序去捕获此类异常。即把可能会出现的这些异常代码块放到try块中,把对异常的处理的代码放到catch块中,这种异常一般在如下几种情况中使用。
异常的发生不会导致程序出错,进行处理后可以继续执行后续的操作。
程序依赖于不可靠的外部条件 如系统io
几个检查异常 IOException SQLException UnknownHostException
对于运行时异常,编译器没有强制对其进行捕获并处理,如果不对这种异常进行处理,当出现这种异常时,会有jvm来处理。在java中,最常见的运行异常
NullPointerException ArryStoreException
IndexOutOfBoundException
(五)多线程
1.Synchronized和lock的区别?
Synchronized关键字,每个对象都有一个对象锁与之相关,该锁表明对象在任何时候只允许被一个线程拥有,当一个线程调用对象的一段synchronized代码时,首先需要获得这个锁,然后去执行相应的代码,执行结束后,释放锁。
Synchronized关键字主要有两种用法, synchronized方法和synchronized块 此外关键字还可以作用于静态方法、类或某个实例,但这都对程序的效率有很大的影响。
只要把多个线程访问资源的操作放在一个标记Synchronized的方法中,就能够保证这个方法在同一时间只能被一个线程来访问,从而保证了多线程访问的安全性。然而,当一个方法的方法体规模非常大的时候,把该方法声明为synchronized会大大影响程序的执行效率。为了提高程序的执行效率,java语言提供了synchronized块
可以把任意代码段声明为synchronized,也可以指定上锁的对象,有非常高的灵活性。
Jdk5新增加了lock接口以及它的一个实现类ReentranLock(重入锁)lock也可以用来实现多线程的同步,具体而言,它提供了如下的一些方法
Lock()以阻塞的方式来获取锁,也就是说,如果获取了锁,则立即返回,如果其他线程持有锁,当前线程等待,直到获取锁后返回。
Trylock()以非阻塞的方式来获取锁,只是尝试地去获取一下锁,如果获取到锁,则立即返回true,否则,立即返回false;
Trylock(long timeout,timeunit unit)如果获取了锁,立即返回true 否则,会等待参数给定的时间单元,在等待的过程中,如果获取了锁,就返回true,如果等待超时,则返回false。
Lockinterrupttibly()、如果获取了锁,则立即返回,如果没有获取锁,则当前线程处于休眠状态,直到获取锁,或者当前线程被其他线程中断。