Java面试题及答案_第1页
Java面试题及答案_第2页
Java面试题及答案_第3页
Java面试题及答案_第4页
Java面试题及答案_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java面试题及答案Java中基本数据类型有哪些?各自的字节长度是多少?Java的基本数据类型包括8种:byte(1字节)、short(2字节)、int(4字节)、long(8字节)、float(4字节)、double(8字节)、char(2字节)、boolean(无明确字节定义,通常认为1位或1字节)。其中boolean类型在JVM规范中未明确规定具体存储大小,实际实现中可能因虚拟机而异,例如HotSpot用int(4字节)存储boolean数组元素,单个boolean变量可能用1字节。String、StringBuilder、StringBuffer的区别是什么?三者都用于处理字符串。String是不可变类,内部通过finalchar[]存储字符,所有修改操作(如concat、replace)都会提供新的String对象。StringBuilder和StringBuffer是可变类,内部使用可扩展的char[]存储。StringBuilder非线程安全,适用于单线程环境;StringBuffer通过synchronized修饰方法保证线程安全,适用于多线程环境。性能上,StringBuilder>StringBuffer>String(频繁修改时)。equals()和==的区别是什么?==比较的是变量的内存地址(基本类型比较值,引用类型比较地址)。equals()是Object类的方法,默认实现等同于==,但可被重写。例如String类重写了equals(),比较的是字符内容是否相同。使用时需注意:若对象未重写equals(),则==和equals()效果一致;重写后需同时重写hashCode()以保证哈希容器的正确性(如HashMap)。为什么重写equals()时必须重写hashCode()?根据Java规范,若两个对象equals()返回true,则它们的hashCode()必须相同;若hashCode()不同,则equals()必为false。哈希容器(如HashMap)依赖hashCode()快速定位桶位置,若只重写equals()而不重写hashCode(),会导致相同逻辑的对象存储在不同桶中,破坏容器的正确性(如put和get操作结果不一致)。例如,自定义类重写了equals()比较内容,但hashCode()仍返回默认的内存地址哈希值,此时两个内容相同的对象会被视为不同键,无法正确存入HashMap。ArrayList和LinkedList的底层结构和适用场景?ArrayList底层是动态扩容的Object数组,默认初始容量10,扩容时新容量为原容量的1.5倍(intnewCapacity=oldCapacity+(oldCapacity>>1))。支持O(1)时间的随机访问(通过索引),但插入/删除元素(非尾部)需要移动数组元素,时间复杂度O(n)。LinkedList底层是双向链表(JDK1.6前为双向循环链表),每个节点包含前驱、后继和数据域。插入/删除元素(已知节点位置)只需调整指针,时间复杂度O(1)(但需先定位节点,实际为O(n)),随机访问需遍历链表,时间复杂度O(n)。因此,ArrayList适合频繁查询、较少增删的场景;LinkedList适合频繁增删、较少查询的场景。HashMap的底层实现(JDK7vsJDK8)?JDK7中HashMap底层是“数组+链表”结构。数组是Entry<K,V>[]table,每个Entry包含hash、key、value、next指针(链表节点)。插入元素时,通过key的hashCode()计算哈希值(hash=hash(key)),再通过(n-1)&hash计算桶索引(n为数组长度,需为2的幂次)。若发生哈希冲突(不同key映射到同一桶),则以链表形式存储。扩容时,当元素数量超过阈值(threshold=capacityloadFactor,默认0.75),数组长度翻倍(newCap=oldCap<<1),所有元素重新计算桶索引并重新插入(rehash)。JDK8中HashMap优化为“数组+链表+红黑树”结构。当链表长度≥8且数组长度≥64时,链表转换为红黑树(时间复杂度从O(n)降至O(logn));当红黑树节点数≤6时,退化为链表。Entry被替换为Node(结构类似),TreeNode继承自Node。哈希计算优化为(h=key.hashCode())^(h>>>16),减少高位信息丢失导致的哈希冲突。扩容时,元素迁移无需重新计算hash,而是通过hash&oldCap判断是否需要移动(若结果为0则留在原桶,否则移动到原桶+oldCap的位置),提升了扩容效率。ConcurrentHashMap如何保证线程安全(JDK7vsJDK8)?JDK7中ConcurrentHashMap采用“分段锁(Segment)”机制。Segment继承自ReentrantLock,数组结构为Segment[]segments,每个Segment包含一个HashEntry<K,V>[]table(即一个小的HashMap)。默认并发级别为16(segments长度16),每个Segment独立加锁,不同Segment的操作可并行。put操作时,先定位到对应的Segment,再对该Segment加锁,保证同一Segment内的操作互斥,不同Segment可并发。JDK8中摒弃了分段锁,采用“CAS+synchronized”机制。底层结构与HashMap类似(数组+链表+红黑树)。put操作时:①计算哈希值和桶索引;②若桶为空(table[i]==null),通过CAS原子操作插入节点;③若桶不为空且头节点hash为-1(MOVED,说明正在扩容),则帮助扩容;④否则,对桶的头节点加synchronized锁,遍历链表或红黑树插入元素。扩容时,通过sizeCtl变量控制,多线程可协助迁移节点,提升并发性能。线程的创建方式有几种?各自的优缺点?Java中线程创建主要有三种方式:1.继承Thread类:自定义类继承Thread,重写run()方法。优点是简单直接;缺点是单继承限制(Java不支持多继承),无法复用其他类的功能。2.实现Runnable接口:自定义类实现Runnable,重写run()方法,通过newThread(runnable).start()启动。优点是避免单继承限制,适合多线程共享同一资源(如多个线程操作同一个Runnable实例);缺点是run()无返回值,无法抛出受检异常。3.实现Callable接口(JDK1.5引入):自定义类实现Callable<V>,重写call()方法(有返回值V,可抛出异常),通过FutureTask包装Callable实例,再通过Thread启动。优点是能获取线程执行结果(通过Future.get());缺点是使用略复杂,需结合FutureTask。实际开发中推荐使用后两种方式(Runnable或Callable),避免单继承限制。synchronized和ReentrantLock的区别?1.锁类型:synchronized是关键字,JVM层面实现(通过monitorenter和monitorexit指令);ReentrantLock是java.util.concurrent.locks包下的类,API层面实现。2.可中断性:synchronized不可中断(除非抛出异常或正常完成);ReentrantLock可通过lockInterruptibly()实现可中断锁。3.公平性:synchronized是非公平锁(线程获取锁的顺序与申请顺序无关);ReentrantLock默认非公平,可通过构造函数ReentrantLock(booleanfair)指定为公平锁(按等待队列顺序分配锁)。4.条件变量:synchronized配合wait()/notify()/notifyAll()使用,功能单一;ReentrantLock通过Condition对象(await()/signal()/signalAll())支持多个等待队列(如生产者-消费者模型中可区分生产者和消费者的等待队列)。5.锁粒度:synchronized自动释放锁(作用域结束或异常时);ReentrantLock需手动调用unlock()释放(通常在finally块中),否则可能导致死锁。选择建议:简单同步场景用synchronized(JVM优化后性能接近ReentrantLock);需要可中断、公平锁或多条件变量时用ReentrantLock。volatile的作用是什么?如何保证可见性和有序性?volatile是轻量级同步机制,作用有二:1.保证可见性:被volatile修饰的变量,其修改对所有线程立即可见。JVM通过内存屏障(MemoryBarrier)实现:写volatile变量时,会强制将本地内存中的值刷新到主内存;读volatile变量时,会强制从主内存读取最新值,避免线程使用过期的本地缓存。2.禁止指令重排序:编译器和CPU为优化性能会对指令重排序(但保证单线程语义不变)。volatile变量通过内存屏障禁止特定类型的重排序。例如,在写volatile变量前的操作不能重排序到写之后,读volatile变量后的操作不能重排序到读之前。典型应用场景:状态标志(如volatilebooleanflag)、单例模式的双重检查锁定(避免指令重排导致的空指针)。线程池的核心参数有哪些?工作流程是怎样的?线程池的核心参数(ThreadPoolExecutor构造函数参数):-corePoolSize:核心线程数,即使空闲也不会被销毁(除非设置allowCoreThreadTimeOut为true)。-maximumPoolSize:最大线程数,线程池允许的最大线程数量。-keepAliveTime:非核心线程的空闲存活时间(核心线程默认不销毁)。-unit:keepAliveTime的时间单位(如TimeUnit.SECONDS)。-workQueue:任务队列,用于存放等待执行的任务(常用队列:ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue、PriorityBlockingQueue)。-threadFactory:线程工厂,用于创建新线程(默认DefaultThreadFactory,可自定义以设置线程名、优先级等)。-handler:拒绝策略,当任务队列已满且线程数达到maximumPoolSize时,对新任务的处理方式(默认AbortPolicy,抛出RejectedExecutionException)。工作流程:①提交任务时,若当前线程数<corePoolSize,创建新核心线程执行任务(不检查队列)。②若当前线程数≥corePoolSize,将任务加入workQueue。③若workQueue已满且当前线程数<maximumPoolSize,创建非核心线程执行任务。④若workQueue已满且当前线程数≥maximumPoolSize,触发拒绝策略。常见预定义线程池(Executors工厂方法):-newFixedThreadPool:核心线程数=最大线程数,无界队列(LinkedBlockingQueue),可能导致OOM。-newCachedThreadPool:核心线程数0,最大线程数Integer.MAX_VALUE,使用SynchronousQueue(无存储),适合短时间大量任务。-newSingleThreadExecutor:单线程,任务顺序执行,无界队列。-newScheduledThreadPool:支持定时/周期性任务,使用DelayedWorkQueue。实际开发中不建议直接使用Executors,推荐通过ThreadPoolExecutor自定义参数,避免无界队列导致的内存溢出。JVM内存区域如何划分?各区域的作用和可能的异常?JVM内存区域(运行时数据区)分为以下部分:1.程序计数器(ProgramCounterRegister):较小的内存空间,指向当前线程执行的字节码指令地址(分支、循环、跳转、异常处理时起作用)。线程私有,无OOM风险。2.虚拟机栈(JavaVirtualMachineStacks):线程私有,每个方法调用对应一个栈帧(包含局部变量表、操作数栈、动态链接、方法出口等)。局部变量表存储基本类型、对象引用和returnAddress。若线程请求的栈深度超过JVM允许值,抛出StackOverflowError;若栈可动态扩展但无法申请到内存,抛出OutOfMemoryError(OOM)。3.本地方法栈(NativeMethodStacks):与虚拟机栈类似,用于执行本地方法(如用C/C++实现的方法)。HotSpot虚拟机将其与虚拟机栈合并。可能抛出StackOverflowError或OOM。4.堆(Heap):线程共享,存储对象实例和数组。JVM管理的最大内存区域,可通过-Xms(初始大小)和-Xmx(最大大小)设置。若堆无法分配新对象且无法扩容,抛出OOM。5.方法区(MethodArea):线程共享,存储类信息(类名、字段、方法、接口)、常量、静态变量、即时编译器编译后的代码等。JDK1.7前(永久代)使用堆的一部分,JDK1.8后(元空间Metaspace)使用本地内存。若方法区无法满足内存分配需求,抛出OOM(JDK1.7前为PermGenSpace,JDK1.8后为Metaspace)。6.运行时常量池(RuntimeConstantPool):方法区的一部分,存储编译期提供的字面量和符号引用(如字符串常量、类/方法的符号引用)。JDK1.7后字符串常量池移至堆中。若常量池无法申请内存,抛出OOM。7.直接内存(DirectMemory):非JVM运行时数据区,通过Unsafe类或NIO的ByteBuffer.allocateDirect()分配,不受堆大小限制,但受物理内存和-XX:MaxDirectMemorySize(默认与-Xmx相同)限制。分配失败时抛出OOM。垃圾回收的常见算法有哪些?各有什么优缺点?1.标记-清除(Mark-Sweep):分“标记”和“清除”两阶段。标记所有需要回收的对象,然后清除标记对象。优点是实现简单;缺点是产生内存碎片(空闲内存不连续),可能导致大对象无法分配。2.复制(Copying):将内存分为大小相等的两块,每次只使用一块。当一块用完时,将存活对象复制到另一块,然后清理原块。优点是无内存碎片,分配高效(只需移动指针);缺点是可用内存减半,空间浪费大。3.标记-整理(Mark-Compact):标记阶段与标记-清除相同,清除阶段将存活对象向内存一端移动,然后清理边界外的内存。优点是无内存碎片;缺点是移动对象需暂停用户线程(STW),效率较低。4.分代收集(GenerationalCollection):根据对象存活周期将内存分为新生代和老年代,分别采用不同的回收算法。新生代(Eden区+两个Survivor区)对象存活率低,采用复制算法;老年代对象存活率高,采用标记-清除或标记-整理算法。HotSpot虚拟机的分代内存布局:-新生代:Eden区(80%)+Survivor0(10%)+Survivor1(10%)。新对象优先在Eden分配(大对象直接进入老年代),MinorGC(YoungGC)时,Eden和Survivor区存活对象复制到另一Survivor区(年龄+1),若年龄≥阈值(默认15,-XX:MaxTenuringThreshold)则进入老年代。-老年代:存储长时间存活的对象或大对象,触发MajorGC(FullGC)时进行回收,通常伴随MinorGC。常见的垃圾收集器有哪些?各适合什么场景?1.Serial收集器:单线程,新生代采用复制算法,老年代采用标记-整理。工作时STW,适合客户端模式(单CPU、内存小)。2.ParNew收集器:Serial的多线程版本,新生代复制算法,配合CMS收集器使用(老年代CMS)。3.ParallelScavenge(ParallelYoung):新生代多线程复制算法,目标是达到可控的吞吐量(吞吐量=用户代码时间/(用户代码时间+GC时间)),适合后台计算、不需要太多交互的场景(如大数据处理)。4.SerialOld:Serial的老年代版本,标记-整理算法,用于客户端或与ParallelScavenge配合(JDK1.5前作为CMS的后备方案)。5.ParallelOld:ParallelScavenge的老年代版本,多线程标记-整理算法,与ParallelScavenge配合实现“吞吐量优先”。6.CMS(ConcurrentMarkSweep):老年代收集器,目标是降低STW时间。流程:初始标记(STW,标记GCRoots直接关联的对象)→并发标记(与用户线程并发,遍历可达对象)→重新标记(STW,修正并发标记期间的变动)→并发清除(与用户线程并发,清除标记对象)。优点是低停顿;缺点是:①占用CPU资源(并发阶段与用户线程竞争CPU);②无法处理浮动垃圾(并发清除期间新产生的垃圾,可能导致ConcurrentModeFailure,触发SerialOld收集器);③标记-清除算法产生内存碎片(可能提前触发FullGC)。适合对响应时间敏感的场景(如Web服务器)。7.G1(Garbage-First):JDK1.7引入,目标是替换CMS。将堆划分为多个大小相等的Region(默认2048个),部分Region作为Eden、Survivor、老年代,还有HumongousRegion存储大对象(≥Region的50%)。G1跟踪每个Region的垃圾价值(回收所获空间+时间),优先回收价值高的Region(“Garbage-First”)。流程:初始标记(STW)→并发标记→最终标记(STW,使用SATB记录变化)→筛选回收(STW,按优先级回收Region,复制存活对象到新Region)。优点是可预测的停顿时间(通过-XX:MaxGCPauseMillis设置目标停顿时间),适合大内存、低延迟场景(如堆内存≥8GB)。8.ZGC(JDK11引入):基于Region和染色指针(ColoredPointers),支持TB级堆内存,STW时间不超过10ms。通过读屏障(LoadBarrier)实现并发标记和转移,适用于超大型内存、极低延迟的场景(如数据库、大数据平台)。类加载的过程分为哪几个阶段?双亲委派模型是什么?类加载过程分为5个阶段(顺序固定):1.加载(Loading):通过类加载器将.class文件的二进制字节流加载到方法区,提供java.lang.Class对象(作为方法区数据的访问入口)。加载来源可以是本地文件、网络、动态提供(如ASM)、数据库等。2.验证(Verification):确保.class文件的字节流符合JVM规范,防止恶意代码。包括文件格式验证(如魔数0xCAFEBABE)、元数据验证(语义检查,如父类是否合法)、字节码验证(操作数栈类型匹配)、符号引用验证(确保引用的类、方法存在)。3.准备(Preparation):为类静态变量分配内存并设置初始值(零值)。例如,staticintvalue=123,准备阶段value=0,初始化阶段才赋值123。staticfinal变量(常量)在准备阶段直接赋值(如staticfinalintvalue=123,准备阶段value=123)。4.解析(Resolution):将符号引用(如CONSTANT_Class_info、CONSTANT_Fieldref_info)替换为直接引用(内存地址或句柄)。解析可发生在类加载时(静态解析)或运行时(动态解析,如invokedynamic指令)。5.初始化(Initialization):执行类构造器<clinit>()方法(由编译器自动收集类变量赋值语句和静态代码块合并提供)。<clinit>()方法按代码顺序执行,线程安全(多个线程初始化同一类时,只有一个线程执行<clinit>(),其他线程等待)。双亲委派模型(ParentDelegationModel):类加载器收到类加载请求时,先委托给父类加载器加载,父类加载器再委托给其父类,直到启动类加载器(BootstrapClassLoader)。若父类加载器无法加载(未找到.class文件),则当前类加载器尝试自己加载。类加载器层级(从顶层到底层):-启动类加载器(BootstrapClassLoader):C++实现,加载JRE/lib下的核心类(如rt.jar、charsets.jar)。-扩展类加载器(ExtensionClassLoader):Java实现(sun.misc.Launcher$ExtClassLoader),加载JRE/lib/ext下的类。-应用类加载器(ApplicationClassLoader):Java实现(sun.misc.Launcher$AppClassLoader),加载classpath下的类(用户自定义类)。-自定义类加载器:继承ClassLoader,覆盖findClass()方法(推荐)或loadClass()方法(需注意双亲委派)。双亲委派的作用:①避免重复加载:同一类只会被顶层类加载器加载一次。②保证安全:防止用户自定义类覆盖核心类(如自定义java.lang.String会被启动类加载器加载的标准String覆盖)。SpringIOC的实现原理是什么?IOC(控制反转)是Spring的核心思想,指将对象的创建、依赖管理的控制权从程序代码转移到容器(Spring容器)。实现原理主要涉及以下步骤:1.配置解析:容器读取配置(XML、注解、Java配置类),解析出Bean的定义信息(类名、属性、依赖、作用域等)。2.Bean定义注册:将解析后的Bean定义存储在BeanDefinitionRegistry中(如DefaultListableBeanFactory的beanDefinitionMap)。3.Bean实例化:容器根据BeanDefinition创建Bean实例。实例化方式包括构造函数反射(默认)、工厂方法(静态工厂或实例工厂)、注解驱动(如@Autowired)。4.依赖注入:对Bean的属性、方法参数、构造函数参数进行注入。注入方式有:-构造器注入:通过构造函数参数注入依赖(明确依赖关系,防止循环依赖)。-setter注入:通过setter方法注入依赖(适合可选依赖)。-字段注入:通过@Autowired、@Resource等注解直接注入字段(简洁,但可能隐藏依赖关系)。5.生命周期回调:Bean实例化后,容器调用初始化方法(如InitializingBean的afterPropertiesSet()、@PostConstruct注解的方法、自定义init-method)。销毁时调用销毁方法(如DisposableBean的destroy()、@PreDestroy注解的方法、自定义destroy-method)。6.代理增强(AOP):若Bean需要被AOP增强(如@Transactional、@Around),容器通过动态代理(JDK动态代理或CGLIB)提供代理对象,替换原Bean实例。IOC容器的典型实现是BeanFactory(基础容器)和ApplicationContext(扩展容器,支持事件、国际化、资源加载等)。ApplicationContext在启动时完成所有单例Bean的初始化(预加载),而BeanFactory在第一次获取Bean时初始化(懒加载)。SpringAOP的实现方式有哪些?如何选择?AOP(面向切面编程)通过将横切关注点(如日志、事务、权限)与业务逻辑分离,提高代码复用性。SpringAOP的实现基于动态代理,主要有两种方式:1.JDK动态代理:基于接口,通过java.lang.reflect.Proxy类提供代理对象。代理类实现目标接口,重写接口方法,在方法调用前后插入切面逻辑。2.CGLIB动态代理:基于类,通过ASM库修改字节码提供目标类的子类(代理类继承目标类)。子类重写父类的非final方法,在方法调用前后插入切面逻辑。选择依据:-若目标对象实现了接口,默认使用JDK动态代理(Spring3.2+)。-若目标对象未实现接口,或强制使用CGLIB(通过@EnableAspectJAutoProxy(proxyTargetClass=true)),则使用CGLIB。-目标方法为final时,CGLIB无法重写该方法,AOP不生效。SpringAOP与AspectJ的关系:SpringAOP是轻量级实现,仅支持方法级别的切面;AspectJ是完整的AOP框架,支持字段、构造器、静态代码块等更细粒度的切面,通过编译时织入(CTW)、加载时织入(LTW)修改字节码。Spring可与AspectJ集成(通过@AspectJ注解),使用AspectJ的注解语法(如@Pointcut、@Before),但底层仍可能使用SpringAOP的动态代理(或AspectJ的织入器)。SpringBean的作用域有哪些?Spring支持以下作用域(通过@Scope注解或<beanscope="...">配置):-singleton(默认):单例,容器中仅存在一个Bean实例(与Spring容器生命周期一致)。-prototype:原型,每次获取Bean时创建新实例(容器不管理其生命周期,销毁需手动调用)。-request:Web作用域,每个HTTP请求创建一个实例(仅在WebApplicationContext中有效)。-session:Web作用域,每个HTTP会话创建一个实例。-application:Web作用域,每个ServletContext创建一个实例(全局作用域)。-websocket:Spring4.2+支持,每个WebSocket会话创建一个实例。注意:singleton是线程不安全的(若Bean包含可变状态),prototype需谨慎使用(可能导致内存泄漏)。SpringMVC的执行流程是怎样的?SpringMVC的核心组件包括DispatcherServlet(前端控制器)、HandlerMapping(处理器映射)、HandlerAdapter(处理器适配器)、Controller(控制器)、ModelAndView(模型视图)、ViewResolver(视图解析器)。执行流程如下:1.用户发送请求至DispatcherServlet。2.DispatcherServlet通过HandlerMapping查找处理该请求的Handler(如Controller的方法),返回HandlerExecutionChain(包含Handler和拦截器)。3.DispatcherServlet通过HandlerAdapter调用Handler(如调用@GetMapping注解的方法),Handler处理请求并返回ModelAndView。4.DispatcherServlet遍历拦截器的postHandle()方法(若有)。5.DispatcherServlet通过ViewResolver解析ModelAndView中的视图名,获取View实例。6.View渲染模型数据(将Model中的数据填充到视图),提供响应返回用户。7.调用拦截器的afterCompletion()方法(无论是否异常)。关键扩展点:-自定义HandlerMapping:实现HandlerMapping接口,定义请求到Handler的映射规则(如基于注解、URL路径)。-自定义HandlerAdapter:实现HandlerAdapter接口,支持处理自定义类型的Handler(如非@Controller注解的类)。-自定义ViewResolver:实现ViewResolver接口,支持解析自定义视图(如JSON、XML、Thymeleaf模板)。事务的传播行为有哪些?Spring如何实现事务?事务传播行为定义了多个事务方法相互调用时,事务的创建和合并规则(Spring通过TransactionDefinition接口定义)。常见传播行为:-PROPAGATION_REQUIRED(默认):当前有事务则加入,无事务则创建新事务。-PROPAGATION_SUPPORTS:当前有事务则加入,无事务则以非事务执行。-PROPAGATION_MANDATORY:当前必须有事务,否则抛出异常。-PROPAGATION_REQUIRES_NEW:创建新事务,挂起当前事务(若有)。-PROPAGATION_NOT_SUPPORTED:以非事务执行,挂起当前事务(若有)。-PROPAGATION_NEVER:当前必须无事务,否则抛出异常。-PROPAGATION_NESTED:在当前事务中创建嵌套事务(通过保存点实现,回滚时只回滚嵌套部分)。Spring事务管理分为编程式(通过TransactionTemplate)和声明式(通过@Transactional注解或XML配置)。声明式事务基于AOP实现,通过TransactionInterceptor拦截方法调用,在方法执行前后管理事务(开启、提交、回滚)。底层依赖平台事务管理器(如DataSourceTransactionManager用于JDBC,HibernateTransactionManager用于Hibernate)。@Transactional的常用属性:-value/transactionManager:指定事务管理器Bean名称。-propagation:传播行为(默认PROPAGATION_REQUIRED)。-isolation:隔离级别(默认ISOLATION_DEFAULT,使用数据库默认隔离级别)。-readOnly:是否为只读事务(优化数据库性能)。-timeout:事务超时时间(秒)。-rollbackFor:指定需要回滚的异常类(默认RuntimeException和Error)。-noRollbackFor:指定不需要回滚的异常类。Java中检查型异常和非检查型异常的区别?Java异常分为Throwable的子类:Error(JVM错误,如OutOfMemoryError,不可恢复)、Exception(可处理的异常)。Exception又分为:-检查型异常(CheckedException):继承自Exception(非RuntimeException),必须显式处理(捕获或声明抛出)。例如IOException、SQLException。-非检查型异常(UncheckedException):继承自RuntimeException,可不显式处理(但可能导致程序终止)。例如NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException。设计原则:检查型异常用于可恢复的错误(如文件不存在,可提示用户检查路径);非检查型异常用于程序逻辑错误(如空指针,应在代码中避免)。try-catch-finally中,如果catch块有return,finally块会执行吗?会执行。finally块在以下情况执行:-try或catch块执行return、break、continue前。-try或catch块抛出异常后。-try块正常结束后。注意:若finally块中也有return,会覆盖try或catch块的return值(不推荐,可能导致逻辑混乱)。例如:```javapublicinttest(){try{return1;}catch(Exceptione){return2;}finally{return3;}}```该方法返回3,因为finally的return覆盖了try的return。若finally块中修改变量值,是否影响返回结果?分情况:-基本类型:try中return的是变量的副本,finally修改原变量不影响返回值。例如:```javapublicinttest(){intx=1;try{returnx;//返回x的副本(1)}finally{x=2;//修改原变量x,但不影响已返回的副本}}```返回1。-引用类型:return的是对象引用的副本,finally修改对象属性会影响返回结果(引用指向同一对象)。例如:```javapublicList<Integer>test(){List<Integer>list=newArrayList<>();list.add(1);try{returnlist;//返回list的引用副本}finally{list.add(2);//修改原对象,引用副本指向的对象被修改}}```返回的list包含[1,2]。单例模式的几种实现方式?哪种最推荐?单例模式保证一个类仅有一个实例,并提供全局访问点。常见实现方式:1.饿汉式:类加载时初始化实例(线程安全)。```javapublicclassSingleton{privatestaticfinalSingletonINSTANCE=newSingleton();privateSingleton(){}publicstaticSingletongetInstance(){returnINSTANCE;}}```优点:简单、线程安全;缺点:类加载即初始化,可能浪费资源(若实例未使用)。2.懒汉式(线程不安全):```javapublicclassSingleton{privatestaticSingletonINSTANCE;privateSingleton(){}publicstaticSingletongetInstance(){if(INSTANCE==null){//多线程可能同时进入INSTANCE=newSingleton();}returnINSTANCE;}}```多线程下可能创建多个实例,不安全。3.懒汉式(线程安全,synchronized方法):```javapublicclassSingleton{privatestaticS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论