必须知道的Java面试题(January)

文章目录

1. 什么是Spring框架?Spring框架有哪些主要模块?
  1. Spring框架是按照设计模式精心打造的轻量级开源框架;
  2. Spring框架主要有数据访问/集成、web、AOP(面向切面编程)、Aspects、工具、消息、核心容器、测试
2. 使用Spring框架能带来哪些好处?
  1. 方便解耦 便于开发
  2. 支持面向切面编程
  3. 支持声明式事务
  4. 方便测试
  5. 方便集成各种优秀框架
  6. 降低JavaEE API 的使用难道
3.什么是控制反转(IOC)?什么是依赖注入?依赖注入的实现方式有哪几种?
  1. 控制反转是一种面向对象编程中的一种设计原则 可以降低代码间的耦合度;
  2. 依赖注入是控制反转的基础;
  3. 依赖注入的实现方式有构造器注入setter方法注入接口注入
4. 请解释下Spring框架中的IOC?
  1. BeanFactory 是Spring IoC容器的具体实现,用来包装和管理前面提到的各种bean。
  2. BeanFactory接口是Spring IoC 容器的核心接口。
5. BeanFactory和ApplicationContext有什么区别?

BeanFactory是Spring框架的最底层接口 提供实例化对象和拿对象的功能;
ApplicationContext(应用上下文)是继承BeanFactory的接口拥有更多功能例如:

  1. 提供了支持国际化的文本消息
  2. 统一的资源文件读取方式
  3. 已在监听器中注册的bean的事件
6. Spring有几种配置方式?

将Spring配置到应用开发中有以下三种方式:

  1. 基于XML的配置
  2. 基于注解的配置
  3. 基于Java的配置
7. 如何用基于XML配置的方式配置Spring?
  1. Spring的XML配置方式是使用被Spring命名空间的所支持的一系列的XML标签来实现的。
  2. Spring有以下主要的命名空间:context、beans、jdbc、tx、aop、mvc和aso。
8. 如何用基于Java配置的方式配置Spring

Spring对Java配置的支持是由@Configuration注解和@Bean注解来实现的。

9. 如何用基于注解的方式配置Spring?

用注解的方式来替代XML方式的bean描述,可以将bean描述转移到组件类的内部,只需要在相关类上、方法上或者字段声明上使用注解即可。

10. 请解释Spring Bean 的生命周期?

Spring bean factory 负责管理在spring容器中被创建的bean的生命周期。
Bean的生命周期由两组回调(call back)方法组成

  1. 初始化之后调用的回调方法。
  2. 销毁之前调用的回调方法。
11. Spring Bean的作用域之间有什么区别?

Spring容器中的bean可以分为5个范围。

  1. singleton:这种bean范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个bean的实例。
  2. prototype:原形范围与单例范围相反,为每一个bean请求提供一个实例。
  3. request:在请求bean范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后,bean会失效并被垃圾回收器回收。
  4. Session:与请求范围类似,确保每个session中有一个bean的实例,在session过期后,bean会随之失效。
  5. global-session:global-session和Portlet应用相关。当你的应用部署在Portlet容器中工作时,它包含很多portlet。如果你想要声明让所有的portlet共用全局的存储变量的话,那么这全局变量需要存储在global-session中。
12. 什么是Spring inner beans?
  1. 在Spring框架中,无论何时bean被使用时,当仅被调用了一个属性。
  2. 一个明智的做法是将这个bean声明为内部bean。
  3. 内部bean可以用setter注入“属性”和构造方法注入“构造参数”的方式来实现。
13. Spring框架中的单例Beans是线程安全吗?
  1. 在某种程度上说Spring的单例bean是线程安全的。
  2. 如果你的bean有多种状态的话(比如 View Model 对象),就需要自行保证线程安全。
14. 请举例说明如何在Spring中注入一个Java Collection?

Spring提供了以下四种集合类的配置元素:

• <list> : 该标签用来装配可重复的list值。
• <set> : 该标签用来装配没有重复的set值。
• <map>: 该标签可用来注入键和值可以为任何类型的键值对。
• <props> : 该标签支持注入键和值都是字符串类型的键值对。

15. 如何向Spring Bean中注入一个Java.util.Properties?

使用<props>标签

16. 请解释自动装配模式的区别?

在Spring框架中共有5种自动装配。

  1. no:这是Spring框架的默认设置,在该设置下自动装配是关闭的,开发者需要自行在bean定义中用标签明确的设置依赖关系。
  2. byName:该选项可以根据bean名称设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
  3. byType:该选项可以根据bean类型设置依赖关系。当向一个bean中自动装配一个属性时,容器将根据bean的类型自动在在配置文件中查询一个匹配的bean。如果找到的话,就装配这个属性,如果没找到的话就报错。
  4. constructor:造器的自动装配和byType模式类似,但是仅仅适用于与有构造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。
  5. autodetect:该模式自动探测使用构造器自动装配或者byType自动装配。首先,首先会尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在bean内部没有找到相应的构造器或者是无参构造器,容器就会自动选择byTpe的自动装配方式。
17. 如何开启基于注解的自动装配?

使用@Autowired注解

18. 请举例解释@Required 注解?

