Java面试题---->持续更新

1. 重载和重写的区别:

 1.重载发生在同一个类中,同名的方法中如果有不同的参数列表(个数不同,顺序不同,类型不同)则视为重载
 2.重写发生在子类和父类之间,重写之后的子类要求与父类被重写的方法有相同的返回类型,
   比父类重写的方法更好访问,且不能比父类重写的方法声明更多的异常。

2. String 和 StringBuffer、StringBuilder 的区别是什么

1.可变性
	String类使用关键字final修饰字符数组来保存字符串,所以String对象是不可变的
	StringBuffer和StringBuilder都继承自AbstractStringBuilder类,
	在AbstractStringBuilder类中是使用字符数组char[]保存字符串的,
	但是没有使用final关键字修饰,所以这两种对象是可变的。
2.线程安全性
	String类中的对象是不可变的,可以理解为常量,所以线程安全
	StringBuffer类对方法加了同步锁或者对调用的方法加了同步锁,所以线程安全。
	StringBuilder并没有对方法加同步锁,所以线程不安全。
3.性能
	每次对String类型进行改变的时候,都会重新创建新的String对象,然后将指针指向新的String对象。
	StringBuffer每次都会对StringBuffer对象自身操作,不会创建新的对象。
	相同情况下,使用StringBuilder会比使用StringBuffer提升10%-15%的性能,但却要冒多线程不安全的风险

3. == 与 equals 的区别?

	==对于基本数据类型和引用类型来说作用是不同的,
	对于基本数据类型来说,使用==比较的两个值是否相等,
	对于引用类型来说,使用==比较的是引用地址是否相等。

	equals本质是==,只是String,Integer等重写了equals(),把它变成了值比较

4. 说说自己是怎么使用synchronized 关键字,在项目中用到了吗?

修饰实例方法,作用于当前对象实例加锁,在进入同步代码块前获取对象实例的锁。
修饰静态方法,作用于当前类对象加锁,在进入同步代码块前获取类对象的锁。
修饰代码块,指定加锁对象,对给定加锁对象,在进入同步代码块前获取给定加锁对象的锁。


项目中使用:双重校验锁实现对象单例(线程安全)
public class Singleton { 
		private volatile static Singleton uniqueInstance; 
		private Singleton() { 
		}
		public static Singleton getUniqueInstance() {
		 //先判断对象是否已经实例过,没有实例化过才进入加锁代码 
		 if (uniqueInstance == null) { //类对象加锁 
		 	synchronized (Singleton.class) { 
		 		if (uniqueInstance == null) {
		  			uniqueInstance = new Singleton(); 
		  				} 
		 		 }
		   }
		   return uniqueInstance; 123456789101112131415161718
	}

5. 抽象类和接口的区别是什么?

1.实现:抽象类的子类使用extends继承父类,接口使用implements实现接口。

2.构造方法:抽象类可以有构造方法,接口不能有构造方法。

3.实现个数量:类可以实现多个接口,但只能继承一个抽象类(Java只支持单继承 )

4.访问修饰符:接口中的方法默认为public修饰,抽象类中的方法可以使用public和protected修饰,但使用private修饰则会报错,
  接口中除了final、static变量不能有其他变量,而抽象类则不一定

5.设计层面:抽象类是对类的抽象,是一种模板设计。接口是对行为的抽象,是一种行为规范。

6. Collection 和 Collections 有什么区别?

1.Collection是一个集合接口,它提供了对集合进行基本操作的通用接口方法,所有的集合都是它的子类,比如List、Set等。

2.Collecitons是一个包装类,提供了很多静态方法,不能被实例化,就像是一个包装类,
比如提供的排序方法:Collections.sort(list).

7. List、Set、Map 之间的区别是什么?

三者最主要的区别是 元素是否有序,是否允许元素重复

在这里插入图片描述
8. HashMap 和 Hashtable 有什么区别?

1.存储:HashMap允许key和value为null ,Hashtable不允许

2.线程安全:Hashtable线程安全,HashMap线程不安全

3.推荐使用: 在Hashtable的类注释中,可以看到Hashtable是一个保留类,不推荐使用,
		   推荐在单线程环境下使用HashMap,多线程中推荐使用ConcurrentHashMap;

9. 说一下 HashMap 的实现原理?

 HashMap是基于hash算法实现的,HashMap通过put(key,value)存储元素,使用get(key)获取元素。
 当传入key值时,通过key.hashcode()计算出hash值,根据hash值,将value保存在bucket。
 当计算出来的hash值相同时,则称之为hash冲突,通常使用链表和红黑树解决hash冲突。
 当冲突个数少时使用链表,否则使用红黑树。

10. 说一下 HashSet 的实现原理?

HashSet是基于HashMap实现的,HashSet底层使用HashMap保存数据的,因此HashSet的实现比较简单。
关于HashSet的操作,直接调用底层HashMap中的方法完成。HashSet不允许元素重复。

11.ArrayList和LinkedList的区别?

ArrayList:
	ArrayList是基于动态数组的,连续内存存储,随机访问元素。
	扩容机制:因为数组长度固定,超出数组长度就要重新创建新的数组,将老的数组中的元素复制到新的数组中。
	如果不是尾部插入数据,还会涉及到元素的移动,所以使用尾插法并指定初始容量,可以极大提升性能,甚至超过LinkedList.

LinkedList:
	LinkedList是基于链表,可以存储在分散的内存中,适合做添加、删除元素,不适合做查询,
	因为查询会逐一遍历元素,遍历LinkedList必须使用iterator接口,不能使用for循环,
	因为在for循环体内,通过get(i)获取元素时,都需要重新遍历list链表,性能消耗极大。

12.ConcurrentHashMap原理解析,jdk7和jdk8版本的区别

