JavaSE-Java基础面试题
重载与重写的区别
重载:本类中,方法名相同,参数列表不同,(参数类型、参数顺序、参数个数),返回值类型可以不同,访问修饰符可不同
重写:子类中,方法名相同,参数不能改,返回值类型一致或其子类,访问权限大于等父类
== 与equals区别是什么
== :
在基本数据类型中 == 比较的是值;在引用数据类型中 == 比较的是地址
equals :
只能比较引用数据类型,默认比较地址,此时等同于 == ;但是String与Ingeter等方法重写了equals方法,变成了值的比较。
final关键字的作用
变量:final修饰的变量必须要初始化,不能再修改
方法:final修饰的方法不能被重写,可以被继承
类:final修饰的类不能被继承
static关键字
- 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享;
- 用来修饰成员方法,将其变为类方法,可以直接使用“类名.方法名”的方式调用,常用于工具类;
- 静态块用法,将多个类成员放在一起初始化,使得程序更加规整,其中理解对象的初始化过程非常关键;在创建对象时,static修饰的成员会首先被初始化,而且我们还可以看到,如果有多个static修饰的成员,那么会按照他们的先后位置进行初始化
- 静态导包用法,将类的方法直接导入到当前类中,从而直接使用“方法名”即可调用类方法,更加方便。
String、StringBuffer 和 StringBuilder 的区别是什么?
String:
String类中有final修饰,所有String对象不可变。
StringBuffer与StringBuilder:
这俩是继承AbstractBuilder类,AbstractBuilder类没有final,所以是可变的;
StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的;
StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
抽象类与接口的区别
- 接口中的变量默认用static和final修饰,不能有其他修饰的变量,必须给初始值
- 接口中的方法默认是public abstract,1.8之后可以有static 或者 default 修饰的方法体;
而抽象类中,可以有普通方法和抽象方法,并可以有main方法 - 类可以继承多个接口,但只能实现一个抽象类
- 抽象类可以有构造函数,接口没有
单例设计模式特点及分类(你了解的设计模式有什么(工厂设计模式 代理设计模式 装饰设计模式)
特点:
只能实例化一次对象
只能有本类实例化(构造器私有化)
如果想要调用,对外一定提供一个获取本类对象的方法
分类(线程不一样)
懒汉:多线程 安全
恶汉:单线程 快捷
了解的:
各有优缺点:
- 代理设计模式:为某对象提供一种代理
通过提供代理以控制对该对象的访问。(找一个更熟悉的代理来替我们操作)
代理模式的应用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
① 修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
② 采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
使用代理模式,可以将功能划分的更加清晰,有助于后期维护!
- 装饰设计模式:给一个对象增加一些功能,
要求是动态的,并且装饰对象和被装饰对象要实现同一个接口
装饰器模式的应用场景:
① 需要扩展一个类的功能。
② 动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。
缺点:产生过多相似的对象,不易排错
List、Set、Map 之间的区别
- List和Set继承Collection接口;Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同key,每个key只能映射一个value。
- List按对象进入的顺序保存对象,不做排序或编辑操作。List接口存储一组不唯一,可重复(可以有多个元素引用相同的对象),有序的对象。
- Set注重独一无二的性质,不允许重复的集合,对每个对象只接受一次,且无序。
- Map特点:元素按键值对存储,无放入顺序,不可重复。
List接口有三个实现类:LinkedList,ArrayList,Vector
- 同步性:LinkedList与ArrayList都是不同步,不保证线程安全,但效率高;而Vector线程同步,线程安全,但效率低
- 底层数据结构:ArrayList底层使用的是Object数组,支持随机访问;LinkedList底层使用的是双向链表数据结构,不支持随机访问,链表增删快,查找慢。
- 数据增长:ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。即Vector增长原来的一倍,ArrayList增加原来的0.5倍。
Set接口有两个实现类:HashSet,LinkedHashSet
HashSet:
为快速查找设计的Set。存入HashSet的对象必须定义hashCode()
- 底层由HashMap实现
- HashSet的值存放在HashMap的key上
- HashMap的value统一为PRESENT
LinkedHashSet
具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。
Map接口有三个实现类:HashMap,HashTable,LinkeHashMap
HashMap
HashMap是Hashtable的轻量级实现(非线程安全的实现)非线程安全,高效,支持null键值(key)
HashTable
HashTable线程安全,低效,不支持null
LinkeHashMap
类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一点。而在迭代访问时发而更快,因为它使用链表维护内部次序。
Java中实现多线程的三种方式
通过继承Thread类
创建Thread的子类来继承Thread类,并重写run()方法,在测试类中调用start()方法开启多线程
通过Runnable接口创建
创建Runnable接口的实现类,重写run()方法,并通过Thread类构造器建立关联,通过关联对象调用start()方法开启多线程
通过Callable和Future创建
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值;
使用FutureTask对象作为Thread对象的target创建并启动新线程;调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
两种方式实现多线程,哪一种更好(如何开启多线程?方式区别?)
如何开启多线程:
无论是继承,还是实现接口,都是调用Thread类中的start方法开启
方式区别:
相同点:无论是继承Thread类,还是实现Runnable接口,都是将多线程执行代码定义在run方法中,并都是通过start方法开启多线程操作
不同点:实现Runnable接口需要增加一步与Thread建立关联的操作,然后才能调用start方法
实际开发中,推荐使用Runnable接口方式,避免Java中单继承的局限性
线程有哪些基本状态
图源《Java 并发编程艺术》4.1.4节
线程的 run()和 start()有什么区别?
每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
start()方法来启动一个线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码; 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行状态, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。 如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接待用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。
sleep() 和 wait() 有什么区别
- sleep() 方法执行完成后,线程会自动苏醒,或者可以使用 wait(long timeout)超时后线程会自动苏醒;线程类(Thread)的静态方法,通过Thread打点调用;不能改变对象的机锁,线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象
- wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法,我们将以上操作称之为等待唤醒机制;当一个线程执行到wait()方法时,它就进入到一个和该对象相关的等待池,同时释放对象的机锁,使得其他线程能够访问
补充
notify唤醒线程池中先进入的
notifyAll唤醒线程池中所有的线程,然后这些被唤醒的线程再次“抢”占CPU执行权;哪个线程“抢”到,哪个就执行;而没抢到的再次回到线程池中;因此,有的线程可能刚被唤醒,就又等待了
什么是线程死锁
两个或两个以上线程因竞争资源,而陷入彼此相互等待,无外力作用下永远等待下去的现象
产生死锁的必要条件
- 互斥条件:该资源任意一个时刻只由一个线程占用。
- 请求与保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求时,因请求资源而阻塞,但对已获得的资源保持不放。
- 不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何避免线程死锁?
为了避免死锁,我们只要破坏产生死锁的四个条件中的其中一个就可以了。
- 破坏互斥条件:这个条件我们没有办法破坏,因为我们用锁本来就是想让他们互斥的(临界资源需要互斥访问)。
- 破坏请求与保持条件:一次性申请所有的资源。
- 破坏不剥夺条件:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
- 破坏循环等待条件:靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。
JavaSE-Java基础面试题的更多相关文章
- 经典的Java基础面试题集锦
经典的Java基础面试题集锦,欢迎收藏和分享. 问题:如果main方法被声明为private会怎样? 答案:能正常编译,但运行的时候会提示”main方法不是public的”. 问题:Java里的传引用 ...
- 非常全面的java基础笔试题
下面是java基础笔试题,当时我去笔试,做了1个小时(80道选择题,后面的简答题就没时间做了),结果很吓人,太挫了,最后被面试官忽悠去培训去了,呵呵.我偷偷把面试题弄了下来,用来学习吧,也希望能对你们 ...
- Java基础机试题
package day8;import java.util.Scanner;/** * Java基础机试题 * @author:lyrand * */public class convert { ...
- 100道Java基础面试题收集整理(附答案)
不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...
- 大数据学习--day04(选择结构、循环结构、大数据java基础面试题)
选择结构.循环结构.大数据java基础面试题 switch: 注意: byte short int char String(jdk1.7支持) 不能是 long float double boolea ...
- 一份最贴近真实面试的Java基础面试题
这是一份Java基础知识的面试题.在网上的关于Java的面试题数不胜数,但认真看过感觉大多数都没有实用性,有很多是面试官根本就不会问到的,那些已经脱离了实际开发的技术问题.而这份资料来源自一份个人觉得 ...
- 最新28道java基础面试题-上
28道java基础面试题 1.面向对象的特征有哪些方面? 答:面向对象的特征主要有以下几个方面: 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面.抽象只关注对象有哪 ...
- 28道java基础面试题-下
28道java基础面试题下 15.Java语言如何进行异常处理,关键字:throws.throw.try.catch.finally分别如何使用? 答:Java通过面向对象的方法进行异常处理,把各种不 ...
- Java基础面试题集(一)
Java基础面试题 一.面向对象编程(OOP) 7 二.常见的Java问题 7 2.1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? 7 2.2.JDK和JRE的区别是什么? ...
- Java基础面试题(史上最全、持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
随机推荐
- vue3 自学(一)基础知识学习和搭建一个脚手架
两年前曾自学过几天vue,那时候版本还是vue2,但后来项目中一直没用到,当时也觉得学习成本太高,便没有继续学习下去.初学者可以看下链接文章以前的吐槽~~ 学习 Vue ,从入门到放弃 最近部门决定升 ...
- 为什么每次下载后必须关闭掉IO流(十五)
读一个文件,忘记关闭了流,你在操作系统里对这个文件的写,删除等操作就会报错,告诉你这个文件被某个进程占用,这是为什么呢? java是从c++设计来的,但是无论是C语言还是C++,都需要手动释放内存,j ...
- java 8内置的四大核心函数式接口
Consumer<T> : 消费性接口 返回值 void accept(T t); public void happy(double money, Consumer<Double& ...
- odoo里的javascript学习---自定义插件
插件效果图 定义js odoo.define('auto_widget',function(require){ "use strict"//通过扩展AbstractField来扩展 ...
- Python如何将py文件打包成exe
安装pyinstaller 打开cmd窗口,输入pip install pyinstaller,命令行输出successfully表示成功. 生成exe文件 一.单个py文件 在py文件目录下,打开c ...
- frameset框架在.net网站中的小实现。
一般我们生成网页,为减少代码的开发量,通常将不变的网页部分进行重用.通用为三种方法: 1.frameset框架 2.用户自定义控件 3.母版页(消耗资源大,不追叙) 通常1,2两种方法常用. 1.fr ...
- js学习笔记之在数组中删除重复的元素自保留一个
遍历要删除的数组arr, 把元素分别放入另一个数组tmp中,在判断该元素在arr中不存在才允许放入tmp中 <script type="text/javascript"> ...
- synchronized 优化手段之锁膨胀机制!
synchronized 在 JDK 1.5 之前性能是比较低的,在那时我们通常会选择使用 Lock 来替代 synchronized.然而这个情况在 JDK 1.6 时就发生了改变,JDK 1.6 ...
- @FeignClient常用属性
@FeignClient(name = "gateway-test", value = "gateway-test", url = "localhos ...
- CF466C 题解
Description 给定一个数组,求有多少组 \(i,j\) 将整个数组分成和相等的三个数组. Solution 从左往右看一遍,记录每一个 \(i\) 使得 \(\sum_{k=1}^i a_k ...