细节!重点!易错点!--面试java基础篇(二)

时间:2021-06-01 03:51:08

今天来给大家分享一下java的重点易错点第二部分,也是各位同学面试需要准备的,欢迎大家交流指正。

1.字符串创建与存储机制:当创建一个字符串时,首先会在常量池中查找是否已经有相同的字符串被定义,其判断的依据是String类型equals的返回值,若已经定义,则直接获取对其的引用。
此时不需要创建新的对象,如果没有定义,首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。(例:new String(”aaa“)可能创建了1个或者2个对象,如果常量池中原来有aaa
那么之创建了一个对象,如果没有aaa,那么就会创建两个对象)

2.==,equals,hashCode的区别:
1) 如果要比较两个基本类型的数据或者两个引用变量是否相等,只能用==运算符。
2)equals是Object类提供的方法之一,Object类中定义的equals是直接用==运算符比较的对象(比较字符串的值是否相等用equals,比较引用是否相等用==)。
3)hashCode方法是从Object方法继承来的,也是用来鉴定两个对象是否相等。Object类中的hashCode方法返回对象在内存地址转换成一个int值,所以如果没有重写hashCode方法,任何对象的hashCode
都是不相等的。

3.String,StringBuffer,StringBuilder,StringTokenizer:
1)String对象一旦被创建,其值就不能被修改(引用不可变)。而StringBuffer则是可以改变类。
2)String在实例化时可以利用构造函数也可以用赋值符号,而StringBuffer只能用构造函数初始化。
3)StringBuilder和StringBuffer一样也是用来修饰字符串,但是StringBuilder不是线程安全的,所以StringBuilder效率更高,当有多个线程访问时使用StringBuffer。
4)StringTokenizer是用来分割字符串的工具。
注意:String s=""和 s=null是不一样的。 s=null 代表s不指向任何一个字符串,而s=""代表s是一个指向空字符串的引用。

4.关于数组:
1)在C和C++中,数组名知识一个指针,这个指针指向了数组的首元素。在Java中,数组不仅有自己的属性,也有一些方法可以被调用,从这个角度来讲,Java中数组是对象。
2)Java数组在定义时,并不会给数组元素分配存储空间,因此[ ]中不需要指定数组的长度。
3)Java数组在被创建后,会根据数组存放的数据类型初始化成对应的初始值。
4)Java中声明二维数组时,[ ]必须为空,二维数组的第二维的长度可以不同(例如定义一个二维数组,第一行两列,第二行三列)。

5.length length() 与size():Java中数组提供了length属性来获取数组的长度,length()方法是针对于字符串而言,计算字符串的长度。size方法是针对反省集合而言,获取其中有多少个元素。

6.finally语句的执行:finally块的作用就是确保无论出现什么情况,finally块里面的代码一定会被执行。如果try-finally或者catch-finally中有return,那么finally块中的retrun语句会覆盖别处的return语句。
但Java中的finally语句不是一定会被执行,如果遇到异常或者exit就会终止。

7.运行时异常和普通异常:Java中提供了两种错误异常类:Error和Exception,他们有着共同的父类-Throwable。
1)Error表示程序在运行期间出现了非常严重的错误,并且是不可恢复的,属于JVM层次的严重错误,这种错误多是由于逻辑错误导致的,属于应该解决的错误,通常不推荐捕获。
2)Exception表示可恢复异常,包含两种类型:检查异常和运行时异常。

8.异常处理需要注意一下几个问题:
1)Java异常处理用到了多态的概念,在捕获异常时,应该先捕获子类,在捕获基类的异常信息。
2)尽早抛出异常,同时对捕获的异常进行异常处理,或者从错误中恢复,或者让程序继续执行。
3)可以根据实际需求自定义异常类,这些自定义的异常类只要继承自Exception类即可。
4)异常能处理就处理,不能处理就抛出。对于一般异常,如果不能处理,就转换成运行时异常抛出。