	jdk7:
		数据结构:ReentrantLock+Segement+HashEntry,每一个Segement中都包含一个HashEntry数组,每一个HashEntry
		        又是链表结构。
		元素查询:二次Hash,第一次Hash定位在Segement上,第二次查询定位在元素所在的链表头部。
		  锁:   采用Segement分段锁,Segement继承了ReentrantLock,锁定操作的Segement,不影响其他的Segement,
			    并发数为Segement的个数,可以通过构造函数指定,数组扩容时不会影响其他Segement,
		     	get方法无需加锁,Volatile保证。


    jdk8:
    		数据结构:红黑树+CAS+Node+Synchronized ,Node中的val和next都是用volatile修饰,保证可见性
    		元素查询: 替换和赋值都是用CAS
    		锁:     锁定链表的头节点,不影响其他元素的读写操作,锁粒度更细,效率更高,扩容时,阻塞所有读写操作,并发扩容。
    		读操作无锁:Node的val和next使用volatile修饰,保证读写操作对该变量互相可见
    		数组使用volatile修饰,保证扩容时被读线程感知。

13.哪些集合类是线程安全的?

	Hashtable、Stack、Vector都是线程安全的,HashMap是线程不安全,但自jdk1.5之后,随着java.util.concurrent并发包的出现,
	它们也有了自己对应的线程安全类,比如:HashMap的线程安全类就是ConcurrentHashMap。

14.创建线程有哪几种方式?

	1. 继承Thread实现run()
	2. 实现runnable接口
	3. 实现callable接口

15.说一下 runnable 和 callable有什么区别?

		runnable没有返回值,callable可以拿到返回值,callable可以看作是runnable的补充。

16. 线程有哪些状态?

在这里插入图片描述

	创建线程对象时,线程进入新建状态;当调用线程对象的start()方法时,线程进入就绪状态;
	当cpu获得时间片时,线程进入运行状态;
	当线程调用wait()或者sleep()方法时,线程进入阻塞状态;
	当休眠时间结束,或者线程调用notify()或者notifyAll()方法时,
	 	线程会从阻塞状态进入就绪状态,在重新获取时间片,进入运行状态;
	当线程执行完毕,或者因异常退出run()方法,则线程生命周期结束,进入终止状态。

17. sleep() 和wait() 有什么区别?

1. sleep()方法来自于Thread,而wait()方法来自于Object
2. sleep()不是放锁,而wait()释放锁。
3. 用法不同:sleep()时间到了会自动恢复,而wait()使用notify或notifyAll()直接唤醒

18. notify()和 notifyAll()有什么区别?

	notify唤醒一个线程,而notifyAll()唤醒全部线程。
	notifyAll()会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功,则继续执行,否则继续留在锁池等待锁被释放后,
		重新参与锁的竞争。
	notify只会唤醒一个线程,具体唤醒哪个线程,由虚拟机决定。

19.线程的 run() 和 start() 有什么区别?

start()方法用于启动线程,而run()方法用于执行线程的运行时代码,run()可以重复调用,而start()只能调用一次。

20.说一说几种常见的线程池及适用场景?

FixedThreadPool:
		用于固定线程数的线程池,适合用于负载较重的服务器。

SingleThreadExexutor:
		只会创建一个线程执行任务,适用于需要保证顺序执行各个任务,
		并且在任意时间点没有多线程活动的场景。

CachedThreadPool:
		是一个会根据需要调整线程数量的线程池。
		大小无界,适用于执行很多的短期异步任务的小程序,或负载较轻的服务器。

ScheduledThreadPool:
		继承自ThreadPoolExecutor.
		它主要用来在给定的延迟之后运行任务,或者定期执行任务。
		使用DelayQueue作为任务队列。

21. 线程池中 submit() 和 execute() 方法有什么区别?

