Java面试题
2018-12-18 本文已影响2人
天道灬酬勤
1.抽象类与接口的区别
1.接口描述了方法的特征,不给出实现,解决java单继承问题,实现了强大的可接插性
2.抽象类提供了部分实现,不能被实例化,可以把公共代码移植到抽象类中
3.面向接口编程而不是面向具体编程。
4.开发中优先选择接口,继承抽象类之后无法在继承,丧失了灵活性。
2.常用的集合有哪些,谈谈你对他们的理解
区别:
1.set:无序,元素不可重复
2.list:有序列表存储,元素可重复
3.map:无序,元素可重复
理解:
1.set接口:有两个实现类,HashSet,LinkedHashSet
2.List接口:三个实现类
LinkedList:基于链表实现,内存散乱,增删快,查找慢。
Arraylist:非线程安全,效率高;基于数组,便于索引,不便于插入删除
Vector:基于线程安全,效率低,基于数组。
3.Map接口:有三个实现类
HashMap:非线程安全,高效,支出null。
HashTable:线程安全,低效,不支持null。
LinkedHashMap:是hashMap的一个子类,保存了记录的插入顺序
SortMap:把保存的记录根据键排序,默认升序
3.==和equals()的区别?
1.==用于比较基本数据类型,比较变量值是否相等,相同则为true。
2.equals()是用来比较两个对象是否相等,实际比较两个对象的内容是否相同。
4.方法重写和重载的区别?
1.方法重写:一般出现在继承中,子类对父类方法的重新实现,重写规则。
2.方法重载;在同一个类中,方法名字相同,参数不同,方法体不同
重载规则:方法名一致,参数列表的顺序,类型,分数不用,与返回值无关,存在子类与父类中,可以抛出不同的异
常,可以有不同的修饰符。
5.throw 和 throws的区别?
throw:
throw语句在方法体内,表示抛出异常,由体内语句处理。抛出的是一个实例,执行throw是一定抛出了异常
throws:
1)throws,语句用在方法声明后面,表示再抛出异常,由方法调用者处理
2)throws主要声明这个方法会抛出异常,让调用者知道要解决这个异常
3)throws 表示出现异常的一种可能性,并不一定发生这些异常
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 操作数据库异常
(9)java.lang.InstantiationException 实例化异常
(10)java.lang.NoSuchMethodException 方法不存在异常
7. final, finally, finalize 的区别
1)final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
2)Finally:异常处理语句结构的一部分,表示总是执行。
3)finalize:Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收
集时的其他资源回收,例如关闭文件等。
8. String、 StringBuffer、 StringBuilder 的区别?
(1)可变,不可变:
String:字符串常量,在修改时不会改变自身;若修改,等于重新生成新的字符串对象
StringBuffer:在修改时会改变对象自身,每次操作都是对 StringBuffer 对象本身进
行修改,不是生成新的对象使用场景:对字符串经常改变情况下,主要方法:append(),insert()等;
(2)线程是否安全:
String 对象定义后不可变,线程安全
StringBuffer 是线程安全的,执行效率较慢,适用于多线程下操作字符串缓冲区大量数据
StringBuilder 是线程不安全的,适用于单线程下操作字符串缓冲区大量数据
9. IO 流
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是
数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
10.Java 中有几种类型的流?分别是什么?
10.1 Java 中的流,可以从不同的角度进行分类。
按流的方向分:输入流和输出流。
按处理数据单位分:字节流和字符流。
按实现功能分:节点流和处理流。
10.2. 字节流和字符流的区别
1.字节流读取的时候,读到一个字节就返回一个字节; 字符流使用了字节流读到一个或多个字节时。先去查指定的编码表
,将查到的字符返回。
2.字节流可以处理所有类型数据,如:图片,MP3,AVI 视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,
就要优先考虑使用字符流,除此之外都用字节流。
11.break 和continue 的区别?
break 和 continue 都是用来控制循环,主要是终止循环;
break 用于完全结束一个循环,跳出循环体执行循环后面的语句;
continue 用于跳过本次循环,执行下次循环;
12.如何实现对象克隆?
1). 实现 Cloneable 接口并重写 Object 类中的 clone()方法;
2). 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深克隆
13.数据类型之间的转换?
1)字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应
基本类型;
2)基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;另一种方法是调用 String 类中的
valueOf()方法返回相应字符串
14.线程和进程的区别?
进程:具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行
资源分配和调度的一个独立单位
线程:是进程的一个实体,是 cpu 调度和分派的基本单位,是比进程更小的可以独立
运行的基本单位
15.编写多线程程序的几种实现方式(换个问法:创建多线程的方式)?
(1)通过继承 Thread 类
(2)通过实现 Runnable 接口(推荐使用,因为 Java 中是单继承,一个类只有 一个父类,若继承了 Thread 类,
就无法在继承其它类,显然实现 Runnable接口更为灵活)
(3)通过实现 Callable 接口(Java 5 之后)
16.请说出同步线程及线程调度相关的方法?
1)wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;
2)sleep(): 使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException 异常;
3)notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是
由 JVM 确定唤醒哪个线程,而且与优先级无关;
4)notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的
线程才能进入就绪状态;
17.启动一个线程是调用run()方法还是start()方法?
启动一个线程是调用 start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由 JVM 调度并执行,
这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。
18.什么是线程池,有哪些常用线程池?
就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁
线程而是放回池中,从而减少创建和销毁线程对象的开销。
常用线程池:
(1)newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序
执
行。
(2)newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大
大小。
(3)newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作
系统(或者说 JVM)能够创建的最大线程大小。
(4)newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。
(5)newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。
19.什么是死锁?
两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程 都陷入了无限的等待中。
20.如何确保 N 个线程可以访问N个资源同时又不导致死锁?
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,
如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
21.获得一个类的类对象有哪些方式?
1):类型.class,例如:String.class
2):对象.getClass(),例如:”hello”.getClass()
3):Class.forName(),例如:Class.forName(“java.lang.String”)
22.简述下你了解的设计模式?
一、设计模式的分类(加粗为常用)
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模
式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、
命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二、单例模式
单例设计模式
单例模式的好处:
1.某些类的创建比较频繁,对于一些大型的对象,这是一笔很大的开销。
2.省去了new的操作,节省了内存的开销,减轻了GC的压力。
3.有些情况只能用单例的设计模式,例如,一些交易核心,只能用一个对象,不然就会乱套了。
饿汉式:(线程安全的)
public class Singleton {
// 私有的构造方法
private Singleton(){
}
// 指向自己实例的私有静态引用
private static Singleton singleton = new Singleton();
// 以自己实例为返回值的静态的公有的方法
public static Singleton getInstance() {
return singleton;
}
}
懒汉式(线程不安全)
public class Singleton {
// 私有的构造方法
private Singleton() {
}
// 不建立对象
private static Singleton singleton = null;
// 以自己实例为返回值的静态的公有的方法
public static Singleton getInstance() {
if (singleton == null) {// 先判断是否为空
singleton = new Singleton();// 如果为空建立对象
}
return singleton;
}
}
三、工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其
创建过程延迟到子类进行。
主要解决:主要解决接口选择的问题。
何时使用:我们明确地计划不同条件下创建不同实例时。
如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
关键代码:创建过程在其子类执行
四、适配器模式
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不
兼容而不能一起工作的那些类可以一起工作。
主要解决:主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环
境要求的接口是现对象不能满足的。
何时使用:
1、系统需要使用现有的类,而此类的接口不符合系统的需要。
2、想要建立一个可以重复使用的类,用于与一些彼此之间
没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。
3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加
实体的需求下,增加一个适配器,在里面包容一个虎对象,实现飞的接口。)
如何解决:继承或依赖(推荐)。
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。