当前位置: 首页 > article >正文

JAVA常见问题解答

1、面型过程与面向对象的区别:

抽象级别:面向过程主要关注解决问题的步骤和过程,以函数为基本单位,强调算法和流程控制。而面向对象则更关注问题领域中的实体和对象,强调将问题划分为多个相互关联的对象,并通过对象之间的交互来解决问题。

数据和行为:面向过程将数据和行为分离,强调数据的处理和操作,而面向对象则将数据和行为封装在一个单元中,即对象,对象包含了自身的状态(数据)和行为(方法)。

可重用性和扩展性:面向对象具有良好的可重用性和扩展性,通过继承、封装和多态等机制可以更方便地创建和扩展新功能。而面向过程缺乏这样的机制,代码复用和扩展相对较为困难。

2、Java基本数据类型:3、JAVA的数据类型

​ 1.基本类型(primitive type):

数值类型:

​ 1)整数类型:byte 1字节 、short 2 字节 、int 4字节 、 long 8字节

​ 2)浮点类型:float 4字节、double 8字节

​ 3)字符类型:char 2字节

boolean类型:占1位 只有true和false两个值

​ 2.引用类型(reference type):类、接口、数组

3、浮点数精度丢失

浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运算的时候要特别小心。
可以考虑采用一些替代方案来实现。如通过 String 结合 BigDecimal 或者通过使用 long 类型来转换。

4、#{}、${}的区别

#{}:Mybatis中#传递参数底层使用PreparedStatement对象,使用占位符方式,相对安全。

${}:Mybatis中$传递参数底层使用Statement对象,字符串拼接方式,相对不安全。

statement:底层传递SQL参数时,使用拼接SQL方式,存在SQL注入安全隐患.

PreparedStatement:底层传递SQL参数时,使用【占位符】方式,相对安全。

所有的标识符都应该以字母(A-Z或者a-z),美元符号($$)或者下划线(_)开始

首字符之后可以是字母(A-Z 或者 a-z),美元符($)、下划线(_)或数字的任何字符组合

不能使用关键字作为变量名或方法名

标识符是大小写敏感的

合法标识符举例:age、$salary、value、 __1_value

5、private的相关知识

private是 一个访问限定修饰符

可修饰的的范围:

修饰成员变量:表示当前成员变量只能在当前类中使用

修饰成员方法:表示当前成员方法只能在当前类中使用

6、Java的集合:

7、索引

索引是帮助MySql高效获取数据的数据结构。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

8、重载、重写

重载的概念 :

在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数 类型不同即可。

重写的概念:

在子类中可以根据需要对从父类中继承来的方法进行改造,也称 为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

二、重载和重写的特点:

重载的特点:

与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类 型)。调用时,根据方法参数列表的不同来区别。

重写的特点:

1.子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表 。

2.子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型 (返回类型为类)。

3.子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限 。

4.子类不能重写父类中声明为private权限的方法 。

5.子类方法抛出的异常不能大于父类被重写方法的异常 (父类异常的子类)。

重写,overriding,是指在继承的情况下,子类中定义了与父类中具有相同型构的新方法,也就是子类重写了父类的方法。

重载,overloading,是在同一个类中,定义了一个以上具有相同名称,但是有着不同型构的方法,在同一个类中是不允许定义多于一个具有相同型构的方法的。

构造器也是可以重载的,实际上,构造器就是一个方法,构造器的名称就是方法的名称。

9、Redis单线程+多线程

Redis数据持久化方式:快照方式和写日志方式

JDK1.7和JDK1.8是Java的两个主要版本。这两个版本之间有许多重要的区别,主要涉及性能改进、新特性和语言改进。下面将详细介绍JDK1.7和JDK1.8之间的主要区别。

一、性能改进

1.1 编译器优化 在JDK1.8中,Java编译器进行了一些优化,包括更好的方法内联、逃逸分析和成员重排序等。这些优化使得JDK1.8在性能方面有所提升,尤其是对于大型、复杂的应用程序。

1.2 垃圾回收器(Garbage Collector) JDK1.8引入了一种新的垃圾回收器,称为G1(Garbage First)。相比于JDK1.7中的CMS(Concurrent Mark and Sweep)回收器,G1回收器具有更好的吞吐量和更低的停顿时间。这对于需要处理大量内存的应用程序来说特别有用。