	execute()适用于runnable类型任务
	submit()适用于runnable类型和callable类型任务
	runnable类型无返回值,callable类型任务可以拿到返回值。

22. 在 Java 程序中怎么保证多线程的运行安全

1. 使用安全类,比如java.until.concurrent并发类
2. 使用synchronized自动锁
3. 使用手动锁Lock

23. 什么是死锁?

当线程A持有独占锁a,并尝试去获取独占锁b的同时,线程B持有独占锁b,并尝试获取独占锁a的情况下,
就会发生由于线程AB互相持有对方所需要的锁,而发生阻塞现象,则称之为死锁。

24. 怎么防止死锁?

1. 尽量使用tryLock(long timeout, TimeUnit unit)下方法ReentrantLock或者ReentrantReadWriteLock设置超时时间,
   超时可以退出,可防止死锁。
2. 尽量使用java.until.concurrent下的并发安全类
3. 尽量降低锁的使用粒度,尽量不要几个功能使用同一把锁。
4. 尽量减少同步代码块

25. ThreadLocal 是什么?有哪些使用场景?

ThreadLock为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立的改变自己的变量副本,
		  而不影响其它线程所对应的变量副本。
应用场景:数据库连接,session管理。

26. synchronized 和 Lock 有什么区别?

1. synchronized 可以给类,代码块,方法加锁,而Lock只能给方法加锁。
2. synchronized 不需要手动获取锁和释放锁,发生异常就会自动释放锁,
  而lock需要手动释放锁和获取锁,如果使用不当,没有使用unlock释放锁,则会造成死锁。
3. 使用Lock可以知道有没有成功获取锁,而使用synchronized 却无法办到。

27. 什么是 Java 序列化?什么情况下需要序列化?

	Java序列化就是为了保存各种对象在内存中的状态,并且可以把保存的对象状态在内存中读出来

以下情况需要使用 Java 序列化: 
	1.使用socket在网络传输对象的时候
	2.使用RMI在网络传送对象的时候
	3.想把内存中的状态保存到文件或者数据库中的时候

28. 动态代理是什么?有哪些应用?

动态代理就是运行时动态生成代理类
应用:spring中的aop、java注解对象获取、rpc

29. 怎么实现动态代理?

1. 使用JDK原生动态代理和cglib动态代理
2. JDK原生动态代理是基于接口实现的,而cglib是基于继承当前类的子类实现的

30. 为什么要使用克隆?

克隆的对象可能包含一些已经修改后的属性,而使用new创建的对象都是初始化状态,
所以当需要一个新的对象保存当前对象的状态时,就靠克隆方法了。

31. session 和 cookie 有什么区别?

1. 存储位置不同:session是保存在服务器端,cookie保存在浏览器端
2. 安全性不同:cookie的安全性一般,可以被伪造和修改
3. 容量和个数限制:cookie有容量限制,每个站点下的cookie也容量限制
4. 存储的多样性:session可以保存在redis、数据库、应用程序中,cookie只能保存在浏览器端

32. 如何避免 SQL 注入?

1. 使用预处理 preparedstatement 
2. 使用正则表达式过滤掉字符中的特殊字符

33. throw 和 throws 的区别?

throw是真实抛出一个异常
throws是声明可能会抛出一个异常

34. final、finally、finalize 有什么区别?

1. final:是修饰符,如果修饰类,此类不能被继承;
   如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。

2. finally:是try{}catch{}finally{}最后一部分,表示不论发生任何情况都会执行,
  finally部分可以省略,
  但如果finally部分存在,则一定会执行finally里面的代码。

3. finalize:是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。

35. 常见的异常类有哪些?

1. NullPointerException 空指针异常
2. ClassNotFoundException 指定类不存在
3. NumberFormatException 字符串转换为数字异常
4. IndexOutOfBoundsException 数组下标越界异常
5. ClassCastException 数据类型转换异常
6. FileNotFoundException 文件未找到异常
7. NoSuchMethodException 方法不存在异常
8. IOException IO 异常
9.SocketException Socket异常

36. 说一下你熟悉的设计模式?

1. 单例模式:保证被创建一次,节省系统资源

2. 工厂模式:解耦代码

3. 观察者模式:定义对象之间一对多的依赖关系,
   这样一来,当一个改变时,所有的依赖着都会收到通知并自动改变
   
4. 外观模式:提供一个统一接口,用来访问子接口中的一群接口,
   外观定义了一个高层的接口,让子系统更容易使用。

5. 模板方法模式:定义一个算法骨架,而将一些具体步骤延申到子类中,
   模板方法模式使得子类在不改变算法结构的情况下,重新定义算法的执行步骤

6. 代理模式:代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。

37. spring框架使用了那些设计模式

1.spring的bean的创建默认使用单例模式
2.spring中获取bean对象通过的是工厂模式
3.spring的aop采用的是动态代理模式
4.在各种BeanFactory以及ApplicationContext实现中也都用到模板模式;

38. 为什么要使用 spring?

1. spring提供ioc技术,容器会帮你管理依赖的对象,从而不需要自己创建和管理依赖对象了,
	更轻松的实现了程序的解耦。

2. spring提供了事务支持,使得事务操作变的更加方便。
3. spring提供了面向切片编程,这样可以更方便的处理某一类的问题。
4. 更方便的框架集成,spring可以很方便的集成其他框架,比如MyBatis、hibernate等。

39. spring常用的注入方式有哪些?

1. setter属性注入
2. 构造方法注入
3. 注解方式注入

40. spring 事务实现方式有哪些?

1. 声明式事务:声明式事务也有两种实现方式,
   基于xml配置文件的方式和注解方式(在类上添加@Transaction注解)。

2. 编码方式:提供编码的形式管理和维护事务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值