如果没有属性被用 @Required 注解过的话,后置处理器会抛出一个BeanInitializationException 异常。

19. 请举例解释@Autowried 注解?
  1. 可以在设值方法上使用@Autowired注解来替代配置文件中的<property>元素。
  2. 当Spring容器在setter方法上找到@Autowired注解时,会尝试用byType 自动装配
20. 请举例说明@Qualifier注解?
  1. @Qualifier注解意味着可以在被标注bean的字段上可以自动装配
  2. @Qualifier注解可以用来取消Spring不能取消的bean应用
21. 构造方法注入和设值注入有什么区别?
  1. 在设值注入方法支持大部分的依赖注入,如果我们仅需要注入int、string和long型的变量,我们不要用设值的方法注入。对于基本类型,如果我们没有注入的话,可以为基本类型设置默认值。在构造方法注入不支持大部分的依赖注入,因为在调用构造方法中必须传入正确的构造参数,否则的话为报错
  2. 设值注入不会重写构造方法的值。如果我们对同一个变量同时使用了构造方法注入又使用了设置方法注入的话,那么构造方法将不能覆盖由设值方法注入的值。很明显,因为构造方法尽在对象被创建时调用。
  3. 在使用设值注入时有可能还不能保证某种依赖是否已经被注入,也就是说这时对象的依赖关系有可能是不完整的。而在另一种情况下,构造器注入则不允许生成依赖关系不完整的对象。
  4. 在设值注入时如果对象A和对象B互相依赖,在创建对象A时Spring会抛出sObjectCurrentlyInCreationException异常,因为在B对象被创建之前A对象是不能被创建的,反之亦然。所以Spring用设值注入的方法解决了循环依赖的问题,因对象的设值方法是在对象被创建之前被调用的。
22. Spring框架中有哪些不同类型的事件?
  1. Spring的ApplicationContext 提供了支持事件和代码中监听器的功能。
  2. 我们可以创建bean用来监听在ApplicationContext 中发布的事件。
  3. ApplicationEvent类和在ApplicationContext接口中处理的事件,如果一个bean实现了ApplicationListener接口,当一个 ApplicationEvent 被发布以后,bean会自动被通知。
  4. Spring 提供了以下5中标准的事件:
    1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
    2. 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
    3. 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
    4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
    5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。
23. FileSystemResource和ClassPathResource有何区别?

ClassPathResource在环境变量中读取配置文件,FileSystemResource在配置文件中读取配置文件。

24. Spring框架中都用到了哪些设计模式?
  1. 代理模式—在AOP和remoting中被用的比较多。
  2. 单例模式—在spring配置文件中定义的bean默认为单例模式。
  3. 工厂模式—BeanFactory用来创建对象的实例。
  4. 模板方法—用来解决代码重复的问题。
25. 面向对象(oop)的三大特征?

继承、多态、封装

26. 多态的好处?
  1. 可替换性:多态对已存在代码具有可替换性
  2. 可扩充性:增加新的子类不影响已经存在的类结构
  3. 接口性:多态是超类通过方法签名,向子类提供一个公共接口,由子类来完善或者重写它来实现的。
  4. 灵活性
  5. 简化性
27. 代码中如何实现多态?
  1. 接口实现
  2. 继承父类重写方法
  3. 同一类中进行方法重载
28. 虚拟机是如何实现多态的?

动态绑定技术(dynamic binding),执行期间判断所引用对象的实际类型,根据实际类型调用对应的方法。

29. 接口的意义?

接口的意义用三个词就可以概括:规范,扩展,回调。

30. 抽象类的意义?
  1. 为其他子类提供一个公共的类型
  2. 封装子类中重复定义的内容
  3. 定义抽象方法,子类虽然有不同的实现,但是定义时一致的
31. 接口和抽象类的区别?
  1. 抽象类可以有默认的方法实现;接口没有
  2. 抽象类可以有构造器;接口没有
  3. 一个子类只存在一个父类;一个子类可以存在多个接口
32. 父类的静态方法能否被子类重写?

不能。重写只适用于实例方法,不能用于静态方法,而子类当中含有和父类相同签名的静态方法,我们一般称之为隐藏。

33. 什么是不可变对象?

不可变对象指对象一旦被创建,状态就不能再改变。

34. 静态变量和实例变量的区别?

静态变量存储在方法区,属于类所有。实例变量存储在堆当中,其引用存在当前线程栈。

35. 能否创建一个包含可变对象的不可变对象?

当然可以创建一个包含可变对象的不可变对象的,你只需要谨慎一点,不要共享可变对象的引用就可以了,如果需要变化时, 就返回原对象的一个拷贝。最常见的例子就是对象中包含一个日期对象的引用。

36. switch中能否使用string做参数?
  1. 在 idk 1.7 之前,switch 只能支持 byte, short, char, int 或者其对应的封装类以及 Enum 类型。
  2. 从 idk 1.7 之后 switch 开始支持 String。
37. switch能否作用在byte、long中?

可以用在 byte 上,但是不能用在 long 上。

38. 你对String对象的intern()熟悉吗?

intern()方法会首先从常量池中查找是否存在该常量值,如果常量池中不存在则现在常量池中创建,如果已经存在则直接返回。