9.Java的IO流:可分为两大类:字符流和字节流。
字符流:以字符16bit为单位,根据码表映射字符,一次可以读出多个字节。包含Reader和Writer两抽象类。
字节流:以字节8bit为单位,包含两个抽象类InputStream,OutputStream。
主要区别:字节流在处理输入输出时不会用到缓存,而字符流用到了缓存。

10.Java Socket:Java中socket分为两种类型:面向连接的Socket通信协议(TCP,传输控制协议)和面向无连接的Socket通信协议(UDP,用户数据报协议)。任何一个Socket都是由IP地址和端口号唯一确定的。

11.NIO:非阻塞方式与传统的Socket相比,在处理大量并发的请求时,使用NIO要比Socket效率高出很多。

12.Java序列化:Java提供了两种对象持久化的方式,分别为序列化和外部序列化(序列化是一种将对象以一连串的字节描述的过程,用于解决在对对象流进行读写操作时引发的问题)。
Java中所有实现序列化的类都必须实现Serializable接口。
序列化特点:
1)如果一个类能被序列化,那么它的子类也能被序列化。
2)由于static代表类的成员,transient代表临时数据,被声明为这两种类型的数据成员是不能够序列化的。
需要被序列化的情况:
1)需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中。
2)序列化能实现深复制,即可以复制引用的对象。

13.Java的解释执行顺序:代码的装入,代码的检验,代码的执行。
Java字节码 的执行也分为两种方式:即时编译方式,解释执行方式,即时编译方式指的是解释器先将字节码编译成机器码,然后再执行该机器码;
解释执行的方式值得是解释器通过每次解释并执行一小段代码来完成Java字节码程序所有的操作。

14.Java中class文件的加载原理:
类加载的方式分为隐式加载与显式加载。隐式加载指的是程序在使用new等方式创建对象时,会隐式的调用类额加载器,把对应的类加载到JVM中。
显式加载指的是通过直接调用class.forName 的方法来吧所需要的类加载到JVM中。

15.类加载的主要步骤:
1)装载。根据查找路径找到相对应的class文件,然后倒入。
2)链接。检查class文件的正确性。给类中的静态变量分配存储空间。将符号引用换成直接引用。
3)初始化。对静态变量和静态代码块执行初始化工作。

16.Java的垃圾回收机制:Java语言本身没有给开发人员提供显式释放已分配内存的方法,也就是说,开发人员不能实时的调用垃圾回收器,但开发
人员可以通过调用System.gc()方法来通知垃圾回收器运行。JVM也不能保证垃圾回收器马上就会运行。

17.Java的内存泄露情况:1)在堆中申请的空间没有被释放;2)对象已经不在被使用,但仍然在内存中保存。
垃圾回收机制的引用可以解决第一种情况。
会引起内存泄露的有以下四个方面:1)静态集合类 2)数据库连接,网络连接,IO连接等。 3)监听器 4)变量不合理的作用域 5)单例模式

18.Java中的堆栈:栈内主要用来存放基本数据类型与引用变量;堆用来存放运行时创建的对象,一般来讲通过new关键字创建的对象都存放在堆内存中。

19.Java Collections框架:包含了大量集合接口以及他们的实现类。如:List,Queue,Set,Stack和Map等。
其中Set,List,Map:
Set特点:集合中国的元素都不能重复,有两个实现类HashSet和TreeSet,其中TreeSet实现了SortedSet接口,是有序的。
List特点:可以保存重复的对象,LinkedList,ArrayList,Vector都实现了List接口。
Map特点:提供了一个从键映射到值的数据接口。它用于保存键值对。值可重复,键唯一。Java中HashMap,TreeMap,LinkedHashMap,WeakHashMap和IdentityHashMap都实现了此接口。

20.Iterator迭代器:三个重要方法
1)容器的iterator()返回一个Iterator然后通过Iterator的next方法返回第一个元素。
2)hasNext判断是否还有元素。
3)remove方法删除迭代器中国的元素。
注意事项:
1)迭代器只能正向遍历集合,适合获取移除元素,ListIterator继承于Iterator专门针对List可以从两个方向遍历List,同时支持元素修改。
2)迭代器具有线程安全问题,在使用迭代器遍历容器时,注意将对容器的操作放到synchronized代码块中。

