面试题
1.1 抽象类和接口的区别
抽象类是什么
含有abstract修饰符的class即为抽象类。
特点:
- 不能创建的实例对象
- 可以有抽象方法
- 可以有构造方法,但构造方法不能是抽象的
- 抽象方法必须子类进行实现,如果子类只实现部分方法,该子类必须是抽象的。
接口是什么
含有interface修饰符的就是 。
特点:
- 接口中的所有方法都必须是抽象的
- 接口中的方法定义默认为public abstract类型
- 接口中的成员变量类型默认为public static final
区别是什么
- 单继承多实现:一个类可以实现多个接口,但只能继承一个抽象类。
- 构造方法:抽象类可以有构造方法,接口中不能有构造方法。(JDK7之前)
- 变量:抽象类中可以有普通成员变量,接口中只有常量。
- 方法:抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
- 修饰符:抽象类中的抽象方法可以使用public和protected进行修饰,但接口中的抽象方法只能使用public abstract修饰。
- 静态方法:抽象类中可以包含静态方法,接口中不能包含静态方法
- 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
1.2 常用的集合有哪些,谈谈对它们的理解
常用的集合有:
单列集合:List、Set
双列集合:Map
特点:
List:有序、可重复
Set:无序、不能重复
Map:键值对、键唯一、值不唯一。如果要向Map集合中存放两个相同的key,后赋值给key的value的会把先赋值给key的value覆盖掉。
常见实现类:
List:
LinkedList:基于链表实现,查询慢,增删快
ArrayList:数组实现,查询快,增删慢
Set:
HashSet:哈希表数据结构,查询速度块,HashSet底层使用HashMap,仅使用key。
LinkedHashSet继承自HashSet,LinkedHashSet中的元素顺序是可以保证的,也就是说遍历序和插入序是一致的。
Map:
HashMap:HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null,不是线程安全的
LinkedHashMap:LinkedHashMap简单来说是一个有序的HashMap,其是HashMap的子类,HashMap是无序的。
HashTable:Hashtable既不支持Null key也不支持Null value,是线程安全的
1.3 ==与equals()的区别
==比较的是值
== 如果比较的是基本数据类型,比较的则是变量值
== 如果比较的为引用数据类型,比较的则是地址值
equals比较的是引用数据类型
如果没有重写hashCode和equals方法,比较的是地址值。因为Object的equals方法中使用是==。
如果重写hashCode和equals方法,则比较的重写后的规则。
例如:两个String字符串比较时:比较的是内容。因为String底层重写了equals方法进行内容的比较。
1.4 方法重写和方法重载的区别
方法重写(overriding):子类对父类的方法进行重写。
方法重载(overloading):同一个类中重载已有的方法。
重写的特点:
1、签名一致:子类重写的方法,必须与父类的方法,返回值、方法名和参数列表都相同。
2、异常窄化:子类抛出的异常要么与父类方法抛出的异常相同,要么抛出的异常是父类方法异常的子类或不抛出。(优生:父类有病,子类没有病)
3、修饰符宽化:子类方法的的访问级别不能低于父类相应方法的访问级别(子类访问级别不能低于父类访问级别)
重载特点
拥有相同的方法名,但是参数列表不同(类型、个数、顺序)
与返回值无关
与参数变量名无关
1.5 throw 和 throws 的区别
throw和throws都于异常有关。
throw:用于抛出异常。
throws:用于声明异常。
throw出现在方法体中,在不同的语句中可能有多处throw。每throw一次只能抛出一个异常。throw抛出异常后可以立即try,也可以在方法上使用throws进行声明。
throws在方法上进行声明,表示一个方法可能出现的异常,需要方法的调用者进行处理。一个方法可以声明多个异常
1.6 描述遇到过的异常有哪些
(1)java.lang.NullPointerException 【空指针异常】
(2)java.lang.ClassNotFoundException 【类找不到异常】
(3)java.lang.NumberFormatException 【数字格式化异常】
(4)java.lang.IndexOutOfBoundsException 【数组角标越界异常】或 【数组索引越界异常】
(5)java.lang.IllegalArgumentException 【非法参数异常】
(6)java.lang.ClassCastException 【类型转换异常】
(7)java.lang.NoClassDefFoundException 【类未定义异常】
(8)SQLException 操作数据库异常 【SQL异常】
(9)java.io.IOException 【IO异常】
(10)java.lang.NoSuchMethodException 【没有匹配方法异常】
1.7 final, finally, finalize 的区别
(1)final:修饰符。
A).如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。
B).如果将变量或者方法声明为final,可以保证它们在使用中不被改变。
C).被声明final的方法只能使用,不能重写。
(2)finally:异常处理机制的一部分
A).finally结构使代码总会执行,而不管是否有异常。
B).使用finally常用于释放资源。
(3)finalize:Java中垃圾回收器执行的方法。
A).它是一个方法,属于java.lang.Object类。
B).在垃圾收集器执行的时候会调用的此方法,进行对象的回收,但在调用垃圾回收gc()后,并不能立即执行回收,JVM根据算法定时执行。
1.8 String、 StringBuffer、 StringBuilder 的区别
从运行速度来看:
StringBuilder > StringBuffer > String
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,因为String对象一旦创建之后该对象是不可更改的,只会重新赋值,
而后两者的对象是变量,是可以更改的,所以String运行速度最慢,而StringBuilder比StringBuffer 效率高,所以StringBuilder运行速度最快,其次StringBuffer 。
字符修改上的区别:
String:不可变字符串;显然线程安全
StringBuffer:可变字符串、效率低、线程安全;
StringBuilder:可变字符序列、效率高、线程不安全;
关于单线程和多线程的推荐
如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。
总结:
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
1.9 【】Java 中有几种类型的流?分别是什么
读写操作,我们通常称为输入/输入(IO)操作。Java通过流进行IO操作的。
字节流
InputStream是所有字节输入流的祖先,
OutputStream是所有字节输出流的祖先。
字符流
Reader是所有读取字符串输入流的祖先
Writer是所有输出字符串的祖先
字节高效流:BufferedOutputStream 、BufferedInputStream
字符高效流:BufferedWriter、BufferedReader
转换流: OutputStreamWriter、InputStreamReader
InputStream -->BufferedInputStream -->InputStreamReader -->Reader -->BufferedReader
1.10 break 和continue 的区别
(1)break:
常用于循环中,含义:结束循环,跳出循环体
其他应用场景:switch语句中,结束语句。
(2)continue:
结束本次循环,进行下一次循环;(注意:如果,循环进行到最后一次,continue执行,结束本次循环, 继续进行循环逻辑判断结束循环。循环结束与continue无关)
扩展:在循环嵌套中,可以通过“循环标号”使内层循环结束外层循环,如:
1.11 数据类型之间的转换
xxx类型转换字符串:String o = Xxx.toString( obj );
一. int转换成String
①.整型转换成字符型
String num = Integer.toString(int n);
②.Long型转换成字符型
String num = Long.toString(long n);
③.Short型转换成字符型
String num = Short.toString(Short n);
④.Float型转换成字符型
String num = Float.toString(Float n);
⑤.Double型转换成字符型
String num = Double.toString(Double n);
String类型转换为xxx:Xxx x = Xxx.parseXxx(String s);
二. String转换成int
①.转换成Int型
int/Integer num = Integer.parseInt(String str);
②.转换成long型
Long/long num = Long.parseLong(String str);
③.转换成short型
short/Short num = Short.parseShort(String str);
④.转换成float型
float/Float num = Float.parseFloat(String str);
⑤.转换成double型
double/Double num = Double.parseDouble(String str);
1.12 说说&和&&的区别
& 位运算,求2个二进制数的与。也可以进行逻辑运算,表达式左边为false,表达式右边继续执行。
&& 逻辑运算符,表达式左边为false,整个表达式结果为false,因此表达式右边不执行。此现象称为逻辑短路。
表达式1 & 表达式2 true & true == true
表达式1 && 表达式2 false && …. == false
表达式1|| 表达式2 true || …. == true
1.13 char型变量中能不能存贮一个中文汉字?为什么?
char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。
1.14 String s = new String("xyz");创建了几个String Object? 二者之间有什么区别
一个或两个。
第一次执行 new String("xyz") ,"xyz"将在字符串常量池中创建一个对象。new String() 又在堆内存中创建一个对象,所以创建了两个对象。
执行第二个语句new String("xyz") ,"xyz"第一次已经在常量池中创建,直接使用不用再创建。每new一次都会在堆内存中创建一个对象,new String() 再次在堆内存中创建对象,所以创建了一个对象。
1.15 Collection 和 Collections的区别
collection:
- 单列集合的顶级父接口
Collections:
- 操作集合的工具类
- 常用于:集合排序、集合不可修改限制等