39. Object中有哪些公共方法?
  1. equals()
  2. clone()
  3. getClass()
  4. notify(),notifyAll(),wait()
  5. toString
40. Java当中的四种引用?

强引用软引用弱引用虚引用。不同的引用类型主要体现在 GC 上

41. WeakReference与SoftReference的区别?

这点在四种引用类型中已经做了解释,这里简单说明一下即可:虽 然 WeakReference 与 SoftReference 都 有 利 于 提 高 GC 和 内 存 的 效 率 , 但 是WeakReference ,一旦失去最后一个强引用,就会被 GC 回收,而软引用虽然不能阻止被回收,但是可以延迟到 JVM 内存不足的时候。

42. 为什么要有不同的引用类型?

在 Java 中有时候我们需要适当的控制对象被回收的时机,因此就诞生了不同的引用类型

43. ==和equals()的区别?
  1. ==是运算符,用于比较两个变量是否相等,而 equals 是 Object 类的方法,用于比较两个对象是否相等。
  2. 对象用==比较时,比较的是内存地址,如果需要比较对象内容,需要重写 equal 方法。
44. equals()和hashCode()的联系?
  1. hashCode()是 Object 类的一个方法,返回一个哈希值
  2. 如果两个对象根据 equal()方法比较相等,那么调用这两个对象中任意一个对象的 hashCode()方法必须产生相同的哈希值。
45. 有没有可能两个不相等的对象有相同的hashcode?
  1. 有可能,两个不相等的对象可能会有相同的 hashcode 值,这就是为什么在 hashmap 中会有冲突。
  2. 如果两个对象相等,必须有相同的 hashcode 值,反之不成立。
46. 可以在hashCode中使用随机数字吗?

不行,因为同一对象的 hashcode 值必须是相同的

47. 3*0.1==0.3返回值是什么?

false,因为有些浮点数不能完全精确的表示出来。

48. a=a+b与a+=b有什么区别?

+=操作符会进行隐式自动类型转换,此处 a+=b 隐式的将加操作的结果类型强制转换为持有
结果的类型,而 a=a+b 则不会自动进行类型转换。

49. short s1= 1;s1 = s1+1;是否有错?s1+=1;呢?

有错误,short 类型在进行运算时会自动提升为 int 类型,也就是说 s1+1 的运算结果是 int
类型。

50. &和&&的区别?
  1. 首先记住&是位操作,而&&是逻辑运算符
  2. 另外需要记住逻辑运算符具有短路特性,而&不具备短路特性。
51. 一个java文件内部可以有类?

只能有一个 public 公共类,但是可以有多个 default 修饰的类。

52. 如何正确的退出多层嵌套循环?

使用break;

53. 内部类的作用?

内部类提供了更好的封装,除了该外围类,其他类都不能访问。

54. final;finalize;finally的不同之处?
  1. final 是一个修饰符,可以修饰变量、方法和类。
  2. finalize 方法是在对象被回收之前调用的方法,给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证。
  3. finally 是一个关键字,与 try 和 catch 一起用于异常的处理。
55. clone()是哪个类的方法?

object类

56. 深拷贝和浅拷贝的区别?

浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象。

深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

57. static都有哪些用法?

static 关键字这两个基本的用法:静态变量静态方法。也就是被 static所修饰的变量/方法都属于类的静态资源,类实例所共享。

58. final有哪些用法?
  1. 被 final 修饰的类不可以被继承
  2. 被 final 修饰的方法不可以被重写
  3. 被 final 修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。
59. java中int;char;long各占多少字节?

(1字节占8位)
int 4;char 2;long 8

60. 64位的JVM中,int的长度是多少?

Java 中,int 类型变量的长度是一个固定值,与平台无关,都是 32 位。意思就是说,在 32
位 和 64 位 的 Java 虚拟机中,int 类型的长度是相同的。

61. int和Integer的区别?
  1. Integer 是 int 的包装类型,在拆箱和装箱中,二者自动转换。
  2. int 是基本类型,直接存数值,而 integer 是对象,用一个引用指向这个对象。
62. int和Integer谁占用的内存更多?

Integer 对象会占用更多的内存。Integer 是一个对象,需要存储对象的元数据。但是 int 是一个原始类型的数据,所以占用的空间更少。

63. Stirng;StringBuffer和StringBuilder区别?
  • String 是字符串常量,final 修饰;
  • StringBuffer 字符串变量(线程安全);
  • StringBuilder 字符串变量(线程不安全)。
64. String和StringBuffer?
  • String 和 StringBuffer 主要区别是性能:String 是不可变对象,每次对 String 类型进行操作都等同于产生了一个新的 String 对象,然后指向新的 String 对象。所以尽量不在对 String 进行大量的拼接操作,否则会产生很多临时对象,导致 GC 开始工作,影响系统性能。

  • StringBuffer 是对对象本身操作,而不是产生新的对象,因此在有大量拼接的情况下,我们建议使用 StringBuffer。

65. StringBuffer和StringBuilder?

StringBuffer 是线程安全的可变字符串,其内部实现是可变数组。StringBuilder 是 jdk 1.5 新增的,其功能和 StringBuffer 类似,但是非线程安全。因此,在没有多线程问题的前提下,使用 StringBuilder 会取得更好的性能