二、新特性

2.1 Lambda表达式 JDK1.8引入了Lambda表达式,这是一种更为简洁的语法形式,可以替代匿名内部类的使用。Lambda表达式可以更方便地编写函数式接口的实现,使得代码更加简洁、易读。

2.2 Stream API Stream API是JDK1.8中另一个重要的新特性。Stream API提供了一种流式处理集合数据的方式,可以支持各种常见的集合操作,如过滤、映射、排序等。Stream API使得代码编写更简洁、易读,同时还可以提高性能。

三、语言改进

3.1 接口的默认方法 在JDK1.8中,接口中可以定义默认方法。默认方法是指接口中包含了实现的方法,这样实现类就不需要再去实现这些方法了。这对于接口的演化来说是一项重大的改进,可以在不破坏现有代码的情况下添加新的方法。

3.2 新的日期和时间API JDK1.8引入了一套新的日期和时间API,这个API提供了更好的性能和更丰富的功能。新的日期和时间API使用更直观的命名,更易用,同时还修复了JDK1.7中存在的一些问题。

4.总结 JDK1.7和JDK1.8是Java的两个主要版本,它们之间有许多重要的区别。JDK1.8在性能方面进行了一些优化,使得它在处理大型、复杂的应用程序时更高效。JDK1.8引入了Lambda表达式和Stream API这两个重要的新特性,使得代码编写更简洁、易读。同时,JDK1.8还引入了接口的默认方法和新的日期和时间API,进一步改进了Java语言的功能。总的来说,JDK1.8是一个更为先进、强大的Java版本,值得开发者们使用和学习。

10、Jvm

VM是Java语言跨平台的关键,Java在虚拟机层面隐藏了底层技术的复杂性以及机器与操作系统的差异性。运行程序的物理机千差万别,而JVM则在千差万别的物理机上面建立了统一的运行平台,实现了在任意一台JVM上编译的程序,都能在任何其他JVM上正常运行。这一极大的优势使得Java应用的开发比传统C/C++应用的开发更高效快捷,程序员可以把主要精力放在具体业务逻辑,而不是放在保障物理硬件的兼容性上。通常情况下,一个程序员只要了解了必要的Java类库、Java语法,学习适当的第三方开发框架,就已经基本满足日常开发的需要了,JVM会在用户不知不觉中完成对硬件平台的兼容及对内存等资源的管理工作

JVM由三部分组成:类加载子系统、运行时数据区、执行引擎

11、类加载

类加载子系统:通过类加载机制加载类的class文件,如果该类是第一次加载,会执行加载、验证、解析。只负责class文件的加载,至于是否可运行,则由执行引擎决定。

类加载过程是在类加载子系统完成的:加载 --> 链接(验证 --> 准备 --> 解析) --> 初始化

12、运行时数据区

在程序运行时,存储程序的内容(例如字节码、对象、参数、返回值等)。运行时数据区包括本地方法栈、虚拟机栈、方法区、堆、程序计数器。

只有方法区和堆是各线程共享的进程内存区域,其他运行区都是每个线程可以独立拥有的。

本地方法栈:存放本地方法调用过程中的栈帧。用于管理本地方法的调用,本地方法是C语言写的。不是所有虚拟机都支持本地方法栈,例如Hotspot虚拟机就是将本地方法栈和虚拟机栈合二为一。栈解决程序的运行问题,即程序如何执行、如何处理数据。

栈帧:栈帧是栈的元素,由三部分组成,即局部变量表(存方法参数和局部变量)、操作数栈(存方法执行过程中的中间结果,或者其他暂存数据)和帧数据区(存方法返回地址、线程引用等附加信息)。

虚拟机栈:存放Java方法调用过程中的栈帧。用于管理Java方法的调用,Java方法是开发时写的Java方法。

方法区:可以看作是一块独立于Java堆的内存空间,方法区是各线程共享的内存区域。

方法区和永久代、元空间的关系:方法区是一个抽象概念,永久代和元空间是方法区的实现方式。

