2023-03-10 22:52:45
String类为什么是final的:
线程安全:String类不可变保证了其线程安全,多个线程可以安全地共享同一个String对象。
安全性:String被广泛用于类加载、网络连接、文件操作等场景,不可变性确保了这些操作的正确性。
缓存hash值:String的hash值在第一次计算后会被缓存,不可变性使得hash值可以重复使用,提高了性能。
字符串常量池:String的不可变性使得字符串常量池的实现成为可能,节省了内存空间。
HashMap的源码,实现原理,底层结构:
实现原理:HashMap基于哈希表实现,通过哈希函数将键映射到数组的索引位置。
底层结构:由数组和链表(或红黑树)组成,数组用于存储键值对,链表或红黑树用于解决哈希冲突。
哈希冲突:当两个键的哈希值相同时,使用链表或红黑树存储这些键值对。
扩容机制:当元素数量超过阈值时,HashMap会进行扩容,重新计算所有元素的哈希值并分配到新的数组中。
ArrayList和LinkedList各自实现和区别:
ArrayList:基于动态数组实现,支持快速随机访问,插入和删除操作在数组末尾效率较高,但在数组中间或开头效率较低。
LinkedList:基于双向链表实现,插入和删除操作在任何位置效率都较高,但随机访问效率较低。
区别:ArrayList适合读多写少的场景,LinkedList适合写多读少的场景。
Java中的队列都有哪些,有什么区别:
ArrayQueue:基于数组实现的有界队列。
LinkedList:基于链表实现的无界队列。
PriorityQueue:基于堆实现的优先级队列。
ConcurrentLinkedQueue:基于链表实现的无界并发队列。
ArrayBlockingQueue:基于数组实现的有界阻塞队列。
LinkedBlockingQueue:基于链表实现的有界阻塞队列。
区别:主要在于实现方式、有界性、并发性以及是否支持优先级。
反射中,Class.forName和classloader的区别:
Class.forName:不仅加载类,还会执行类的静态初始化块。
ClassLoader:仅加载类,不执行静态初始化块。
应用场景:Class.forName常用于数据库驱动加载,ClassLoader常用于自定义类加载器。
Java7、Java8的新特性:
Java7:switch语句支持String类型、try-with-resources语句、泛型实例化类型推断、数字字面量下划线支持、NIO 2.0等。
Java8:Lambda表达式、Stream API、函数式接口、默认方法、Optional类、新的日期时间API等。
Java数组和链表两种结构的操作效率:
数组:随机访问效率高,插入和删除操作在数组末尾效率较高,但在数组中间或开头效率较低。
链表:插入和删除操作在任何位置效率都较高,但随机访问效率较低。
Java内存泄露的问题调查定位:jmap,jstack的使用:
jmap:用于生成堆转储快照,可以查看堆内存中的对象分布情况。
jstack:用于生成线程快照,可以查看线程的调用栈信息,帮助定位死锁或线程阻塞问题。
string、stringbuilder、stringbuffer区别:
String:不可变字符串,线程安全。
StringBuilder:可变字符串,非线程安全,性能较高。
StringBuffer:可变字符串,线程安全,性能较低。
Hashtable和HashMap的区别:
线程安全:Hashtable是线程安全的,HashMap是非线程安全的。
性能:Hashtable性能较低,HashMap性能较高。
Null值:Hashtable不允许键或值为null,HashMap允许一个键为null,多个值为null。
异常的结构,运行时异常和非运行时异常,各举个例子:
异常结构:Throwable是所有异常和错误的超类,Exception是异常的超类,RuntimeException是运行时异常的超类。
运行时异常:如NullPointerException、ArrayIndexOutOfBoundsException等。
非运行时异常:如IOException、SQLException等。
String a= “abc” String b = "abc" String c = new String("abc") String d = "ab" + "c" .他们之间用 == 比较的结果:
a == b:true,因为a和b指向字符串常量池中的同一个对象。
a == c:false,因为c是通过new关键字创建的新对象,位于堆中。
a == d:true,因为d在编译时会被优化为"abc",指向字符串常量池中的同一个对象。
String 类的常用方法:
length():返回字符串的长度。
charAt(int index):返回指定索引处的字符。
substring(int beginIndex):返回从beginIndex开始的子字符串。
equals(Object obj):比较字符串内容是否相等。
indexOf(String str):返回指定子字符串的索引位置。
trim():去除字符串两端的空白字符。
Java 的引用类型有哪几种:
强引用:最常见的引用类型,只要强引用存在,对象就不会被垃圾回收。
软引用:用于描述有用但非必需的对象,内存不足时会被垃圾回收。
弱引用:用于描述非必需对象,无论内存是否充足,下次垃圾回收时都会被回收。
虚引用:主要用于跟踪对象被垃圾回收的活动,无法通过虚引用获取对象实例。
抽象类和接口的区别:
定义方式:抽象类使用abstract关键字定义,接口使用interface关键字定义。
方法实现:抽象类可以包含抽象方法和具体方法,接口只能包含抽象方法(Java8后可以有默认方法和静态方法)。
变量:抽象类可以包含实例变量,接口只能包含公共静态常量。
继承:一个类只能继承一个抽象类,但可以实现多个接口。
Java的基础类型和字节大小:
byte:1字节
short:2字节
int:4字节
long:8字节
float:4字节
double:8字节
char:2字节
boolean:1字节(JVM实现可能不同)
Hashtable,HashMap,ConcurrentHashMap 底层实现原理与线程安全问题:
Hashtable:使用synchronized关键字保证线程安全,性能较低。
HashMap:非线程安全,使用数组和链表(或红黑树)实现。
ConcurrentHashMap:使用分段锁(Java7)或CAS+synchronized(Java8)保证线程安全,性能较高。
Hash冲突怎么办?哪些解决散列冲突的方法:
开放定址法:线性探测、二次探测、双重哈希等。
链地址法:使用链表或红黑树存储哈希冲突的元素。
再哈希法:使用多个哈希函数计算哈希值。
建立公共溢出区:将所有哈希冲突的元素存储在公共溢出区中。
HashMap冲突很厉害,最差性能,你会怎么解决?从O(n)提升到log(n)咯,用二叉排序树的思路说了一通:
解决思路:当链表长度超过阈值时,将链表转换为红黑树,将查找时间复杂度从O(n)降低到O(log n)。
rehash:
定义:当HashMap的元素数量超过阈值时,会进行扩容,重新计算所有元素的哈希值并分配到新的数组中,这个过程称为rehash。
目的:减少哈希冲突,提高查找效率。
hashCode() 与 equals() 生成算法、方法怎么重写:
重写原则:如果两个对象相等(equals方法返回true),则它们的hashCode值必须相等;反之不成立。
重写步骤:
重写equals方法,确保逻辑正确。
重写hashCode方法,使用相同的字段计算哈希值。
确保hashCode方法计算结果一致且分布均匀。
讲讲IO里面的常见类,字节流、字符流、接口、实现类、方法阻塞:
字节流:InputStream、OutputStream及其子类,如FileInputStream、FileOutputStream等。
字符流:Reader、Writer及其子类,如FileReader、FileWriter等。
接口:Closeable、Flushable、Readable、Appendable等。
方法阻塞:如read方法在读取数据时会阻塞,直到有数据可读或到达文件末尾。
讲讲NIO:
定义:NIO(New IO)是Java提供的非阻塞IO API,支持面向缓冲区、基于通道的IO操作。
核心组件:Channel、Buffer、Selector。
特点:非阻塞、高性能、支持异步IO。
String 编码UTF-8 和GBK的区别:
UTF-8:变长编码,支持全球所有语言,一个字符可能占用1-4个字节。
GBK:双字节编码,主要用于中文,一个字符占用2个字节。
什么时候使用字节流、什么时候使用字符流:
字节流:处理二进制数据,如图片、音频、视频等。
字符流:处理文本数据,如TXT文件、XML文件等。
递归读取文件夹下的文件,代码怎么实现:
session和cookie的区别和联系,session的生命周期,多个服务部署时session管理:
区别:session存储在服务器端,cookie存储在客户端;session用于跟踪用户状态,cookie用于存储用户偏好或身份信息。
联系:session依赖cookie存储session ID。
生命周期:session的生命周期由服务器配置决定,默认30分钟不活动后失效。
多服务部署:使用session复制、session共享(如Redis)或令牌机制管理session。
servlet的一些相关问题:
生命周期:init、service、destroy。
请求处理:doGet、doPost等方法。
转发与重定向:forward和sendRedirect的区别。
webservice相关问题:
定义:WebService是一种跨平台的、基于XML的远程调用技术。
协议:SOAP、WSDL、UDDI。
实现:JAX-WS、JAX-RS等。
jdbc连接,forname方式的步骤,怎么声明使用一个事务。举例并具体代码:
无框架下配置web.xml的主要配置内容:
servlet配置:servlet、servlet-mapping。
监听器配置:listener。
过滤器配置:filter、filter-mapping。
会话配置:session-config。
欢迎文件列表:welcome-file-list。
jsp和servlet的区别:
JSP:本质上是Servlet,侧重于视图展示,支持HTML标签和JSP标签。
Servlet:侧重于逻辑处理,生成动态内容。
Java的内存模型以及GC算法:
内存模型:程序计数器、虚拟机栈、本地方法栈、堆、方法区。
GC算法:标记-清除、复制、标记-整理、分代收集。
JVM性能调优都做了什么:
堆内存调整:设置合适的堆大小和新生代/老年代比例。
选择合适的GC算法:根据应用特点选择Serial、Parallel、CMS或G1。
监控工具:使用jstat、jmap、jstack等工具监控JVM状态。
介绍JVM中7个区域,然后把每个区域可能造成内存的溢出的情况说明:
程序计数器:不会溢出。
虚拟机栈:栈深度过大导致StackOverflowError。
本地方法栈:同虚拟机栈。
堆:对象过多导致OutOfMemoryError: Java heap space。
方法区:类过多导致OutOfMemoryError: Metaspace(Java8后)。
运行时常量池:常量过多导致OutOfMemoryError: Metaspace。
直接内存:通过ByteBuffer.allocateDirect分配过多内存导致OutOfMemoryError。
介绍GC 和GC Root不正常引用:
GC:垃圾回收机制,自动回收不再使用的对象内存。
GC Root:作为垃圾回收起点的对象,如虚拟机栈中的引用、方法区中的静态引用等。
不正常引用:如内存泄漏导致的对象无法被回收。
自己从classload 加载方式,加载机制说开去,从程序运行时数据区,讲到内存分配,讲到String常量池,讲到JVM垃圾回收机制,算法,hotspot:
类加载机制:加载、验证、准备、解析、初始化。
运行时数据区:程序计数器、虚拟机栈、本地方法栈、堆、方法区。
内存分配:对象在堆中分配内存,String常量池在方法区(Java8后位于堆中)。
垃圾回收机制:分代收集,使用不同的GC算法。
HotSpot:Oracle的JVM实现,支持多种GC算法和优化技术。
JVM如何分配直接内存, new 对象如何不分配在堆而是栈上,常量池解析:
直接内存分配:通过ByteBuffer.allocateDirect分配。
栈上分配:通过逃逸分析确定对象是否可以在栈上分配(JIT优化)。
常量池解析:字符串常量池在类加载时解析并存储字符串字面量。
数组多大放在 JVM 老年代(不只是设置 PretenureSizeThreshold ,问通常多大,没做过一问便知):
PretenureSizeThreshold:默认值为0,表示所有对象都先在新生代分配。
实际大小:通常大于1MB的对象会直接在老年代分配(取决于具体JVM实现和配置)。
老年代中数组的访问方式:
直接访问:通过数组索引直接访问元素。
系统调用:对于大数组,可能需要通过系统调用访问内存。
GC 算法,永久代对象如何 GC , GC 有环怎么处理:
永久代对象GC:通过Full GC回收永久代中的无用类。
GC有环处理:使用可达性分析算法,从GC Root出发标记所有可达对象,未被标记的对象视为垃圾。
谁会被 GC ,什么时候 GC:
被GC的对象:不再被任何GC Root引用的对象。
GC时机:当Eden区满时触发Minor GC,当老年代满时触发Full GC。
如果想不被 GC 怎么办:
保持引用:确保对象始终被GC Root引用。
使用软引用或弱引用:根据需要控制对象的生命周期。
如果想在 GC 中生存 1 次怎么办:
finalize方法:重写finalize方法,在对象被回收前执行一些操作(不推荐使用)。
hibernate和ibatis的区别:
Hibernate:全自动化ORM框架,支持HQL查询,缓存机制完善。
iBatis:半自动化ORM框架,需要手动编写SQL,灵活性高。
讲讲mybatis的连接池:
内置连接池:MyBatis内置了一个简单的连接池,支持配置最大连接数和最大活跃连接数。
第三方连接池:支持与DBCP、C3P0、Druid等第三方连接池集成。
Spring框架中需要引用哪些jar包,以及这些jar包的用途:
spring-core:核心工具类。
spring-beans:Bean支持。
spring-context:上下文支持。
spring-aop:AOP支持。
spring-tx:事务支持。
spring-jdbc:JDBC支持。
spring-web:Web支持。
spring-webmvc:MVC支持。
SpringMVC的原理:
前端控制器:DispatcherServlet接收请求。
处理器映射:HandlerMapping找到处理请求的Controller。
处理器适配器:HandlerAdapter调用Controller方法。
视图解析:ViewResolver解析视图并渲染响应。
SpringMVC注解的意思:
@Controller:标识一个类为Controller。
@RequestMapping:映射请求URL到处理方法。
@RequestParam:绑定请求参数到方法参数。
@ModelAttribute:绑定请求参数到模型对象。
@ResponseBody:将方法返回值直接写入响应体。
Spring中beanFactory和ApplicationContext的联系和区别:
BeanFactory:基础IoC容器,延迟加载Bean。
ApplicationContext:高级IoC容器,预加载Bean,支持AOP、事件传播等。
联系:ApplicationContext继承自BeanFactory。
Spring注入的几种方式(循环注入):
构造器注入:通过构造器参数注入依赖。
Setter注入:通过Setter方法注入依赖。
字段注入:通过反射直接注入字段(不推荐)。
循环注入:通过构造器注入会导致循环依赖问题,可通过Setter注入或@Lazy注解解决。
Spring如何实现事务管理的:
声明式事务:通过@Transactional注解配置事务。
编程式事务:通过TransactionTemplate或PlatformTransactionManager手动管理事务。
Spring IOC:
定义:控制反转,将对象的创建和管理交给容器。
实现方式:依赖注入(DI)。
Spring AOP的原理:
动态代理:通过JDK动态代理或CGLIB动态代理实现AOP。
切面编程:将横切关注点(如日志、事务)模块化。
Hibernate中的1级和2级缓存的使用方式以及区别原理(Lazy-Load的理解):
一级缓存:Session级别的缓存,默认开启,用于减少数据库访问。
二级缓存:SessionFactory级别的缓存,需要手动配置,用于跨Session缓存对象。
Lazy-Load:延迟加载,只有在真正访问对象时才加载数据,提高性能。
Hibernate的原理体系架构,五大核心接口,Hibernate对象的三种状态转换,事务管理:
五大核心接口:Session、SessionFactory、Transaction、Query、Configuration。
对象状态:临时态、持久态、游离态。
事务管理:通过Transaction接口管理事务。
Java创建线程之后,直接调用start()方法和run()的区别:
start():启动新线程,调用run()方法。
run():直接在当前线程执行run()方法,不会启动新线程。
常用的线程池模式以及不同线程池的使用场景:
newFixedThreadPool:固定大小线程池,适用于负载较重的服务器。
newCachedThreadPool:可缓存线程池,适用于负载较轻的服务器。
newScheduledThreadPool:定时任务线程池,适用于定时任务执行。
newSingleThreadExecutor:单线程线程池,适用于需要顺序执行的场景。
newFixedThreadPool此种线程池如果线程数达到最大值后会怎么办,底层原理:
处理方式:任务会被放入队列等待执行。
底层原理:使用LinkedBlockingQueue作为任务队列,线程从队列中获取任务执行。
多线程之间通信的同步问题,synchronized锁的是对象,衍伸出和synchronized相关很多的具体问题,例如同一个类不同方法都有synchronized锁,一个对象是否可以同时访问。或者一个类的static构造方法加上synchronized之后的锁的影响:
同步问题:synchronized锁的是对象,确保同一时间只有一个线程可以访问锁定的代码块。
不同方法:同一个对象的不同synchronized方法不能同时被访问。
static方法:synchronized static方法锁的是类对象,与实例方法互斥。
了解可重入锁的含义,以及ReentrantLock 和synchronized的区别:
可重入锁:同一个线程可以多次获取同一把锁。
区别:
ReentrantLock:需要手动释放锁,支持公平锁、超时锁等高级特性。
synchronized:自动释放锁,使用简单,但功能较少。
同步的数据结构,例如concurrentHashMap的源码理解以及内部实现原理,为什么他是同步的且效率高:
内部实现:Java7使用分段锁,Java8使用CAS+synchronized。
高效原因:通过减少锁的粒度(如分段锁或桶锁)提高并发性能。
AtomicInteger和volatile等线程安全操作的关键字的理解和使用:
AtomicInteger:基于CAS实现的原子整数,保证线程安全。
volatile:保证变量的可见性,但不保证原子性。
线程间通信,wait和notify:
wait:释放锁并等待其他线程通知。
notify:唤醒一个等待的线程。
notifyAll:唤醒所有等待的线程。
定时线程的使用:
Timer:单线程定时任务执行器。
ScheduledExecutorService:多线程定时任务执行器,推荐使用。
场景:在一个主线程中,要求有大量(很多很多)子线程执行完之后,主线程才执行完成。多种方式,考虑效率:
CountDownLatch:通过计数器等待所有子线程完成。
CyclicBarrier:通过屏障等待所有子线程到达某一点。
CompletableFuture:通过异步任务组合等待所有子线程完成。
进程和线程的区别:
进程:资源分配的基本单位,拥有独立的内存空间。
线程:CPU调度的基本单位,共享进程的内存空间。
什么叫线程安全?举例说明:
定义:当多个线程访问某个类、对象或方法时,不会引起意外的结果。
例子:Vector是线程安全的,ArrayList是非线程安全的。
线程的几种状态:
新建:线程被创建但未启动。
可运行:线程正在等待CPU资源。
运行:线程正在执行。
阻塞:线程因某种原因暂停执行。
死亡:线程执行完毕或异常退出。
并发、同步的接口或方法:
并发接口:Callable、Future、Runnable。
同步方法:synchronized方法、ReentrantLock。
HashMap 是否线程安全,为何不安全。 ConcurrentHashMap,线程安全,为何安全。底层实现是怎么样的:
HashMap:非线程安全,多线程下可能导致数据不一致或死循环。
ConcurrentHashMap:线程安全,通过分段锁(Java7)或CAS+synchronized(Java8)实现。
J.U.C下的常见类的使用。 ThreadPool的深入考察; BlockingQueue的使用。(take,poll的区别,put,offer的区别);原子类的实现:
ThreadPool:线程池管理,如ExecutorService、ScheduledExecutorService。
BlockingQueue:take阻塞直到有元素可取,poll非阻塞;put阻塞直到有空间可放,offer非阻塞。
原子类:基于CAS实现,如AtomicInteger、AtomicReference。
简单介绍下多线程的情况,从建立一个线程开始。然后怎么控制同步过程,多线程常用的方法和结构:
建立线程:继承Thread类或实现Runnable接口。
同步控制:使用synchronized、ReentrantLock、CountDownLatch等。
常用方法:start、join、wait、notify、sleep等。
Volatile的理解:
定义:保证变量的可见性,但不保证原子性。
使用场景:状态标志、一次性发布等。
实现多线程有几种方式,多线程同步怎么做,说说几个线程里常用的方法:
实现方式:继承Thread类、实现Runnable接口、使用Callable和Future。
同步方式:synchronized、ReentrantLock、Semaphore等。
常用方法:start、join、wait、notify、sleep等。
HTTP是无状态通信,HTTP的请求方式有哪些,可以自己定义新的请求方式么:
请求方式:GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECT。
自定义请求方式:理论上可以,但服务器和客户端需支持。
Socket通信,以及长连接,分包,连接异常断开的处理:
Socket通信:基于TCP/IP协议的网络通信。
长连接:保持连接不断开,减少握手开销。
分包:通过协议头指定数据长度或使用分隔符分包。
异常处理:通过心跳机制检测连接状态,超时后重连。
Socket通信模型的使用,AIO和NIO:
BIO:阻塞式IO,一个线程处理一个连接。
NIO:非阻塞式IO,一个线程处理多个连接。
AIO:异步IO,操作系统完成IO操作后通知应用。
Socket框架netty的使用,以及NIO的实现原理,为什么是异步非阻塞:
Netty:基于NIO的高性能网络框架,支持异步非阻塞通信。
NIO原理:通过Selector监听多个Channel的事件,实现一个线程处理多个连接。
异步非阻塞:IO操作不会阻塞线程,通过回调或Future处理结果。
同步和异步,阻塞和非阻塞:
同步:调用方等待被调用方返回结果。
异步:调用方不等待被调用方返回结果,通过回调或Future处理结果。
阻塞:调用方在等待结果时被挂起,无法执行其他操作。
非阻塞:调用方在等待结果时继续执行其他操作。
OSI七层模型,包括TCP,IP的一些基本知识:
七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP模型:网络接口层、网络层、传输层、应用层。
TCP:面向连接的、可靠的传输协议。
IP:网络层协议,负责数据包的路由和转发。
HTTP中,GET和POST的区别:
GET:请求数据附加在URL后,有长度限制,