66. 什么是编译器常量?使用它有什么风险?

公共静态不可变(public static final )变量也就是我们所说的编译期常量

67. java当中使用什么类型表示价格比较好?

如果不是特别关心内存和性能的话,使用 BigDecimal,否则使用预定义精度的 double 类型。

68. 如何将byte转为String?

可以使用 String 接收 byte[] 参数的构造器来进行转换,需要注意的点是要使用的正确的编码,否则会使用平台默认编码,这个编码可能跟原来的编码相同,也可能不同。

69. 垃圾回收算法有哪些?

垃圾回收从理论上非常容易理解,具体的方法有以下几种:

  1. 标记-清除
  2. 标记-复制
  3. 标记-整理
  4. 分代回收
70. 如何判断一个对象是否应该被回收?

这就是所谓的对象存活性判断,常用的方法有两种:1.引用计数法; 2.对象可达性分析。

71. 简单的解析一下垃圾回收?
  • Java 垃圾回收机制最基本的做法是分代回收。
  • 内存中的区域被划分成不同的世代,对象根据其存活的时间被保存在对应世代的区域中。
  • 一般的实现是划分成 3 个世代:年轻、年老和永久
  • 内存的分配是发生在年轻世代中的。
  • 当一个对象存活时间足够长的时候,它就会被复制到年老世代中。对于不同的世代可以使用不同的垃圾回收算法。
72. 调用System.gc()会发什么?

通知 GC(垃圾回收) 开始工作,但是 GC 真正开始的时间不确定。

73. 说说进程;线程;协程之间的区别?

进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。

74. 守护线程和非守护线程的区别?

程序运行完毕,jvm 会等待非守护线程完成后关闭,但是 jvm 不会等待守护线程。守护线程最典型的例子就是 GC 线程。

75. 什么是多线程上下文切换?

多线程的上下文切换是指 CPU 控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程。

76. 创建线程的两种方式?区别?

通过实现 java.lang.Runnable 接口或者通过扩展 java.lang.Thread 类。相比扩展 Thread实现Runnable 接口可能更优.原因有二:

  • Java 不支持多继承。因此扩展 Thread 类就代表这个子类不能扩展其他类。
  • 而实现Runnable 接口的类还可能扩展另一个类。
  • 类可能只要求可执行即可,因此继承整个 Thread 类的开销过大。
77. Thread类中的start()和run()方法有什么区别?
  1. start()方法被用来启动新创建的线程,而且 start()内部调用了 run()方法,这和直接调用 run()方法的效果不一样。
  2. 当你调用 run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程
78. 怎么检测一个线程是否持有对象监视器?

Thread 类提供了一个 holdsLock(Object obj)方法,当且仅当对象 obj 的监视器被某条线程持有的时候才会返回 true,注意这是一个 static 方法,这意味着”某条线程”指的是当前线程。

79. Runnable和Callable的区别?

Runnable 接口中的 run()方法的返回值是 void,它做的事情只是纯粹地去执行 run()方法中的代码而已;Callable 接口中的 call()方法是有返回值的,是一个泛型,和 Future、FutureTask配合可以用来获取异步执行的结果。

80. 什么导致线程阻塞?

阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)

81. wait(),notify()和 suspend(),resume()之间的区别?

初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。

82. 产生死锁的条件?
  1. 互斥条件:一个资源每次只能被一个进程使用。
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
83. 为什么 wait()方法和 notify()/notifyAll()方法要在同步块中被调用?

这是 JDK 强制的,wait()方法和 notify()/notifyAll()方法在调用前都必须先获得对象的锁

84. wait()方法和 notify()/notifyAll()方法在放弃对象监视器时有什么 区别?

wait()方法立即释放对象监视器,notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。

85. wait()与 sleep()的区别?

sleep()来自 Thread 类,和 wait()来自 Object 类。调用 sleep()方法的过程中,线程不会释放对象锁。而 调用 wait 方法线程会释放对象锁

86. 为什么 wait, nofity 和 nofityAll 这些方法不放在 Thread 类当中?

一个很明显的原因是 JAVA 提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。

87. 怎么唤醒一个阻塞的线程?

如果线程是因为调用了 wait()、sleep()或者 join()方法而导致的阻塞,可以中断线程,并且通过抛出 InterruptedException 来唤醒它;如果线程遇到了 IO 阻塞,无能为力,因为 IO 是操作系统实现的,Java 代码并没有办法直接接触到操作系统。

88. synchronized 和 ReentrantLock 的区别?

synchronized 是和 if、else、for、while 一样的关键字,ReentrantLock 是类,这是二者的本质区别。

89. FutureTask 是什么?

FutureTask 表示一个异步运算的任务

90. 一个线程如果出现了运行时异常怎么办?
  1. 如果这个异常没有被捕获的话,这个线程就停止执行了。
  2. 另外重要的一点是:如果这个线程持有某个某个对象的监视器,那么这个对象监视器会被立即释放。
91. Java当中有哪几种锁?
  1. 自旋锁
  2. 偏向锁
  3. 轻量级锁
92. 如何在两个线程间共享数据?