永久代:属于JVM方法区的内存,用来存储类的元数据,如类名、方法信息、字段信息等一些静态的数据。JDK7及之前方法区也叫永久代。缺点是内存大小固定,容易出现oom问题。可以通过-XX:PermSize设置永久代大小。永久代对象只能通过Major GC(又称Full GC)进行垃圾回收。

元空间:是Hotspot在JDK8引入的,用于取代永久代。元空间属于本地内存,由操作系统直接管理,不再受JVM管理。同时内存空间可以自动扩容,避免内存溢出。默认情况下元空间可以无限使用本地内存,也可以通过-XX:MetaspaceSize限制内存大小。

常量池:就是一张表,JVM根据这张常量表找到要执行的类信息和方法信息

类常量池:是.class字节码文件中的资源仓库,主要存放字面量(表示字符串值和数值,例如字符串值"abc"、final常量、静态变量)和符号引用(类和接口的全限定名、字段名、方法名)。

运行时常量池:类加载的“加载”阶段会创建运行时常量池,统一存放各个类常量池去重后的符号引用。在类加载的“解析”阶段JVM会把运行时常量池的这些符号引用转为直接引用。类常量池。类常量池在字节码文件中的,运行时常量池在内存中。

字符串常量池:专门针对String类型设计的常量池。是当前应用程序里所有线程共享的,每个jvm只有一个字符串常量池。存储字符串对象的引用。在创建String对象时,JVM会先在字符串常量池寻找是否已存在相同字符串的引用,如果有的话就直接返回引用,没的话就在堆中创建一个对象,然后常量池保存这个引用并返回引用。

堆:存放对象实例、实例变量、数组,包括新生代(伊甸园区、幸存区S0和S1)和老年代。堆是垃圾收集器管理的内存区域。堆解决的是数据存储的问题,即数据怎么放、放在哪儿。堆实际内存空间可以不连续,大小可以选择固定大小或可扩展,堆是各线程共享的内存区域。

程序计数器(PC寄存器):存放下一条字节码指令的地址,由执行引擎读取下一条字节码指令并转为本地机器指令进行执行。是程序控制流(分支、循环、跳转、线程恢复)的指示器,只有它不会抛出OutOfMemoryError。每个线程有自己独立的程序计数器,以便于线程在切换回来时能知道下一条指令是什么。程序计数器生命周期与线程一致。

执行引擎:将字节码指令解释/编译为对应平台上的本地机器指令。充当了将高级语言翻译为机器语言的译者。执行引擎在执行过程中需要执行什么样的字节码指令依赖于PC寄存器。每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。

字节码指令(JVM指令):字节码文件中的指令,内部只包含一些能够被JVM所识别的字节码指令、符号表,以及其他辅助信息,不能够直接运行在操作系统之上。

本地机器指令:可以直接运行在操作系统之上。

13、JUC

什么是JUC?

JUC 是 Java Util Concurrent 的缩写,即 Java 并发编程工具包,提供了一些多线程编程常用的类和实用工具,包括原子操作类、线程池、锁、自定义同步器等,可以帮助开发者更容易地编写并发程序。

2. JUC 中的锁有哪些?它们的区别是什么?

JUC 中常见的锁包括 synchronized 关键字、ReentrantLock、ReentrantReadWriteLock、StampedLock 等。其区别如下:

synchronized 锁是 Java 内置的锁机制,它的使用方法非常简单,同一时间只能有一个线程获得锁,其他线程需要等待锁的释放。但它只能实现独占锁,不能实现读写分离。

ReentrantLock 是一种可重入锁,支持独占锁和共享锁,使用灵活,但需要手动释放锁。

ReentrantReadWriteLock 是一种读写锁,读操作可以多线程并发处理,而写操作独占锁,可以提高并发效率,但实现相对复杂。

StampedLock 是 JDK1.8 较新加入的一种锁,它具有乐观锁的特性,能够提高并发读效率,但写操作需要加独占锁。

14、CAS?

CAS 是 Compare and Swap 的缩写,即比较并交换。CAS 是一种基于乐观锁的锁机制,可以实现无锁并发算法,适用于高并发环境。

