Java开发面试题汇总 -- 精选版(附答案)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 目前流行的开发技术、常见的面试问题以及问题的答案都已经写的特别清楚了,今天我在之前的基础上,再基于面个人的经验继续精选一些面试题给大家阅读参考。 image 1,Java的反射 Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。

目前流行的开发技术、常见的面试问题以及问题的答案都已经写的特别清楚了,今天我在之前的基础上,再基于面个人的经验继续精选一些面试题给大家阅读参考。

image

1,Java的反射

Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java 的反射机制。反射也就是动态加载对象,并对对象进行剖析。Class 类与java.lang.reflect 类库一起对反射的概念进行了支持,该类库包含了Field,Method,Constructor类(每个类都实现了Member 接口)。

image

反射的作用:

1),在运行时判断任意一个对象所属的类

2),在运行时构造任意一个类的对象

3),在运行时判断任意一个类所具有的成员变量和方法

4),在运行时调用任意一个对象的方法

优点:可以动态的创建对象和编译,最大限度发挥了java的灵活性。

缺点:对性能有影响。使用反射基本上一种解释操作,告诉JVM我们要做什么并且满足我们的要求,这类操作总是慢于直接执行java代码。

如何使用java的反射?

a. 通过一个全限类名创建一个对象

1) Class.forName("全限类名");

2) 类名.class; 获取Class<?> clazz 对象

3) 对象.getClass();

b. 获取构造器对象,通过构造器new出一个对象

1) Clazz.getConstructor([String.class]);

2) Con.newInstance([参数]);

c. 通过class对象创建一个实例对象(就相当与new类名()无参构造器)

1) Clazz.newInstance();

d. 通过class对象获得一个属性对象

1) Field c=clazz.getFields(); 获得某个类的所有的公共(public)的字段,包括父类中的字段。

2) Field c=clazz.getDeclaredFields(); 获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。

e、通过class对象获得一个方法对象

1)Clazz.getMethod("方法名",class…..parameaType);(只能获取公共的)

2)Clazz.getDeclareMethod("方法名"); (获取任意修饰方法,不能执行私有)

  1. M.setAccessible(true);(让私有的方法可以执行)

f. 让方法执行

Method.invoke(obj实例对象,obj可变参数);

2,Spring的源码分析及实现

Spring是一个开源的、轻量级的Java 开发框架。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。Spring的核心是控制反转(IOC)和面向切面(AOP)。

什么是IOC?

控制反转(IOC)就是把原先我们代码里面需要实现的对象创建、依赖的代码,反转给容器来帮忙实现。那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们可配置的文件。IOC容器最主要是完成了对象的创建和依赖的管理注入等。

Spring IOC体系结构:

Spring Bean的创建是典型的工厂模式,这一系列的Bean工厂,也即IOC容器为开发者管理对象间的依赖关系提供了很多便利和基础服务,在Spring中有许多的IOC容器的实现供用户选择和使用,其相互关系如下:

image

BeanFactory作为最顶层的一个接口类,它定义了IOC容器的基本功能规范,BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。IOC容器接口BeanFactory:

public interface BeanFactory {

在BeanFactory里只对IOC容器的基本行为作了定义,根本不关心你的bean是如何定义怎样加载的。正如我们只关心工厂里得到什么的产品对象,至于工厂是怎么生产这些对象的,这个基本的接口不关心。

而要知道工厂如何产生对象,就需要看具体的IOC容器实现,spring提供了许多IOC容器的实现。如XmlBeanFactory,ClasspathXmlApplicationContext等。其中XmlBeanFactory就是针对最基本的ioc容器的实现,这个IOC容器可以读取XML文件定义的BeanDefinition(XML文件中对bean的描述),如果说XmlBeanFactory是容器中的屌丝,ApplicationContext应该算容器中的高富帅了。

ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能外,还为用户提供了以下的附加服务。从ApplicationContext接口的实现,我们看出其特点:

1, 支持信息源,可以实现国际化。(实现MessageSource接口);

2, 访问资源。(实现ResourcePatternResolver接口,这个后面要讲);

3, 支持应用事件。(实现ApplicationEventPublisher接口);

Spring ****AOP

AOP即面向切面编程。可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

Spring对AOP的支持

Spring中AOP代理由Spring的IOC容器负责生成、管理,其依赖关系也由IOC容器负责管理。因此,AOP代理可以直接使用容器中的其它bean实例作为目标,这种关系可由IOC容器的依赖注入提供。Spring创建代理的规则为:

1)、默认使用Java动态代理来创建AOP代理,这样就可以为任何接口实例创建代理了;

