Java面试之前复习总结(一)
时间在一分一秒的过去,面临求职面试也是越来越近了,在看面试题以及牛客网做题时,遇到了很多不理解或者之前没见过的,就把他总结下来了,发个博客,大家共勉,之后会持续更新。
1、String类都有那些常用的方法。
length(); split(); replace();
equals(); subString(); charAt();
concat(); 大小写转换; indexOf();
trim(); isEmpty(); contains();
startWith()
补充:Object类方法
clone、 equals finalize getClass
hashCode notify notifyAll toString
wait
补充:异常分类
算数异常 类型转换异常 非法参数异常
下标越界异常 空指针异常 安全性检查异常
need-to-insert-img
need-to-insert-img
2、StringBuilder和StringBuffer区别
根本区别就是StringBuilder是线程不安全的,而StringBuffer是线程安全的。
速度,StringBuilder > StringBuffer > String
String是不可变的,其他两个是可变的
按照性能排序 String(大姐,jdk1.0) < StringBuffer(二姐,jdk1.0)
StringBuffer很多方法都被synchronized修饰了,而StringBuilder没有,所以StringBuilder速度比StringBuffer快。建议用StringBuilder。
JVM运行程序主要时间都是浪费在创建对象和回收对象上。
eg:String s = “this is”+“only”“simple test”;等同于 String s = “this is only simple test”。
3、Map和List的遍历区别
List:增强的for循环(最差)、for(int i=0;i
List:对越arrayList、Vector遍历应该采用随机访问get
LinkedList:采用迭代器
关于Map能不能存储null情况
keyvalue
TreeMap不允许允许线程不安全
HashMap允许允许线程不安全
关于Map遍历的entrySet和keySet
推荐使用entrySet,说明,keySet其实是遍历了两次,一次转化为Iterator对象,另一次是从HashMap中取出key所对应的value,而entrySet只遍历了一次就把他key和value全部都存到entry中了,效率更高。
need-to-insert-img
Set代表无序,不重复,Map代表key-value组成的集合,Map的key要求是不能重复,没有顺序,把Map的所有key组合起来就是Set。
4、数组与List区别
ArrayList的底层实现还是数组,索引速度快。
LinkedList:是基于链表。
对于随机访问,get set ArrayList优秀。
对于新增和删除,LinkedList优秀
5、Set和List区别
根本:Set 无序,不重复。 List:有序,元素可重复
Java遍历List
第一种:
for(Iterator it = list.iterator(); it.hasNext();) {
......
}
这种方式在循环执行过程中会进行数据锁定, 性能稍差, 同时,如果你想在循环过程中去掉某个元素,只能调用it.remove方法, 不能使用list.remove方法, 否则一定出并发访问的错误.
第二种:
for(A a : list) {
......
}
它内部还是调用第一种, 换汤不换药, 这种循环方式还有其他限制, 不建议使用它
第三种:
for(int i = 0; i < list.size(); i++) {
A a = list.get(i);
......
}
它内部不做锁定, 效率最高, 但是当写多线程时要考虑并发操作的问题!
注:TreeMap和HashMap,Hash底层采用数组来保存key和value
6、垃圾回收
System.gc();
Runtime.gc() 也就是 Runtime.getRuntime().gc();
7、反射机制
在Java运行环境中获取类的属性和方法,调用对象的任意一个方法,这种动态获取类的信息,以及动态动态调用对象的方法的功能,就叫做Java的反射机制。
8、Java的数据类型
need-to-insert-img
补充:关于float与double精度丢失问题
float:有效位是7位。
double:有效位16位
9、Java类加载机制
10、栈和链表有什么区别
栈:先进后出。
链表:随便什么地方都可以插入删除
11、Map、HashMap、LinkedHashMap存储结构以及实现原理
HashMap底层是用数组实现的。
Map中包括一个内部类Entry,封装了一个key-value
LinkedHashMap采用双向链表来维护元素关系,因为要维护元素顺序,所以性能略低于HashMap。
12、short s1 =1, s1 = s1 + 1 有错吗,shrot s1 = 1 , s1 +=1有错吗。
对于第一种,由于1是int型,因此s1 + 1 运算是int型,需要强制类型转化,
而第二种相当于 s1 = (short)(s1 + 1)其中隐含了强制类型转化。
13、Integer 和int区别。
注意:就是涉及到自动装箱。
Integer a1 = new Integer(3);
Integer a2 = 3;
System.out.println(a1 == a2); //false 如果a2是int型,就是true
Integer a = 15;
Integer b = 15;
Integer c = 129;
Integer d = 128;
System.out.println(a == b); //true
System.out.println(c ==d ); //false
注:如果整形字面的量值在-128 ~128之间,那么不new对象,而是引用常量池中的Integer对象。
访问控制符
类成员:private、default、protected、public
修饰类:public、final、abstract
修饰方法:public、默认、protected、private、|static、find、abstract
修饰变量:public、默认、protected、private、|static、find
类型private无protectedpublic
同一类√√√√
同一包中子类 √√√
同一包非子类 √√√
不同包子类 √√
不同包非子类 √
14、HashMap采用拉链法解决冲突(链地址法)
HashMap有两个参数影响性能,初始容量和加载因子(装填因子)。
链表法就是将相同hash值的对象组织成一个链表放在hash值对应的槽位中。
开放地址法是通过一个探测算法,当某个槽位已经被占据的情况下继续寻找下一个可以使用的槽位,很显然,HashMap解决冲突的方法是拉链法,也叫链地址法。
15、关于Java默认导入的包。
Java.lang,包含如下
Object:是所有类的父类。
基础类型包装类
数学类
String和StringBuilder
系统和运行时类:System.in 和out 是标准的输入类和输出类,System所有成员变量和方法都是静态的。
16、关于==和equals
==可用于基本类型和引用类型的比较,采用Integer比较,只要new,就不同。Integer.valueOf()和Integer a = 53,等价。切记Intger.valueOf()的源码,大于127都要new。
17、Java语言中数组复制的方法.
System.arrayCopy() > clone > Arrays.copyOf -> for循环赋值。(按性能排序)。
need-to-insert-img
关于clone方法:Java.lang.Object类的clone()方法,为protected类型,不可直接调用,需要先对要克隆的对象进行下列操作,首先被克隆的类应该实现Cloneable接口,然后在该类中覆盖clone方法,并且在该类中调用super.clone()方法。
need-to-insert-img
复制引用和赋值对象的区别。
复制引用:是指将某个对象的地址复制,所以复制后的对象副本的地址和源对象相同,这样,当改变副本的某个值后,源对象值也被改变;
复制对象:是将源对象整个复制,对象副本和源对象的地址并不相同,当改变副本的某个值后,源对象值不会改变;
Cat cat1=new Cat("xiaohua",3);//源对象
System.out.println("源对象地址"+cat1);
//调用clone方法,复制对象
Cat cat2=(Cat)cat1.clone();
Cat cat3=(Cat)cat1;//复制引用
System.out.println("复制对象地址:"+cat2);
System.out.println("复制引用地址:"+cat3);
need-to-insert-img
可以看出,复制引用的对象和源对象地址相同,复制对象和源对象地址不同
18、关于静态代码块,代码块,构造方法的执行顺序.
父类静态代码块-》子类静态代码块-》父类构造代码块-》父类构造函数-》子类构造代码块-》子类构造函数。
注意:构造代码块和构造函数一起执行。
先执行静态初始化快,普通初始化快和午餐的构造函数一起i执行。
19、&& 和&
&&短路,如果&&左边位false,直接短路掉
&非短路。
20、return、break、和continue
return:直接退出循环
break:跳出本层循环
continue:跳过本次循环
补充:break只能用在循环语句中,while,do....while或者for 或者switch中
21、Math.round(11.5等于多少)
12.round其实就是四舍五入
注:关于四舍五入的方法
//第一种方法,使用DecimalFormat来格式化数字。
String ss = new DecimalFormat("#.000").format(s);
System.out.println("DecimalFormat四舍五入: "+ ss);
//第二种方式,使用String.format
System.out.println("使用String.format:" + String.format("%.3f", s));
//第三种方式,使用技巧round 这种方式存在问题
System.out.println("使用技巧round:" + Math.round(s*1000)*0.001d);
//错误System.out.println("使用技巧round:" + Math.round(s*1000*0.001d));
//第四种方式
BigDecimal big = new BigDecimal(s);
double d = big.setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("第四种方式获取:" + d);
System.out.println(big.setScale(3, BigDecimal.ROUND_HALF_UP));
22、switch是否作用于byte上,是否作用long,是否String
Java5之前,switch(expr)。expr只能是byte,short,int,char
Java5之后,enum,
Java7,String
long,目前还不支持
23、数组有没有length()方法,String有没有length属性?
数组有length属性,String有length方法。
24、构造器不能被继承,所以不能被重写,但课重载,
25、为什么不能通过返回值类型区分重载
例如 int f(),void f(),在方法调用时可以省略类型f(),这时系统怎么处理?会找不到,会迷糊,所以,通过返回值区分重载行不通。
26、String s = new String("xyz"),创建了几个对象。
创建了两个对象,一个是静态区的。
27、Java中的final关键字有那些用法,
修饰类,表示该类不能被继承。
修饰方法
修饰变量
28、关于字符编码转换,就是利用String的构造方法和普通方法。
String a = "你好";
String b = new String(a.getBytes("gb2312"),"ISO-8859-1");
System.out.println(b);
String c = new String(a,"gbk").getBytes("utf-8");//第二种
29、TreeMap和TreeSet在排序时,如何比较元素,Collection中的sort()方法如何比较元素,
TreeSet要求所有存放对象必须实现Comparable接口,该接口提供compareTo()方法,
TreeMap要求存放的键值对映射的建必须实现Compareable接口,从而根据建进行排序。
Collection.sort()有两种排序方式:
传入的对象实现了Comparable
不强制要求传入元素必须课比较,但如要传入第二个参数,参数时实现Comparable接口的子类型,相关于临时定义了一个排序规则。
关于comparable(java.lang)和compartor(java.util)
list列表中所有元素必须实现Comparable接口,实现Comparable需要重写comparTo方法。
使用Comparable有很大局限性,实现此接口只能按compareTo(T t)定义的方法。
一个类的兑现更要实现多种排序方式,可以为该接口定义不同的比较器,实现comparator接口
附:compartor与comparable区别:comparator接口与Comparable接口的区别
补充:线程和进程的区别
进行是执行着的应用程序,而线程是进程内部的一个执行序列,一个进程可以又多个线程,
线程同步:
使用lock与使用同步方法有点类似,只是使用lock时显示使用lock对象作为同步锁,而使用同步方式时系统隐世使用当前对象作为同步监视器。而使用lock对象时,每个lock对象对应一个Account对象,一样可以保证对于同一个Account对象,同一时间只能又一个线程进入临界区。
30、关于Thread类的sleep方法和对象(Object)的wait方法。
Thread.sleep() Object.wait()
调用了sleep时线程类休眠的静态方法,调用此方法会让当前线程暂停执行指定事件,将执行机会(CPU)让给其他线程,但对象的锁依然保持,因此休眠结束后自动恢复。
wait是Object的方法,调用wait方法导致当前线程放弃对象所进入线程池,只有调用对象的notify()方法,才能被重新唤醒。
31、创建线程的三种方法。
继承Thread
实现Runnable
使用Callable和FUTURE(2、3实现方式相同,所以归结到一类)
推荐采用实现Runnable接口,Callable接口来创建线程,因为如果是继承,就浪费了一次继承的机会,导致无法再继承其他的类,而接口不一样。
32、状态
线程是进行内的并发,没有自己的内存空间,共享进程的。
线程的四种状态:就绪,执行,挂起。结束
need-to-insert-img
join:等待另一个线程完成
Sleep()之后线程进入阻塞状态,然后进入就绪状态,
wait()之后线程进入等待队列,等待唤醒进入就绪状态。
yield执行后线程进入就绪状态(直接进入就绪状态,不进入阻塞)
join执行后线程进入阻塞状态
need-to-insert-img
need-to-insert-img
sleep与yield
sleep()方法暂停后,会给其他线程机会,不会理会优先级,
sleep()方法会将线程转入阻塞状态,然后进入就绪状态,而yield()不会将线程转入阻塞,只是i强制当前进程进入就绪,因此完全有可能某个线程调用yield()方法暂停后,立即再次获得处理器资源执行
sleep()方法抛出一个InterruptedExecption异常。
sleep(0放比yield()方法具有更好的一致性,通常不建议使用yield()方法来控制并发线程执行。
线程相关:
1、关键字synchronized 、static、abstract、final
synchronized:用于方法或代码块前,使此方法或者代码块编程同步的。
static:用于声明静态变量,static关键字可以修饰变量,方法,静态代码块。
静态变量:
由static修饰的变量称为静态变量
静态变量属于类,而不属于某个对象
静态变量它的副本只有一个(静态变量在类中只加载一)
静态方法:
在静态方法中只能调用静态变量和静态方法
在非静态方法中,可以调用静态方法或者变量。
在静态方法中不能使用this和super关键字。
静态代码块
作用:用来给静态成员变量初始化
abstract:用于定义抽象类或者方法
final:用于声明常量,即只能赋一次值
volatile:用来确保将变量的跟新操作通知到其他线程,当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。然而,在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比 synchronized关键字更轻量级的同步机制。
serialize:Java 对象序列化为二进制文件
33、Java中如何实现序列化以及实现序列化的意义。
实现Serializable接口
意义:可以将硫化后的对象进行读写操作,也可用于网络之间对象传输,序列化是为了解决对象流读写坐坐时引发的问题。
34、xml文档有几种形式?本质?解析。
两种:dtd schema
schema本身也是一个xml文件,可以被xml解析,约束能力大于dtd
解析xml有两种:
dom:使用dom要预先加载整个文件适合随机访问,(空间换时间)
SAX:是事件驱动型,适合对xml顺序访问。
35、简述JDBC
加载驱动,Class.forName("com.mysql.jdbc.");
创建链接,Connention conn = DriverManager.getConnection("")
创建语句:PrepareStatement ps = conn.prepareStatement("");
执行语句:ResultSet rs = ps.executeQuery()
处理结果
关闭资源
36、事务的ACID:原子性,一致性,隔离性,持久性
脏读:A事务读取B事务尚未提交的数据,并再次基础上操作,而B事务执行回滚,那么A事务读到的数据就是脏数据。
不可重复读:A事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改了。
幻读:
37、获取一个对象
A.class()
a.getClass()
Class.forName()
38、Arrays.toString(int[]),Arrays工具类的头String方法。
首先检查是否为空,如果为空就return "[]",否则,StringBuilder,先append一个"[",然后循环,append一个数,if 到结尾 return appent ”]“,否则append(",")
39、类变量是指用satic修饰的属性,
40、在子类构造方法中使用super(),显示调用父类的构造方法,super()必须卸载子类构造方法第一行,否则不通过。
41、Java是一次编写多出运行,c++是一次编写多处编译
42、新生代,老年代,持久代
43、LinkedList实现了List,而不是继承,AbstractSet实现了Set
44、StringBuilder通过调用toString()方法转换为String型。
45、override重写,overloadding重载。
重写是子类重新定义了父类的方法,重写必有相同的方法名,参数列表和返回值类型。
重载是发生在同一个类里面的两个或多个方法名相同,但参数不同的情况
46、什么是java虚拟机,为什么java被称为平台无关语言,
Java虚拟机是一个可执行Java字节码的虚拟机进程,Java源文件被编译成能被Java虚拟机执行的字节码文件。
47、关于抽象类和接口,区别和共同点。
接口中的方法都是抽象的,而抽象类则可以同时包含抽象和非抽象方法。
类可以实现多个接口,但只能继承一个抽象类。
类可以不实现抽象类和接口中声明的方法,当然在这种情况下类也必须是抽象的。
抽象类可以在比提供接口实现的情况下实现接口。
接口中声明的变量默认都是final的,抽象类可以包含非final的
接口中的成员函数默认都是public的,抽象类的成员函数可以是private、protected或者public
接口是绝对抽象的,不可以被实例化,抽象类也是不可以被实例化的
48、Iterator,ListIterator
Iterator可以遍历set和list集合,但是ListInterator只能用来遍历List
Itertator只能向前遍历,ListIterator既可以向前也可以向后,
ListIterator实现了Iterator接口。
49、快速失败和安全失败的区别是什么
Java.util都是快速失败,
Java.util.conncurrent包瞎所有类都是安全失败的。
快速失败会抛出ConncurrentModificationException异常,而安全失败永远不会抛出这样的异常。
50、Java中HashMap的工作原理。
Java中HashMap以键值对形式存储元素,HashMap需要一个hash函数,它使用hashCode()和equals()方法向集合添加元素,当调用put()方法时,HashMap会计算key的hash值。
HashMap的一些重要的特性是它的容量、负载因子和扩容极限。