通过在线程之间共享对象就可以了,然后通过 wait/notify/notifyAll、await/signal/signalAll 进行唤起和等待,比方说阻塞队列 BlockingQueue 就是为线程之间共享数据而设计的。

93. 如何正确的使用wait()?使用if还是while?

wait() 方法应该在循环调用,因为当线程获取到 CPU 开始执行的时候,其他条件可能还没有满足,所以在处理前,循环检测条件是否满足会更好。

94. 什么是线程局部变量ThreadLocal?
  1. 线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。
  2. Java提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。
95. 生产者消费者模型的作用是什么?
  1. 通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率,这是生
    产者消费者模型最重要的作用。
  2. 解耦,这是生产者消费者模型附带的作用,解耦意味着生产者和消费者之间的联系少,
    联系越少越可以独自发展而不需要收到相互的制约。
96. 为什么要使用线程池?
  1. 避免频繁地创建和销毁线程,达到线程对象的重用。
  2. 另外,使用线程池还可以根据项目灵活地控制并发的数目。
97. Java中用到的线程调度算法是什么?

抢占式。一个线程用完 CPU 之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

98. Thread.sleep(0)的作用是什么?

由于 Java 采用抢占式的线程调度算法,因此可能会出现某条线程常常获取到 CPU 控制权的情况,为了让某些优先级比较低的线程也能获取到 CPU 控制权,可以使用 Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡 CPU 控制权的一种操作。

99. 什么是CAS?

CAS,全称为 Compare and Swap,即比较-替换

100. 什么是乐观锁和悲观锁?
  • 乐观锁:乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。
  • 悲观锁:悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像 synchronized,不管三七二十一,直接上了锁就操作资源了。
101. Java中的++操作符线程安全吗?

不是线程安全的操作。它涉及到多个指令,如读取变量值,增加,然后存储回内存,这个过程可能会出现多个线程交差。

102. poll()方法和remove()方法区别?

poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常

103. WeakHashMap 与 HashMap 的区别是什么?

WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key对象没有任何引用时,key/value 将会被回收。

104. ArrayList 和 LinkedList 的区别?

最明显的区别是 ArrayList 底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。

105. ArrayList 和 Array 有什么区别?
  • Array 可以容纳基本类型和对象,而 ArrayList 只能容纳对象
  • Array 是指定大小的,而 ArrayList 大小是固定的
106. Comparator 和 Comparable 的区别?
  • Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。
  • Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。
107. 如何实现集合排序?

可以使用有序集合,如 TreeSetTreeMap,你也可以使用有顺序的的集合,如 list,然后通过 Collections.sort() 来排序。

108. 如何打印数组内容?

可以使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组

109. LinkedList 的是单向链表还是双向?

双向循环链表

110. TreeMap的实现原理?

采用红黑树实现

111. 遍历 ArrayList 时如何正确移除一个元素?

ArrayList 的 remove()

112. SimpleDateFormat 是线程安全的吗?

DateFormat 的所有实现,包括 SimpleDateFormat 都不是线程安全的

113. 如何格式化日期?

可以使用 SimpleDateFormat 类或者 joda-time 库来格式日期。DateFormat 类允许你使用多种流行的格式来格式化日期。

114. Java 中,Serializable 与 Externalizable 的区别?
  • Serializable 接口是一个序列化 Java 类的接口,以便于它们可以在网络上传输或者可以将它们的状态保存在磁盘上,是 JVM 内嵌的默认序列化方式,成本高、脆弱而且不安全。
  • Externalizable 允许你控制整个序列化过程,指定特定的二进制格式,增加安全机制
115. JVM特性?

平台无关性. Java 语言的一个非常重要的特点就是与平台的无关性。

116. 简述堆和栈的区别?

VM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。