2)、当需要代理的类不是代理接口的时候,Spring会切换为使用CGLIB代理,也可强制使用CGLIB;

AOP编程其实是很简单的事情,纵观AOP编程,程序员只需要参与三个部分:

1)、定义普通业务组件

2)、定义切入点,一个切入点可能横切多个业务组件

3)、定义增强处理,增强处理就是AOP框架为普通业务组件织入的处理动作

所以进行AOP编程的关键就是定义切入点和定义增强处理,一旦定义了合适的切入点和增强处理,AOP框架将自动生成AOP代理,即:代理对象的方法=增强处理+被代理对象的方法。

下面给出一个Spring AOP的.xml文件模板,名字叫做aop.xml,之后的内容都在aop.xml上进行扩展:

<?xml version="1.0" encoding="UTF-8"?>

3,****动态代理****(cglib 与 JDK)

JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP;

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换;

如何强制使用CGLIB实现AOP?

1) 添加CGLIB库,SPRING_HOME/cglib/*.jar

2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK动态代理和CGLIB字节码生成的区别?

1)  JDK动态代理只能对实现了接口的类生成代理,而不能针对类;

2)  CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成final

4,分布式锁的实现方案

分布式锁一般有三种实现方式:

1. 数据库锁;

2. 基于Redis的分布式锁;

3. 基于ZooKeeper的分布式锁。

基于数据库锁实现

方案1:

CREATE TABLE `methodLock` (

当我们想要锁住某个方法时,执行以下SQL:

insert into methodLock(method_name,desc) values (`method_name`,`desc`);

:想要释放锁的话,需要执行以下Sql:

delete from methodLock where method_name ='method_name';

方案2:

CREATE TABLE `method_lock` (

获取锁:

 select id, method_name, state,version from method_lock where state=1 and method_name='methodName';

占有锁:

update t_resoure set state=2, version=2, update_time=now() where method_name='methodName' and state=1 and version=2;

缺点:

   1、这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。

   2、这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。

   3、这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。

   4、这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。

解决方案:

    1、数据库是单点?搞两个数据库,数据之前双向同步。一旦挂掉快速切换到备库上。

    2、没有失效时间?只要做一个定时任务,每隔一定时间把数据库中的超时数据清理一遍。

    3、非阻塞的?搞一个while循环,直到insert成功再返回成功。

    4、非重入的?在数据库表中加个字段,记录当前获得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了。

基于redis的分布式锁

实现方案:

try{

缺点:

在这种场景(主从结构)中存在明显的竞态:
客户端A从master获取到锁,
在master将锁同步到slave之前,master宕掉了。
slave节点被晋级为master节点,
客户端B取得了同一个资源被客户端A已经获取到的另外一个锁。安全失效!

基于zookeeper实现

方案:可以直接使用zookeeper第三方库Curator客户端,这个客户端中封装了一个可重入的锁服务。

image

Curator提供的InterProcessMutex是分布式锁的实现。acquire方法用户获取锁,release方法用于释放锁。

缺点:

性能上可能并没有缓存服务那么高。因为每次在创建锁和释放锁的过程中,都要动态创建、销毁瞬时节点来实现锁功能。ZK中创建和删除节点只能通过Leader服务器来执行,然后将数据同不到所有的Follower机器上。

三种方案的比较

上面几种方式,哪种方式都无法做到完美。就像CAP一样,在复杂性、可靠性、性能等方面无法同时满足,所以,根据不同的应用场景选择最适合自己的才是王道。

从理解的难易程度角度(从低到高):数据库 > 缓存 > Zookeeper

从实现的复杂性角度(从低到高):Zookeeper >= 缓存 > 数据库

从性能角度(从高到低):缓存 > Zookeeper >= 数据库

从可靠性角度(从高到低):Zookeeper > 缓存 > 数据库

5,Java设计模式部分搞笑解读

1、工厂模式,

搞笑解读:—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory。
工厂模式:客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。

2,单例模式

搞笑解读:俺有6个漂亮的老婆,她们的老公都是我,我就是我们家里的老公Sigleton,她们只要说道“老公”,都是指的同一个人,那就是我(白日美梦)。

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。

3,适配器模式

搞笑解读:在一次聚会碰到了一个很漂亮的乌克兰MM,可不会说乌克兰语,她也不会说普通话,只好求助于会乌克兰语的朋友,他作为我们之间的Adapter,让我们可以相互交谈了(也不知道他会不会耍我)。
适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。

4,代理模式

搞笑解读:跟MM在网上聊天,一开头总是“hi,你好”,“你从哪儿来呀?”“你多大了?”“身高多少呀?”这些话,真烦人,写个程序做为我的Proxy吧,凡是接收到这些话都设置好了自动的回答,接收到其他的话时再通知我回答,酷吧。

代理模式:代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些 情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可 以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。

免费获取Java工程化、高性能及分布式、高性能、高架构、性能调优、Spring、MyBatis、Netty源码分析等多个知识点高级进阶干货的直播免费学习权限及相关视频资料,还有spring和虚拟机等书籍扫描版

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
8天前
|
搜索推荐 Java Android开发
课时146:使用JDT开发Java程序
在 Eclipse 之中提供有 JDT环境可以实现java 程序的开发,下面就通过一些功能进行演示。 项目开发流程
|
9天前
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
|
17天前
|
人工智能 安全 IDE
一天成为Java开发高手:用飞算JavaAI实现十倍提效
“一天成为Java开发高手”曾被视为天方夜谭,但飞算JavaAI的出现改变了这一局面。这款AI开发助手通过智能引导、需求分析、自动化逻辑处理和完整代码工程生成,大幅简化了Java开发流程。它不仅帮助新手快速上手,还让资深开发者提高效率,减少调试时间。现在,参与“飞算JavaAI炫技赛”,展示你的开发实力,赢取丰厚奖品!
|
17天前
|
人工智能 Java 数据处理
Java高级应用开发:基于AI的微服务架构优化与性能调优
在现代企业级应用开发中,微服务架构虽带来灵活性和可扩展性,但也增加了系统复杂性和性能瓶颈。本文探讨如何利用AI技术,特别是像DeepSeek这样的智能工具,优化Java微服务架构。AI通过智能分析系统运行数据,自动识别并解决性能瓶颈,优化服务拆分、通信方式及资源管理,实现高效性能调优,助力开发者设计更合理的微服务架构,迎接未来智能化开发的新时代。
|
1月前
|
JavaScript 安全 Java
智慧产科一体化管理平台源码,基于Java,Vue,ElementUI技术开发,二开快捷
智慧产科一体化管理平台覆盖从备孕到产后42天的全流程管理,构建科室协同、医患沟通及智能设备互联平台。通过移动端扫码建卡、自助报道、智能采集数据等手段优化就诊流程,提升孕妇就诊体验,并实现高危孕产妇五色管理和孕妇学校三位一体化管理,全面提升妇幼健康宣教质量。
48 12
|
1月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
109 14
|
1月前
|
安全 Java 程序员
Java 面试必问!线程构造方法和静态块的执行线程到底是谁?
大家好,我是小米。今天聊聊Java多线程面试题:线程类的构造方法和静态块是由哪个线程调用的?构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节有助于掌握Java多线程机制。下期再见! 简介: 本文通过一个常见的Java多线程面试题,详细讲解了线程类的构造方法和静态块是由哪个线程调用的。构造方法由创建线程实例的主线程调用,静态块在类加载时由主线程调用。理解这些细节对掌握Java多线程编程至关重要。
57 13
|
2月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
87 9
|
2月前
|
前端开发 Java 程序员
菜鸟之路day02-04拼图小游戏开发一一JAVA基础综合项目
本项目基于黑马程序员教程,涵盖面向对象进阶、继承、多态等知识,历时约24小时完成。项目去除了登录和注册模块,专注于单机游戏体验。使用Git进行版本管理,代码托管于Gitee。项目包含窗体搭建、事件监听、图片加载与打乱、交互逻辑实现、菜单功能及美化界面等内容。通过此项目,巩固了Java基础并提升了实际开发能力。 仓库地址:[https://gitee.com/zhang-tenglan/puzzlegame.git](https://gitee.com/zhang-tenglan/puzzlegame.git)
51 6
|
2月前
|
算法 安全 Java
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
103 16

热门文章

最新文章