CAS 的实现原理是,先读取变量的内存地址中的值,和期望的值进行比较,如果相同,则将新值写入这个内存地址,如果不同,则重试整个操作,直到交换成功为止。

15、JUC 中的线程池有哪些类型?

JUC中的线程池有四种类型:

FixedThreadPool:线程池中的线程数一定、不变,适用于长时间处理任务,效率高。

CachedThreadPool:线程池中的线程数可以动态调整,适用于短时间处理任务,效率高。

SingleThreadExecutor:线程池中只有一个线程,适用于顺序执行一些任务。

ScheduledThreadPool:定时执行任务的线程池。

16、JUC 中的 CountDownLatch 是什么?怎么使用?

CountDownLatch 是一种计数器,可以用于实现线程间的等待。它的使用方法如下:

通过构造方法初始化计数器。

通过 countDown() 方法减少计数器的值。

通过 await() 方法等待计数器为 0。

多个线程调用 await() 方法等待计数器的值为 0。

17、JUC 中的 Semaphore 是什么?怎么使用?

Semaphore 是一种信号量,它是一种在多线程环境中协调各个线程,避免出现某一资源供不应求或者竞争过度的机制。Semaphore 可以用于控制某时刻并发访问的数量,使用方法如下:

通过构造方法初始化信号量的数量。

通过 acquire() 方法获取信号量的锁。

通过 release() 方法释放信号量的锁。

18、JUC 中的 BlockingQueue 是什么?有哪些实现方式?

BlockingQueue 是一种阻塞队列,可以实现线程间的阻塞式等待和通信,是一种实现生产者—消费者模型的有效方式。JUC 提供的 BlockingQueue 实现有以下几种:

ArrayBlockingQueue:基于数组的有界阻塞队列。

LinkedBlockingQueue:基于链表的可选有界阻塞队列。

PriorityBlockingQueue:支持优先级排序的无界阻塞队列。

SynchronousQueue:不存储元素的阻塞队列。

19、 JUC 中的 FutureTask 是什么?怎么使用?

FutureTask 是一种可用于异步获取操作结果的类,可以用于类似于线程池的场景中,批量提交任务,然后获取执行结果。FutureTask 的使用流程如下:

创建 Callable 对象。

创建 FutureTask 对象,将 Callable 对象传入。

使用 FutureTask 对象作为线程的任务,使用线程执行器(如 ThreadPoolExecutor)来执行线程任务。

调用 get() 方法阻塞等待当前线程任务执行完毕并返回结果。

20、JUC 中的 ConcurrentHashMap 是什么?为什么可以实现高并发?

ConcurrentHashMap 是一种高效、线程安全的 Map 集合,可以实现更高效的并发访问。从 JDK1.8 开始,Java 采用 CAS 和 Synchronized 结合的方式对 ConcurrentHashMap 进行了一些优化,可以实现高并发的读写操作,且在容器操作较为频繁的情况下,相对于 Hashtable 和 Collections.synchronizedMap 等集合实现类,性能更好。

21  JUC 中的 LockSupport 是什么?有什么作用?

LockSupport 是一种线程阻塞工具,可以实现类似于 wait() 方法的阻塞等待效果,但它比 wait() 方法更加灵活和高效。LockSupport 提供了 park() 和 unpark() 两个方法来实现线程的阻塞和唤醒,可以用于线程间的通信。

22 JUC 中的 CyclicBarrier 是什么?怎么使用?

CyclicBarrier 是一种线程阻塞工具,可以等待所有线程完成某个阶段的任务后再执行下一个阶段的任务。可以看做是一种多线程协作的计数器,通过计数器的值来确定此次所有线程是否完成任务。CyclicBarrier 的使用方法如下:

通过构造方法初始化计数器,指定等待的线程数。

每个线程调用 await() 方法表示到达当前阶段的同步点,等待其他线程到达。

当所有线程都到达同步点后,计数器的值变为 0,线程可以继续执行下一阶段的任务。

23   JUC 中的 Exchanger 是什么?有什么作用?

Exchanger 是一种工具类,可以用于两个线程之间的数据交换,支持实现线程间的数据共享和同步。Exchanger 的使用方法如下:

通过构造方法创建 Exchanger 对象。

