概念Java的特点平台无关性一次编写到处运行。面向对象Java是一门严格的面向对象编程语言一切皆对象。内存管理Java有自己的垃圾回收机制自动管理内存和回收不再使用的对象。Java的优、劣势优势跨平台、面向对象、强大的生态系统、内存管理、多线程支持、安全性、稳定性。劣势性能、语法繁琐、内存消耗、面向对象过于严格、开发效率较低。Java为什么是跨平台的主要依赖于JVM。Java程序经编译生成字节码文件.classJVM可以将字节码文件翻译成特定平台下的机器码然后运行。只需要在不同平台安装不同版本的JVM就能运行Java程序从而实现“一次编写到处运行”。注意Java代码和编译后产生的字节码都是同一份JVM将相同的字节码文件翻译成不同平台对应的机器码从而让Java程序能在不同平台运行如下图JVM、JRE、JDK三者关系包含关系如下图JVMJava虚拟机。是Java程序运行的环境。JVM 执行引擎能跑字节码但没东西可跑。JREJava运行时环境。是Java程序运行所需的最小环境。JRE JVM 核心类库 其他运行时组件类加载器、校验器等。JDKJava开发工具包。是开发Java程序所需工具的集合提供了开发、编译、调试和运行Java程序所需的全部工具和环境。JDK JRE 编译器等开发工具。JVM和Java的区别JVM是一个平台也是一种软件是跑代码的环境Java是一种编程语言是一种写代码的工具。二者分工不同但相互配合如下图概念解释热点代码被 JVM 统计出来的、频繁执行的代码方法/循环是 JIT 编译的对象。阈值一个次数标准比如 10000 次达到这个标准就触发 JIT 编译。JVM是什么JVM是Java虚拟机主要工作是解释自己的指令集即字节码并映射到本地的CPU指令集和OS的系统调用。JVM屏蔽了与操作系统平台相关的信息使得Java程序只需要通过编译生成在Java虚拟机上运行的目标代码字节码就可以在多种平台上不加修改地运行即“一次编译到处运行”。编译型语言和解释型语言的区别编译型语言在程序执行之前整个程序的源代码会被编译成目标平台的机器码生成可执行文件。执行时直接运行编译后的代码速度快但跨平台性较差。典型的编译型语言如C、C。解释型语言在程序执行时逐行解释源代码并执行不生成独立的可执行文件。通常由解释器动态解释并执行代码跨平台性好但执行速度相对较慢。典型的解释型语言如Python、JavaScript。Python和Java的区别Java是一种编译与解释混合执行的语言源代码先被javac预编译成字节码再由JVM加载后通过解释器和JIT即时编译器执行。Python是一种解释型语言运行时由解释器逐行解释源代码并执行。Python内部也会先预编译为字节码.pyc但整体执行模型仍以解释型为主值传递与引用传递的区别值传递传递的是实际值的副本。适用于基本数据类型修改方法内的参数不会影响原变量的值。引用传递传递的是对象引用的副本而非对象本身原引用与副本引用指向同一个对象。通过副本引用修改对象内部数据会影响原对象但若修改的是副本引用的指向如重新赋值则不会影响原引用的指向。注意在Java中参数传递并不存在真正的“引用传递”所谓的引用传递其本质也是值传递只不过传递的不是实际值的副本而是引用的副本。数据类型八种基本数据类型Java八种基本数据类型的字节数1字节byte、boolean、2字节short、char、4字节int、float、8字节long、double。浮点数的默认类型为double如果需要声明一个常量为float型则必须要在末尾加上f域F。整数的默认类型为int声明Long型在末尾加上l或者L。八种基本数据类型的包装类除了char的是Character、int类型的是Integer其他都是首字母大写。char类型是无符号的不能为负所以是0开始的。int和long是多少位、多少字节的int类型是32位bit占4个字节bytelong类型是64位bit占8个字节byte。int类型和long类型都是有符号整数类型int类型的取值范围是从-231到231-1long类型的取值范围是从-263到263-1。long和int可以互转吗可以。但是long转int时需要注意溢出问题。int转long可以直接赋值也可以强制类型转换因为long的位数比int多可表示的数字范围也更大所以long转int是安全的。long转int必须使用强制类型转换且需要注意数据丢失或溢出问题。当long的值超出了int类型可表示的范围其转换的结果是截断后的低位部分。所以在进行转换之前最好先检查long的值是否在int类型可表示的数据范围之内。数据类型转换方式自动类型转换隐式转换、强制类型转换显示转换、字符串转换、数值之间的转换。自动类型转换隐式转换目标类型的范围大于原类型。例如int转long、float转double等。强制类型转换显示转换目标类型的范围小于原类型。例如long转int、double转int等。字符串转换Java提供了将字符串表示的数值数据转换为其他数值类型的方法例如Integer.parseInt()方法可以将字符串转换为整型intDouble.parseDouble()可以将字符串转换为浮点型double。数值之间的转换Java提供的包装类中封装了一些数值类型之间的转换方法。例如整型与字符型之间的互转。类型互转会出现什么问题基本数据类型转换的问题大范围数据转小范围数据存在潜在的数据溢出或精度损失的问题。数据溢出例如long转int。精度损失由于浮点数的表示方式不同所以进行浮点数类型的转换时可能会发生精度损失例如float转double。此外double转int会将小数部分舍弃所以也会发生精度损失问题。对象引用转换的问题进行向下转型时若父类对象实际上并不是目标子类的实例转型时就会抛出ClassCastException异常。原因在于Java的对象在运行时会记录其真是类型当进行向下转型时Java会检查对象的实际类型是否与目标类型兼容。建议在转换之前用instanceof检查。为什么用BigDecimal不用double?double会出现精度丢失问题而BigDecimal是精确计算。所以一般牵扯到金钱的计算都用BigDecimal。double执行的是二进制浮点运算有些情况下不能精确地表示一个小数就像十进制无法精确地表示1/31/30.333…。二进制表示小数只能表示能够用1/(2^n)表示的任意组合。BigDecimal可以确保精确的十进制数值计算避免了double可能出现的舍入误差。但需注意在创建BigDecimal对象时应该使用字符串作为参数而不能直接使用浮点数以避免浮点数精度丢失问题。装箱和拆箱是什么装箱基本数据类型转换为对应的包装类。拆箱包装类转换为对应的基本数据类型。自动装箱一般发生在赋值和方法调用时。自动装箱也有弊端不必要的频繁装箱会创建多余的包装类对象从而引起性能问题。自动装箱实际上是由编译器将语句替换为Xxx.valueOf(…)调用例如Integer i 1就是Integer i Integer.valueOf(1)。Java为什么要有Integer第一Java是一种严格的面向对象的编程语言一切皆对象将基本类型封装成类类型符合其面向对象编程的思想第二Java中绝大部分方法或类都是用来处理类类型对象的第三Java中的泛型只能使用引用类型不能使用基本类型第四在Java中基本类型和引用类型不能直接进行转换必须通过包装类来实现第五Java集合只能存储对象不能存储基本数据类型。Integer相比int有什么优点Integer是int类型的包装类。其核心优势体现以下几点能表达null语义。int是基本数据类型有默认值为0无法区分“值为0”和“无值/未赋值”而Integer是对象引用可以赋值为null在数据库字段可为空、接口返回可能缺失的数值等场景下非常有用。泛型支持Java泛型只能使用对象类型不能使用基本类型。提供丰富的对象方法Integer提供了许多实用工具方法方便操作。例如Integer.parseInt(String)可以实现字符串转整数。缓存优化机制Integer内部缓存了-128~127之间的常用数值多次valueOf返回同一对象节省内存并提升性能。那为什么还要保留int类型Integer相比int的缺点包装类是引用类型对象的引用和对象本身是分开存储的而对于基本数据类型变量对应的内存块直接存储数据本身。因此基本类型数据在读写效率方面要优于包装类。此外Integer占用内存更大一个Integer对象约16个字节而int类型才4个字节。Integer的缓存Integer类的内部实现了一个静态缓存池用于存储特定范围内的整数数值对应的Integer对象。默认情况下这个范围是从-128到127。当通过Integer.valueOf(int)方法创建一个在这个范围内的整数对象时并不会每次都生成新的对象实例而是复用缓存池中的现有对象。面向对象怎么理解面向对象简单说说封装、继承和多态面向对象是一种编程范式它将现实世界中的事物抽象为对象对象具有属性和行为方法。面向对象编程的设计思想是以对象为中心通过对象之间的交互来完成程序的功能具有灵活性和可扩展性。Java面向对象具有三大特性封装、继承和多态。封装封装是指将对象的属性数据和行为方法结合在一起对外隐藏对象的内部细节仅通过对象提供的接口与外界交互。封装的目的是增强安全性和简化编程使得对象更加独立。继承继承是一种可以使得子类自动共享父类数据结构和方法的机制。它是代码复用的重要手段通过继承可以建立类与类之间的层次关系使得结构更加清晰。多态多态是指允许不同类的对象对同一消息作出响应。即同一个接口使用不同的实例而执行不同的操作。多态可以分为编译时多态重载和运行时多态重写。它使得程序具有良好的灵活性和可扩展性。多态体现在哪几个方面多态在面向对象编程中主要体现在方法重载、方法重写、接口与实现、向上转型和向下转型这四个方面。方法重载指同一个类中可以有多个同名方法它们具有不同的参数列表参数类型、数量或顺序不同。编译器会在编译时根据传入的参数来确定调用哪个方法。方法重写指子类能够提供对父类中同名方法的具体实现。在运行时JVM会根据对象的实际类型来确定调用哪个版本的方法。接口与实现多个类可以实现同一个接口并且可以用接口类型的引用来调用这些类的方法。这使得程序在面对不同具体实现时保持一贯的调用方式。向上转型和向下转型向上转型是指使用父类类型的引用指向子类对象通过这种方式可以在运行时采用不同的子类实现。向下转型是指将父类引用转回其子类类型但在转换前建议使用instanceof检查对象的实际类型是否与目标类型兼容以避免ClassCastException异常。多态解决了什么问题多态是指子类可以替换父类在实际的代码运行过程中调用子类的方法实现。多态可以提高代码的扩展性和复用性。例如基于接口而非实现编程、依赖倒置原则、利用多态去掉冗长的if-else语句等等。面向对象的设计原则面向对象编程有六大原则单一职责原则SRP接口应该小而专开放封闭原则OCP对扩展开放对修改封闭里氏替换原则LSP子类对象应该能够替换所有的父类对象接口隔离原则ISP接口应该小而专依赖倒置原则DIP高层不应该依赖于底层二者都应该依赖于抽象高层调用接口底层实现接口抽象不应该依赖于细节细节应该依赖于抽象。最少知识原则LoD一个类应该只与它的直接朋友交互与外界只能通过它朋友提供的接口间接地交互它的朋友包括对象自身、方法参数传入的对象、成员变量引用的对象、方法内部创建的对象。重载与重写有什么区别重载又称编译时多态指同一个类中定义有多个同名方法但是它们的参数列表不同。重写又称运行时多态指子类重写父类的方法方法名、参数、返回值类型必须与父类保持一致。设计用途普通类既可以直接使用也可以被继承而抽象类主要作为基类被继承扩展。抽象类和普通类区别实例化普通类可以直接new抽象类不可以只能被继承。方法实现普通类不能有抽象方法所有的方法都要有实现而抽象类的方法既可以有实现也可以没有。抽象类和普通类的相同点都能有普通方法。都只能单继承。都可以实现多个接口。Java抽象类和接口的区别本质区别抽象类描述的是is-a关系例如猫是一种动物接口描述的是can-do能力例如猫可以爬树、鸟可以飞用接口。具体区别实现方式实现接口的关键字是implements继承抽象类的关键字是extends一个类可以实现多个接口但只能继承一个抽象类。方法是否能有默认实现抽象类从诞生起就可以有具体方法而接口在Java8之前只能有抽象方法在Java8之后可以用default方法提供默认实现用static方法提供工具方法。成员变量抽象类的变量可以是普通的可以被子类修改而接口的变量必须是public static final常量一定义就得赋值不可被修改。构造方法抽象类可以有构造方法接口完全没有构造方法。访问修饰符抽象类的方法可以是public、protected、default、private普通方法抽象方法不能是private、static、native而接口的抽象方法默认public abstract不能写其他修饰符Java9之后可以有private方法但只能被接口内的default方法调用。抽象类能加final修饰吗不能。Java中的抽象类是用来被继承的而final修饰符是禁止类被继承或方法被重写的二者天生互斥。接口里面可以定义哪些方法Java8之前只能定义抽象方法默认被public abstract修饰Java8之后可以用default方法提供默认实现用static方法提供工具方法Java9之后可以有private方法但只能被接口内的default方法调用。抽象类可以被实例化吗不可以。抽象类的存在主要是作为基类被其他类继承虽然可以有构造函数但只是用来做一些初始化工作在子类实例化时被调用。接口可以包含构造函数吗不可以。接口主要是做一些行为上的约定can-do只用来被实现不会有实例所以没有也不需要有构造函数。解释Java中的静态变量和静态方法静态变量被static修饰属于类而不是属于某一个对象在内存中只存在一份可以被类的所有实例共享只在类加载时进行一次内存分配可以直接通过类名.变量名访问。静态方法被static修饰属于类而不是属于某一个对象在内存中只存在一份可以被类的所有实例共享静态方法中只能访问静态变量和静态方法可以直接通过类名.方法名调用不可以被重写但可以被隐藏子类方法上不加Override注解是在编译时绑定而非运行时动态绑定。非静态内部类和静态内部类的区别本质区别非静态内部类是属于某个外部类对象的而静态内部类是属于外部类本省的就像外部类的一个静态成员。具体区别是否依赖外部实例非静态内部类必须依赖外部实例而静态内部类不依赖外部示例可以独立存在。创建方式非静态内部类通过外部类实例.new 内部类()创建对象而静态内部类直接通过new 外部类.静态内部类()创建对象。访问外部类实例成员非静态内部类可以直接访问而静态内部类需要通过外部实例访问想一想如果没有外部类实例那这个实例成员肯定也不存在但是静态变量可以在没有外部类实例的时候独立存在所以它要访问外部类的实例成员肯定要在有外部类实例的前提下才能访问。能否定义静态成员非静态内部类在Java16之前不能毕竟它是依赖于外部类实例的如果有静态成员这个静态成员肯定是属于类而不依赖实例那就相互矛盾了而静态内部类可以定义静态成员变量。非静态内部类为什么不能有静态方法因为非静态内部类的实例必须绑定到外部类实例而静态方法属于类不依赖实例。如果允许那么调用 Inner.staticMethod() 时不需要任何外部类实例这与非静态内部类“必须依附于外部类实例”的设计矛盾。Java 16 后允许静态常量但仍有严格限制。什么时候用静态内部类当内部类和外部类实例无关时用静态内部类。例如 HashMap.Node 是静态内部类一个节点不需要知道它属于哪个 HashMap 对象。当内部类必须访问外部类实例成员时用非静态内部类例如迭代器它需要知道当前集合对象。非静态内部类可以直接访问外部方法编译器是怎么做到的编译器在生成字节码时会给非静态内部类加了一个“隐藏的”外部类引用比如叫 this$0在生成非静态内部类的构造方法时将外部类实例作为参数传入并在内部类的实例化过程中建立外部类实例与内部类实例之间的联系从而实现直接访问外部方法的功能。步骤一给内部类增加一个隐藏字段。步骤二修改内部类的构造方法。步骤三在构造方法中保存外部引用。关键字Java中final的作用修饰类、方法、变量。修饰类被修饰的类不能被其他类继承。修饰方法被修饰的方法不能被子类重写。修饰变量修饰基本数据类型时表示该变量一旦被赋值就不能再改变修饰引用数据类型时表示该引用不能再指向其他对象但是该引用指向的对象的内容还是可以修改的即限制的只是引用本身指向而非引用指向的对象。Java中static的作用修饰类的成员变量、方法、代码块和内部类。修饰变量被修饰的变量属于类本身在内存中只存在一份类的所有实例共享同一份静态变量。通常用于存储所有对象共享的数据如常量、计数器等。修饰方法被修饰的方法属于类本身在内存中只有一份。通常用于工具类方法如 Math.random()、工厂方法等不需要依赖对象状态即可完成操作。修饰代码块静态代码块在类初始化阶段执行且只执行一次JVM的类生命周期为加载 — 链接验证、准备、解析— 初始化通常用于初始化静态变量或执行类级别的预处理操作。修饰内部类静态内部类不依赖于外部类的实例可以独立存在。在内部类与外部类的实例无关时使用避免内部类持有外部类的引用导致的内存泄漏。
Java基础面试题总结(一)
发布时间:2026/6/3 18:29:24
概念Java的特点平台无关性一次编写到处运行。面向对象Java是一门严格的面向对象编程语言一切皆对象。内存管理Java有自己的垃圾回收机制自动管理内存和回收不再使用的对象。Java的优、劣势优势跨平台、面向对象、强大的生态系统、内存管理、多线程支持、安全性、稳定性。劣势性能、语法繁琐、内存消耗、面向对象过于严格、开发效率较低。Java为什么是跨平台的主要依赖于JVM。Java程序经编译生成字节码文件.classJVM可以将字节码文件翻译成特定平台下的机器码然后运行。只需要在不同平台安装不同版本的JVM就能运行Java程序从而实现“一次编写到处运行”。注意Java代码和编译后产生的字节码都是同一份JVM将相同的字节码文件翻译成不同平台对应的机器码从而让Java程序能在不同平台运行如下图JVM、JRE、JDK三者关系包含关系如下图JVMJava虚拟机。是Java程序运行的环境。JVM 执行引擎能跑字节码但没东西可跑。JREJava运行时环境。是Java程序运行所需的最小环境。JRE JVM 核心类库 其他运行时组件类加载器、校验器等。JDKJava开发工具包。是开发Java程序所需工具的集合提供了开发、编译、调试和运行Java程序所需的全部工具和环境。JDK JRE 编译器等开发工具。JVM和Java的区别JVM是一个平台也是一种软件是跑代码的环境Java是一种编程语言是一种写代码的工具。二者分工不同但相互配合如下图概念解释热点代码被 JVM 统计出来的、频繁执行的代码方法/循环是 JIT 编译的对象。阈值一个次数标准比如 10000 次达到这个标准就触发 JIT 编译。JVM是什么JVM是Java虚拟机主要工作是解释自己的指令集即字节码并映射到本地的CPU指令集和OS的系统调用。JVM屏蔽了与操作系统平台相关的信息使得Java程序只需要通过编译生成在Java虚拟机上运行的目标代码字节码就可以在多种平台上不加修改地运行即“一次编译到处运行”。编译型语言和解释型语言的区别编译型语言在程序执行之前整个程序的源代码会被编译成目标平台的机器码生成可执行文件。执行时直接运行编译后的代码速度快但跨平台性较差。典型的编译型语言如C、C。解释型语言在程序执行时逐行解释源代码并执行不生成独立的可执行文件。通常由解释器动态解释并执行代码跨平台性好但执行速度相对较慢。典型的解释型语言如Python、JavaScript。Python和Java的区别Java是一种编译与解释混合执行的语言源代码先被javac预编译成字节码再由JVM加载后通过解释器和JIT即时编译器执行。Python是一种解释型语言运行时由解释器逐行解释源代码并执行。Python内部也会先预编译为字节码.pyc但整体执行模型仍以解释型为主值传递与引用传递的区别值传递传递的是实际值的副本。适用于基本数据类型修改方法内的参数不会影响原变量的值。引用传递传递的是对象引用的副本而非对象本身原引用与副本引用指向同一个对象。通过副本引用修改对象内部数据会影响原对象但若修改的是副本引用的指向如重新赋值则不会影响原引用的指向。注意在Java中参数传递并不存在真正的“引用传递”所谓的引用传递其本质也是值传递只不过传递的不是实际值的副本而是引用的副本。数据类型八种基本数据类型Java八种基本数据类型的字节数1字节byte、boolean、2字节short、char、4字节int、float、8字节long、double。浮点数的默认类型为double如果需要声明一个常量为float型则必须要在末尾加上f域F。整数的默认类型为int声明Long型在末尾加上l或者L。八种基本数据类型的包装类除了char的是Character、int类型的是Integer其他都是首字母大写。char类型是无符号的不能为负所以是0开始的。int和long是多少位、多少字节的int类型是32位bit占4个字节bytelong类型是64位bit占8个字节byte。int类型和long类型都是有符号整数类型int类型的取值范围是从-231到231-1long类型的取值范围是从-263到263-1。long和int可以互转吗可以。但是long转int时需要注意溢出问题。int转long可以直接赋值也可以强制类型转换因为long的位数比int多可表示的数字范围也更大所以long转int是安全的。long转int必须使用强制类型转换且需要注意数据丢失或溢出问题。当long的值超出了int类型可表示的范围其转换的结果是截断后的低位部分。所以在进行转换之前最好先检查long的值是否在int类型可表示的数据范围之内。数据类型转换方式自动类型转换隐式转换、强制类型转换显示转换、字符串转换、数值之间的转换。自动类型转换隐式转换目标类型的范围大于原类型。例如int转long、float转double等。强制类型转换显示转换目标类型的范围小于原类型。例如long转int、double转int等。字符串转换Java提供了将字符串表示的数值数据转换为其他数值类型的方法例如Integer.parseInt()方法可以将字符串转换为整型intDouble.parseDouble()可以将字符串转换为浮点型double。数值之间的转换Java提供的包装类中封装了一些数值类型之间的转换方法。例如整型与字符型之间的互转。类型互转会出现什么问题基本数据类型转换的问题大范围数据转小范围数据存在潜在的数据溢出或精度损失的问题。数据溢出例如long转int。精度损失由于浮点数的表示方式不同所以进行浮点数类型的转换时可能会发生精度损失例如float转double。此外double转int会将小数部分舍弃所以也会发生精度损失问题。对象引用转换的问题进行向下转型时若父类对象实际上并不是目标子类的实例转型时就会抛出ClassCastException异常。原因在于Java的对象在运行时会记录其真是类型当进行向下转型时Java会检查对象的实际类型是否与目标类型兼容。建议在转换之前用instanceof检查。为什么用BigDecimal不用double?double会出现精度丢失问题而BigDecimal是精确计算。所以一般牵扯到金钱的计算都用BigDecimal。double执行的是二进制浮点运算有些情况下不能精确地表示一个小数就像十进制无法精确地表示1/31/30.333…。二进制表示小数只能表示能够用1/(2^n)表示的任意组合。BigDecimal可以确保精确的十进制数值计算避免了double可能出现的舍入误差。但需注意在创建BigDecimal对象时应该使用字符串作为参数而不能直接使用浮点数以避免浮点数精度丢失问题。装箱和拆箱是什么装箱基本数据类型转换为对应的包装类。拆箱包装类转换为对应的基本数据类型。自动装箱一般发生在赋值和方法调用时。自动装箱也有弊端不必要的频繁装箱会创建多余的包装类对象从而引起性能问题。自动装箱实际上是由编译器将语句替换为Xxx.valueOf(…)调用例如Integer i 1就是Integer i Integer.valueOf(1)。Java为什么要有Integer第一Java是一种严格的面向对象的编程语言一切皆对象将基本类型封装成类类型符合其面向对象编程的思想第二Java中绝大部分方法或类都是用来处理类类型对象的第三Java中的泛型只能使用引用类型不能使用基本类型第四在Java中基本类型和引用类型不能直接进行转换必须通过包装类来实现第五Java集合只能存储对象不能存储基本数据类型。Integer相比int有什么优点Integer是int类型的包装类。其核心优势体现以下几点能表达null语义。int是基本数据类型有默认值为0无法区分“值为0”和“无值/未赋值”而Integer是对象引用可以赋值为null在数据库字段可为空、接口返回可能缺失的数值等场景下非常有用。泛型支持Java泛型只能使用对象类型不能使用基本类型。提供丰富的对象方法Integer提供了许多实用工具方法方便操作。例如Integer.parseInt(String)可以实现字符串转整数。缓存优化机制Integer内部缓存了-128~127之间的常用数值多次valueOf返回同一对象节省内存并提升性能。那为什么还要保留int类型Integer相比int的缺点包装类是引用类型对象的引用和对象本身是分开存储的而对于基本数据类型变量对应的内存块直接存储数据本身。因此基本类型数据在读写效率方面要优于包装类。此外Integer占用内存更大一个Integer对象约16个字节而int类型才4个字节。Integer的缓存Integer类的内部实现了一个静态缓存池用于存储特定范围内的整数数值对应的Integer对象。默认情况下这个范围是从-128到127。当通过Integer.valueOf(int)方法创建一个在这个范围内的整数对象时并不会每次都生成新的对象实例而是复用缓存池中的现有对象。面向对象怎么理解面向对象简单说说封装、继承和多态面向对象是一种编程范式它将现实世界中的事物抽象为对象对象具有属性和行为方法。面向对象编程的设计思想是以对象为中心通过对象之间的交互来完成程序的功能具有灵活性和可扩展性。Java面向对象具有三大特性封装、继承和多态。封装封装是指将对象的属性数据和行为方法结合在一起对外隐藏对象的内部细节仅通过对象提供的接口与外界交互。封装的目的是增强安全性和简化编程使得对象更加独立。继承继承是一种可以使得子类自动共享父类数据结构和方法的机制。它是代码复用的重要手段通过继承可以建立类与类之间的层次关系使得结构更加清晰。多态多态是指允许不同类的对象对同一消息作出响应。即同一个接口使用不同的实例而执行不同的操作。多态可以分为编译时多态重载和运行时多态重写。它使得程序具有良好的灵活性和可扩展性。多态体现在哪几个方面多态在面向对象编程中主要体现在方法重载、方法重写、接口与实现、向上转型和向下转型这四个方面。方法重载指同一个类中可以有多个同名方法它们具有不同的参数列表参数类型、数量或顺序不同。编译器会在编译时根据传入的参数来确定调用哪个方法。方法重写指子类能够提供对父类中同名方法的具体实现。在运行时JVM会根据对象的实际类型来确定调用哪个版本的方法。接口与实现多个类可以实现同一个接口并且可以用接口类型的引用来调用这些类的方法。这使得程序在面对不同具体实现时保持一贯的调用方式。向上转型和向下转型向上转型是指使用父类类型的引用指向子类对象通过这种方式可以在运行时采用不同的子类实现。向下转型是指将父类引用转回其子类类型但在转换前建议使用instanceof检查对象的实际类型是否与目标类型兼容以避免ClassCastException异常。多态解决了什么问题多态是指子类可以替换父类在实际的代码运行过程中调用子类的方法实现。多态可以提高代码的扩展性和复用性。例如基于接口而非实现编程、依赖倒置原则、利用多态去掉冗长的if-else语句等等。面向对象的设计原则面向对象编程有六大原则单一职责原则SRP接口应该小而专开放封闭原则OCP对扩展开放对修改封闭里氏替换原则LSP子类对象应该能够替换所有的父类对象接口隔离原则ISP接口应该小而专依赖倒置原则DIP高层不应该依赖于底层二者都应该依赖于抽象高层调用接口底层实现接口抽象不应该依赖于细节细节应该依赖于抽象。最少知识原则LoD一个类应该只与它的直接朋友交互与外界只能通过它朋友提供的接口间接地交互它的朋友包括对象自身、方法参数传入的对象、成员变量引用的对象、方法内部创建的对象。重载与重写有什么区别重载又称编译时多态指同一个类中定义有多个同名方法但是它们的参数列表不同。重写又称运行时多态指子类重写父类的方法方法名、参数、返回值类型必须与父类保持一致。设计用途普通类既可以直接使用也可以被继承而抽象类主要作为基类被继承扩展。抽象类和普通类区别实例化普通类可以直接new抽象类不可以只能被继承。方法实现普通类不能有抽象方法所有的方法都要有实现而抽象类的方法既可以有实现也可以没有。抽象类和普通类的相同点都能有普通方法。都只能单继承。都可以实现多个接口。Java抽象类和接口的区别本质区别抽象类描述的是is-a关系例如猫是一种动物接口描述的是can-do能力例如猫可以爬树、鸟可以飞用接口。具体区别实现方式实现接口的关键字是implements继承抽象类的关键字是extends一个类可以实现多个接口但只能继承一个抽象类。方法是否能有默认实现抽象类从诞生起就可以有具体方法而接口在Java8之前只能有抽象方法在Java8之后可以用default方法提供默认实现用static方法提供工具方法。成员变量抽象类的变量可以是普通的可以被子类修改而接口的变量必须是public static final常量一定义就得赋值不可被修改。构造方法抽象类可以有构造方法接口完全没有构造方法。访问修饰符抽象类的方法可以是public、protected、default、private普通方法抽象方法不能是private、static、native而接口的抽象方法默认public abstract不能写其他修饰符Java9之后可以有private方法但只能被接口内的default方法调用。抽象类能加final修饰吗不能。Java中的抽象类是用来被继承的而final修饰符是禁止类被继承或方法被重写的二者天生互斥。接口里面可以定义哪些方法Java8之前只能定义抽象方法默认被public abstract修饰Java8之后可以用default方法提供默认实现用static方法提供工具方法Java9之后可以有private方法但只能被接口内的default方法调用。抽象类可以被实例化吗不可以。抽象类的存在主要是作为基类被其他类继承虽然可以有构造函数但只是用来做一些初始化工作在子类实例化时被调用。接口可以包含构造函数吗不可以。接口主要是做一些行为上的约定can-do只用来被实现不会有实例所以没有也不需要有构造函数。解释Java中的静态变量和静态方法静态变量被static修饰属于类而不是属于某一个对象在内存中只存在一份可以被类的所有实例共享只在类加载时进行一次内存分配可以直接通过类名.变量名访问。静态方法被static修饰属于类而不是属于某一个对象在内存中只存在一份可以被类的所有实例共享静态方法中只能访问静态变量和静态方法可以直接通过类名.方法名调用不可以被重写但可以被隐藏子类方法上不加Override注解是在编译时绑定而非运行时动态绑定。非静态内部类和静态内部类的区别本质区别非静态内部类是属于某个外部类对象的而静态内部类是属于外部类本省的就像外部类的一个静态成员。具体区别是否依赖外部实例非静态内部类必须依赖外部实例而静态内部类不依赖外部示例可以独立存在。创建方式非静态内部类通过外部类实例.new 内部类()创建对象而静态内部类直接通过new 外部类.静态内部类()创建对象。访问外部类实例成员非静态内部类可以直接访问而静态内部类需要通过外部实例访问想一想如果没有外部类实例那这个实例成员肯定也不存在但是静态变量可以在没有外部类实例的时候独立存在所以它要访问外部类的实例成员肯定要在有外部类实例的前提下才能访问。能否定义静态成员非静态内部类在Java16之前不能毕竟它是依赖于外部类实例的如果有静态成员这个静态成员肯定是属于类而不依赖实例那就相互矛盾了而静态内部类可以定义静态成员变量。非静态内部类为什么不能有静态方法因为非静态内部类的实例必须绑定到外部类实例而静态方法属于类不依赖实例。如果允许那么调用 Inner.staticMethod() 时不需要任何外部类实例这与非静态内部类“必须依附于外部类实例”的设计矛盾。Java 16 后允许静态常量但仍有严格限制。什么时候用静态内部类当内部类和外部类实例无关时用静态内部类。例如 HashMap.Node 是静态内部类一个节点不需要知道它属于哪个 HashMap 对象。当内部类必须访问外部类实例成员时用非静态内部类例如迭代器它需要知道当前集合对象。非静态内部类可以直接访问外部方法编译器是怎么做到的编译器在生成字节码时会给非静态内部类加了一个“隐藏的”外部类引用比如叫 this$0在生成非静态内部类的构造方法时将外部类实例作为参数传入并在内部类的实例化过程中建立外部类实例与内部类实例之间的联系从而实现直接访问外部方法的功能。步骤一给内部类增加一个隐藏字段。步骤二修改内部类的构造方法。步骤三在构造方法中保存外部引用。关键字Java中final的作用修饰类、方法、变量。修饰类被修饰的类不能被其他类继承。修饰方法被修饰的方法不能被子类重写。修饰变量修饰基本数据类型时表示该变量一旦被赋值就不能再改变修饰引用数据类型时表示该引用不能再指向其他对象但是该引用指向的对象的内容还是可以修改的即限制的只是引用本身指向而非引用指向的对象。Java中static的作用修饰类的成员变量、方法、代码块和内部类。修饰变量被修饰的变量属于类本身在内存中只存在一份类的所有实例共享同一份静态变量。通常用于存储所有对象共享的数据如常量、计数器等。修饰方法被修饰的方法属于类本身在内存中只有一份。通常用于工具类方法如 Math.random()、工厂方法等不需要依赖对象状态即可完成操作。修饰代码块静态代码块在类初始化阶段执行且只执行一次JVM的类生命周期为加载 — 链接验证、准备、解析— 初始化通常用于初始化静态变量或执行类级别的预处理操作。修饰内部类静态内部类不依赖于外部类的实例可以独立存在。在内部类与外部类的实例无关时使用避免内部类持有外部类的引用导致的内存泄漏。