21.LinkedList,ArrayList,Vector区别:
LinkedList相当于链表的数据结构,适合进行增删操作,ArrayList,Vector相当于数组数据结构,适合进行读取操作。
ArrayList,Vector的最大区别是Vector是线程安全的而ArrayList不是线程安全的,正是因为Vector是线程安全的,其性能上要略逊于ArrayList。

22.HashMap,TreeMap,HashTable,WeakHashMap有什么区别:
1)HashMap是HashTable的轻量级实现(非线程安全的),他们都完成了Map接口,主要区别是HashMap允许空键值,但最多只允许一个为空,HashTable不允许。
2)HashMap把HashTable 的contains方法去掉了,改成了containsValue和containsKey。HashTable 继承自Dictionary而HashMap是Map接口的实现。
3)HashTable 是线程安全的HashMap不是。
4)在Map中进行插入删除和定位元素HashMap是最好的选择。如果需要排序或者自定义顺序遍历键,TreeMap更好。如果要输入的顺序和输出的顺序一样LinkedHashMap更合适。

23.使用自定义类作为HashMap的键值时需要注意:
1)如果想根据对象的相关属性来自定义是否相等,就要重写equals和hashCode方法。
2)当自定义类的多项作为HashMap的key时,最好把这个类设计为不可变类。
3)如果两个对象相等,那么他们就有着相同的hashCode,反之不成立。

24.什么是线程,有什么优点,和进程有什么区别:
线程有四种状态:运行,就绪,挂起,结束。
进程是指一段正在执行的程序,而线程可以被看做是轻量级的进程,他是程序执行的最小单元,一个进程可以拥有多个线程,各个线程之间共享程序的内存空间(代码段,数据段,堆空间)
以及一些进程级的资源,但各个线程拥有自己的栈空间。
多线程的优点:
1)减少程序的响应时间。
2)与进程相比,线程的创建和切换开销更小。
3)多CPU或多核计算机本身具有多线程能力,如果使用单线程,则浪费计算机资源。
4)多线程能够简化程序的结构,便于理解。

25.实现同步的方法:利用synchronized关键字来实现同步:两种方式:
1)利用同步代码块实现同步。
2)利用同步方法实现(方法用synchronized关键字声明)。

26.Java实现多线程三种方法:
1)继承Thread重写run方法。
2)实现Runnable接口,并实现run方法。
3)实现Callable接口,重写call方法。

27.run方法与start方法有什么区别:start方法启动一个线程,通过run方法完成实际的操作,如果直接调用线程类的run方法,就会被当成一个普通函数来调用,程序仍然一个线程。

28:sleep方法和wait方法哟什么区别:
sleep方法是使线程暂停执行一段时间的方法,wait是使线程暂停执行的方法。
1)原理不同:sleep是Thread类的静态方法,是线程用来控制自身流程的,而wait方法是Object类的方法,用于线程间的通信,这个方法会使对象锁进程等待,知道其他线程调用notify方法
2)对锁的处理机制不同:wait方法会使线程放掉他锁占用的锁。
3)使用区域不同:wait方法必须放在同步控制方法或者同步语句块中使用。sleep必须捕获异常。

29:JDBC访问数据库一般的步骤:
1)加载JDBC驱动器。
2)加载JDBC驱动。
3)建立数据库连接,获取Connection对象。
4)建立Statement对象或者PreparedStatement对象。
5)执行SQL语句。
6)访问结果集Result对象。
7)依次关闭对象,释放资源。

30.PreparedStatement对象的优点:
1)效率更高(命令会被数据库进行编译和解析,放到命令缓冲区,下次会直接解析缓冲区中的命令,不会再编译一遍)。
2)代码的可读性和维护性更好。
3)安全性更好。