线程 A 通过 exchange() 方法交换数据。

线程 B 通过 exchange() 方法交换数据。

数据完成交换后,线程 A 和线程 B 都将获取到对方传输过来的数据。

24 JUC 中的 ForkJoinPool 是什么?有什么作用?

FprkJoinPool 是一种支持任务窃取的线程池,可以将大任务分解为若干子任务进行并行执行,提高任务的并行度。ForkJoinPool 采用“工作窃取”模式,在执行完自己的任务之后,可以从其他线程的队列中获取任务进行执行,能够充分利用 CPU 资源,提升执行效率。

25  JUC 中的 ThreadLocal 是什么?有什么作用?

ThreadLocal 是一种线程本地变量,可以允许多个线程并发访问同一个变量,但它是基于线程的隔离机制实现的,可以保证变量对每个线程都是独立的。ThreadLocal 的主要使用场景包括为每个线

26  JUC 中的 Lock 接口常用的方法有哪些?怎么应用到实际开发中?

Lock 接口常用的方法包括 lock()、 tryLock()、 unlock()、newCondition()。其中 lock() 方法可以获取锁,tryLock() 方法尝试获取锁, unlock() 方法释放锁,newCondition() 方法可以创建与锁相关的 condition 对象,用于实现等待/通知模式。

Lock 接口可以应用于实际开发中的同步代码块中,可以使用 ReentrantLock 增强原有的同步机制,提高程序的并发性能和灵活性。

27 JUC 中的 AtomicInteger 是什么?有什么作用?

AtomicInteger 是一种原子类,可以保证对数值的增量/减量操作是原子性的,且不会产生竞争冲突,能够实现线程安全访问变量。AtomicInteger 可以应用于环境下对同一个变量的多次修改更新操作,避免数据更新时对同一变量产生冲突。

28 JUC 中的 CopyOnWriteArrayList 是什么?有什么作用?

CopyOnWriteArrayList 是一种线程安全的 ArrayList, 其实现基于“写时复制”技术,当对其进行并发修改时,不会对原始数据产生影响,而是暂时性的复制出一个副本进行操作,可以避免并发修改导致的数据损坏和不一致性。

29  JUC 中的 Phaser 是什么?怎么使用?

Phaser(阶段器)是一种新的线程同步工具,主要用于分阶段的任务,它可以灵活的控制阶段的完成次数,当所有关联的线程都完成当前阶段时,才可以进入下一阶段,


http://www.kler.cn/a/473056.html

相关文章:

  • Spring Boot教程之四十九:Spring Boot – MongoRepository 示例
  • C语言的语法
  • Python创建GitHub标签的Django管理命令
  • 用JAVA编写一个简单的小游戏
  • BeanFactory与factoryBean 区别,请用源码分析,及spring中涉及的点,及应用场景
  • el-table 多级表头
  • 【LeetCode Hot100 贪心算法】 买卖股票的最佳时机、跳跃游戏、划分字母区间
  • 【网络云SRE运维开发】2025第2周-每日【2025/01/08】小测-【第8章 STP生成树协议】理论和实操
  • 【Linux】shell脚本编程
  • 详解opencv resize之INTER_LINEAR和INTER_AREA
  • 用户注册模块(芒果头条项目进度4)
  • JVM三JVM虚拟机
  • 战地雷达通信系统中无人机与特种车辆智能组网及雷达通信一体化研究报告
  • UE蓝图节点备忘录
  • C++ 泛型编程:动态数据类模版类内定义、类外实现
  • 嵌入式系统 (2.嵌入式硬件系统基础)
  • 文献阅读分享:ChatGPT在推荐系统中的偏见研究
  • 使用Qt实现json数据的格式检测并序列化输出 Qt5.4.0环境
  • 根据docker file 编译镜像
  • 入门嵌入式(六)——定时器
  • GPIO输入及两个应用案例
  • 『SQLite』解释执行(Explain)
  • benchANT 性能榜单技术解读 Part 1:写入吞吐
  • 金融租赁系统助力行业转型与升级的创新之路
  • 生成模型:变分自编码器-VAE
  • 产品经理-商业模式构建 - AxureMost