117. 简述 JVM 内存分配?
  • 基本数据类型比变量和对象的引用都是在栈分配的。
  • 堆内存用来存放由 new 创建的对象和数组
  • 类变量(static 修饰的变量),程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中。
  • 实例变量:当你使用 java 关键字 new 的时候,系统在堆中开辟并不一定是连续的空间分配给变量,是根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”,实例变量的生命周期–当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存。
  • 局部变量: 由声明在某方法,或某代码段里(比如 for 循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放。
118. JDK 1.8 特性?
  1. Lambda 表达式,允许像对象一样传递匿名函数
  2. Stream API,充分利用现代多核 CPU,可以写出很简洁的代码
  3. Date 与 Time API,最终,有一个稳定、简单的日期和时间库可供你使用
  4. 扩展方法,现在,接口中可以有静态、默认方法。
  5. 重复注解,现在你可以将相同的注解在同一类型上使用多次。
119. Maven 和 ANT 有什么区别?

虽然两者都是构建工具,都用于创建 Java 应用,但是 Maven 做的事情更多

120. 多线程有什么用?
  1. 发挥多核CPU 的优势
  2. 防止阻塞
  3. 便与建模
121. 线程和进程的区别是什么?

进程和线程的主要差别在于它们是不同的操作系统资源管理方式

122. Java实现线程有哪几种方式?
  1. 继承 Thread 类实现多线程
  2. 实现 Runnable 接口方式实现多线程
123. 启动线程方法start()和run()有什么区别?
  1. 只有调用了 start()方法,才会表现出多线程的特性,不同线程的 run()方法里面的代码交替执行。
  2. 如果只是调用 run()方法,那么代码还是同步执行的,必须等待一个线程的 run()方法里面的代码全部执行完毕之后,另外一个线程才可以执行其 run()方法里面的代码。
124. 怎么终止一个线程?如何优雅地终止线程?

stop 终止,不推荐。

125. 一个线程的生命周期有哪几种状态?他们它们之间如何流转的?
  • NEW:毫无疑问表示的是刚创建的线程,还没有开始启动。
  • RUNNABLE: 表示线程已经触发 start()方式调用,线程正式启动,线程处于运行中状态。
  • BLOCKED:表示线程阻塞,等待获取锁,如碰到 synchronized、lock 等关键字等12占用临界区的情况,一旦获取到锁就进行 RUNNABLE 状态继续运行。
  • WAITING:表示线程处于无限制等待状态,等待一个特殊的事件来重新唤醒,如通过wait()方法进行等待的线程等待一个 notify()或者 notifyAll()方法,通过 join()方法进行等待的线程等待目标线程运行结束而唤醒,一旦通过相关事件唤醒线程,线程就进入了 RUNNABLE 状态继续运行。
  • TIMED_WAITING:表示线程进入了一个有时限的等待,如 sleep(3000),等待 3 秒后线程重新进行 RUNNABLE 状态继续运行。
  • TERMINATED:表示线程执行完毕后,进行终止状态。需要注意的是,一旦线程通过 start 方法启动后就再也不能回到初始 NEW 状态,线程终止后也不能再回到RUNNABLE 状态
126. 线程中的wait()和sleep()方法有什么区别?

sleep 方法和 wait 方法都可以用来放弃 CPU 一定的时间,不同点在于如果线程持有某个对象的监视器,sleep 方法不会放弃这个对象的监视器,wait方法会放弃这个对象的监视器

127. 多线程同步有哪几种方法?

Synchronized 关键字,Lock 锁实现,分布式锁等

128. 什么是死锁?如何避免死锁?

死锁就是两个线程相互等待对方释放对象锁

129. 多线程之间如何进行通信?

wait/notify

130. 线程怎样拿到返回结果?

实现Callable 接口。

131. 新建T1、T2、T3三个线程如何保证它们按顺序执行?

用 join 方法。

132. 为什么要使用线程池?

因为每次创建和销毁一个线程都是要消耗系统资源的,如果为每个任务都创建线程这无疑是一个很大的性能瓶颈。所以,线程池中的线程复用极大节省了系统资源

133. 线程池启动线程submit()和execute()方法有什么不同?
  • execute 没有返回值,如果不需要知道线程的结果就使用 execute 方法,性能会好很多。
  • submit 返回一个 Future 对象,如果想知道线程结果就使用 submit 提交,而且它能在主线程中通过 Future 的 get 方法捕获线程中的异常。
134. 什么是活锁、饥饿、无锁、死锁?
  • 死锁:相互占用对方的资源的锁,而又相互等对方释放锁
  • 活锁:当多线程中出现了相互谦让,都主动将资源释放给别的线程使用
  • 饥饿:优先级高的线程一直抢占优先级低线程的资源,导致低优先级线程无法得到执行
  • 无锁:没有对资源进行锁定,即所有的线程都能访问并修改同一个资源
135. 什么是原子性、可见性、有序性?
  • 原子性:同一时间只有一个线程对一个变量进行操作
  • 可见性:其他线程是否可以看见该共享变量修改后的值
  • 有序性:程序是按代码顺序执行的
136. 什么是守护线程?有什么用?

当用户线程全部执行完结束之后,守护线程才会跟着结束;如果一个应用内只存在一个守护线程,没有用户线程,守护线程自然会退出。

137. 一个线程运行时发生异常会怎样?

异常没有被捕获该线程将会停止执行

138. Synchronized有哪几种用法?

锁类、锁方法、锁代码块。

139. Fork/Join框架是干什么的?

大任务自动分散小任务,并发执行,合并小任务结果。

140. 线程过多会造成什么异常?

线程过多会造成栈溢出,也有可能会造成堆异常

141. 怎样检测一个线程是否拥有锁?

java.lang.Thread#holdsLock 方法

142. jdk中排查多线程问题用什么命令?

jstack

143. 线程同步需要注意什么?
  1. 尽量缩小同步的范围,增加系统吞吐量。
  2. 分布式同步锁无意义,要使用分布式锁。
  3. 防止死锁,注意加锁顺序。
144. 线程wait()方法使用有什么前提?

要在同步块中使用。

145. 线程之间如何传递数据?

通 过 在 线 程 之 间 共 享 对 象 就 可 以 了 , 然 后 通 过 wait/notify/notifyAll 、await/signal/signalAll 进行唤起和等待,

146. 怎么唤醒一个阻塞的线程?

通过抛出 InterruptedException 来唤醒它;如果线程遇到了 IO 阻塞,无能为力,因为 IO是操作系统实现的,Java 代码并没有办法直接接触到操作系统。

147. 不可变对象对多线程有什么帮助?

不可变对象保证了对象的内存可见性,对不可变对象的读取不需要进行额外的同步手段提升了代码执行效率

148. 线程上下文切换是什么意思?

多线程的上下文切换是指 CPU 控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程

149. Java中用到了什么线程调度算法?

抢占式。一个线程用完 CPU 之后,操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。

150. 什么是乐观锁和悲观锁?
  • 乐观锁:就像它的名字一样,对于并发间操作产生的线程安全问题持乐观状态,乐观锁认为竞争不总是会发生,因此它不需要持有锁,将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量,如果失败则表示发生冲突,那么就应该有相应的重试逻辑。
  • 悲观锁:还是像它的名字一样,对于并发间操作产生的线程安全问题持悲观状态,悲观锁认为竞争总是会发生,因此每次对某资源进行操作时,都会持有一个独占的锁,就像synchronized,不管三七二十一,直接上了锁就操作资源了
151. 同步方法和同步块哪种好?

同步块,这意味着同步块之外的代码是异步执行的,这比同步整个方法更提升代码的效率。
请知道一条原则:同步的范围越小越好。

152. Runnable和Thread用哪个好?
  1. Java 不支持类的多重继承,但允许你实现多个接口。
  2. 所以如果你要继承其他类,也为了减少类之间的耦合性,Runnable 会更好
153. Java中notify和notifyAll有什么区别?
  1. notify()方法不能唤醒某个具体的线程,所以只有一个线程在等待的时候它才有用武之地。
  2. notifyAll()唤醒所有线程并允许他们争夺锁确保了至少有一个线程能继续运行。
154. 为什么wait/notify/notifyAll这些方法不再thread类里面?
  1. 一个很明显的原因是JAVA 提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。
  2. 如果线程需要等待某些锁那么调用对象中的wait()方法就有意义了。
  3. 如果 wait()方法定义在 Thread 类中,线程正在等待的是哪个锁就不明显了。
155. 为什么wait和notify方法要在同步块中调用?

是 因 为 Java API 强 制 要 求 这 样 做

156. Java中堆和栈有什么不同?
  1. 每个线程都有自己的栈内存,用于存储本地变量,方法参数和栈调用,一个线程中存储的变量对其它线程是不可见的。
  2. 而堆是所有线程共享的一片公用内存区域。
157. 如何在Java中获取线程堆栈?

在 Windows 你可以使用 Ctrl + Break 组合键来获取线程堆栈,Linux 下用 kill -3 命令。你也可以
用 jstack 这个工具来获取,它对线程 id 进行操作,你可以用 jps 这个工具找到 id。

158. 如何创建线程安全的单例模式?

单例模式即一个 JVM 内存中只存在一个类的对象实例分类

  1. 懒汉式
    类加载的时候就创建实例
  2. 饿汉式
    使用的时候才创建实例
159. 什么是阻塞式方法?

阻塞式方法是指程序会一直等待该方法完成期间不做其他事情

160. 什么是spring?
  1. Spring 是个 java 企业级应用的开源开发框架
  2. Spring 主要用来开发 Java 应用,但是有些扩展是针对构建 J2EE 平台的 web 应用
  3. Spring 框架目标是简化 Java 企业级应用开发,并通过 POJO 为基础的编程模型促进良好的编程习惯
161. 使用spring框架的好处是什么?
  1. 轻量:Spring 是轻量的,基本的版本大约 2MB
  2. 控制反转:Spring 通过控制反转实现了松散耦合,对象们给出它们的依赖,而不是创建或查找依赖的对象们
  3. 面向切面的编程(AOP):Spring 支持面向切面的编程,并且把应用业务逻辑和系统服务分开
  4. 容器:Spring 包含并管理应用中对象的生命周期和配置
  5. MVC 框架:Spring 的 WEB 框架是个精心设计的框架,是 Web 框架的一个很好的替代品
  6. 事务管理:Spring 提供一个持续的事务管理接口,可以扩展到上至本地事务下至全局事务(JTA)
  7. 异 常 处 理 : Spring 提 供 方 便 的 API 把 具 体 技 术 相 关 的 异 常 ( 比 如 由 JDBC ,Hibernate or JDO 抛出的)转化为一致的 unchecked 异常
162. spring有哪些模块组成?
  1. 数据访问/集成
  2. web
  3. aop
  4. aspect
  5. 工具
  6. 消息
  7. 核心容器
  8. 测试
163. 核心容器模块?

这是基本的 Spring 模块,提供 spring 框架的基础功能,BeanFactory 是 任何以spring 为基础的应用的核心。Spring 框架建立在此模块之上,它使 Spring 成为一个容器。

164. ApplicationContext 通常的实现是什么?
  • FileSystemXmlApplicationContext :此容器从一个 XML 文件中加载 beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。
  • ClassPathXmlApplicationContext:此容器也从一个 XML 文件中加载 beans的定义,这里,你需要正确设置 classpath 因为这个容器将在 classpath 里找bean 配置。
  • WebXmlApplicationContext:此容器加载一个 XML 文件,此文件定义了一个WEB 应用的所有 bean。
165. Bean 工厂和 Application contexts 有什么区别?

Application contexts 提供一种方法处理文本消息,一个通常的做法是加载文件资源(比如镜像),它们可以向注册为监听器的 bean 发布事件。

166. 什么是依赖注入?

依赖注入,是 IOC 的一个方面,是个通常的概念,它有多种解释。

167. 依赖注入的方式?
  • 构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
  • Setter 方法注入:Setter 方法注入是容器通过调用无参构造器或无参 static 工厂 方法实例化 bean 之后,调用该 bean 的 setter 方法,即实现了基于 setter 的依赖注入。
168. 一个 Spring Bean 定义 包含什么?

一个 Spring Bean 的定义包含容器必知的所有配置元数据,包括如何创建一个bean,它的生命周期详情及它的依赖。

169. 如何给 Spring 容器提供配置元数据?

这里有三种重要的方法给 Spring 容器提供配置元数据。

  • XML 配置文件。
  • 基于注解的配置。
  • 基于 java 的配置。
170. 怎样定义类的作用域?

通过 bean 定义中的 scope 属性来定义

171. 解释 Spring 支持的几种 bean 的作用域?

Spring 框架支持以下五种 bean 的作用域:

  • singleton : bean 在每个 Spring ioc 容器中只有一个实例。
  • prototype:一个 bean 的定义可以有多个实例。
  • request:每次 http 请求都会创建一个 bean,该作用域仅在基于 web 的 SpringApplicationContext 情形下有效。
  • session:在一个 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
  • global-session:在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。
  • default:缺省
172. . Spring 框架中的单例 bean 是线程安全的吗?

不,Spring 框架中的单例 bean 不是线程安全的

173. 解释 Spring 框架中 bean 的生命周期?

初始化和销毁

174. 哪些是重要的 bean 生命周期方法? 你能重载它们吗?

The bean 标签有两个重要的属性(init-methoddestroy-method)。用它们你可以自己定制初始化和注 销方法。

175. 什么是 Spring 的内部 bean?
176. 在 Spring 中如何注入一个 java 集合?

Spring 提供以下几种集合的配置元素:

  • <list>类型用于注入一列值,允许有相同的值。
  • <set> 类型用于注入一组值,不允许有相同的值。
  • <map> 类型用于注入一组键值对,键和值都可以为任意类型。
  • <props>类型用于注入一组键值对,键和值都只能为 String 类型。
177. 什么是 bean 装配?

bean 装配是指在 Spring 容器中把 bean 组装到一起,前提是容器需要知道 bean 的依赖关系,如何通过依赖注入来把它们装配到一起。

178. 解释不同方式的自动装配?

有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入

  • no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
  • byName:通过参数名 自动装配,Spring 容器在配置文件中发现 bean 的 autowire属性被设置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的bean。
  • byType:通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire属性被设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的bean。如果有多个 bean 符合条件,则抛出错误。
  • constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
  • autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType方式。
179. 你可以在 Spring 中注入一个 null 和一个空字符串吗?

可以

180. 什么是基于注解的容器配置?

基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring配置而非通过 XML 文件。

181. 怎样开启注解装配?

注解装配在默认情况下是不开启的,为了使用注解装配,我们必须在 Spring 配置文件中配置 <context:annotation-config/>元素。

182. @Required 注解

这个注解表明 bean 的属性必须在配置的时候设置,通过一个 bean 定义的显式的属性 值 或 通 过 自 动 装 配 , 若 @Required 注解的bean 属性未被设置 , 容器将抛 出BeanInitializationException。

183. @Autowired 注解

@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。它的用法和@Required 一样,修饰 setter 方法、构造器、属性或者具有任意名称和/或多个参数的 PN 方法。

184. . @Qualifier 注解

当 有 多 个 相同 类 型 的 bean 却 只有一个需要自动装配时 ,将 @Qualifier 注 解 和@Autowire 注解结合使用以消除这种混淆,指定需要装配的确切的 bean。

185. 在 Spring 框架中如何更有效地使用 JDBC?

以开发者只需
写 statements 和 queries 从数据存取数据,JDBC 也可以在 Spring 框架提供的模板类的帮助下更有效地被使用,这个模板叫 JdbcTemplate

186. Spring 支持的事务管理类型?

Spring 支持两种类型的事务管理:

  1. 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
  2. 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和 XML配置来管理事务
187. . Spring 框架的事务管理有哪些优点?
  1. 它为不同的事务 API 如 JTA,JDBC,Hibernate,JPA 和 JDO,提供一个不变的编程模式。
  2. 它为编程式事务管理提供了一套简单的 API 而不是一些复杂的事务 API 如它支持声明式事务管理。
  3. 它和 Spring 各种数据访问抽象层很好得集成。
188. 你更倾向用那种事务管理类型?

大多数 Spring 框架的用户选择声明式事务管理,因为它对应用代码的影响最小,因此更符合一个无侵入的轻量级容器的思想。

189. 解释 AOP?

面向切面的编程,或 AOP, 是一种编程技术,允许程序模块化横向切割关注点,或横切典型的责任划分,如日志和事务管理。

190. Aspect 切面?
  1. AOP 核心就是切面,它将多个类的通用行为封装成可重用的模块,该模块含有一组API 提供横切功能。
  2. 比如,一个日志模块可以被称作日志的 AOP 切面。
  3. 根据需求的不同,一个应用程序可以有若干切面。
  4. 在 Spring AOP 中,切面通过带有@Aspect注解的类实现。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值