java基础面试知识点
java基础1. Java面试核心概念Java三大特点平台无关性、面向对象、内存管理。平台无关性通过JVMJava虚拟机实现。源代码编译成字节码.class文件可在任何安装了相应JVM的操作系统上运行。面向对象核心是“对象”。对象是类的一个运行实例且对象实际是堆内存中的一块具体空间内存管理Java具备自动垃圾回收机制GC开发者无需手动释放内存这与C/C不同。2. JDK、JRE、JVM关系三者是包含与被包含的关系从大到小依次为JDK JRE JVMJDK (Java Development Kit)完整的Java开发工具包包含JRE和编译器javac、调试器jdb等。JRE (Java Runtime Environment)Java运行环境包含JVM和Java类库rt.jar。JVM (Java Virtual Machine)核心组件负责执行字节码、内存管理、垃圾回收等。不同平台有不同版本的JVM。3. 值传递与引用传递核心原则Java中只有值传递不存在真正的引用传递。基本数据类型传递的是值的副本适用于基本数据类型。方法内部对参数的修改不影响原始变量。引用数据类型传递的是对象引用的副本地址值而非对象本身。如果修改对象内部的状态会影响原始对象如果修改引用指向则不影响原始对象。4. Java数据类型八种基本数据类型byte, short, int, long, float, double, char, boolean。三种引用数据类型接口, 数组, 类。类型转换自动类型转换由小范围向大范围转换如int - long安全。强制类型转换由大范围向小范围转换如long - int可能导致数据溢出或精度丢失。字符串与基本类型转换在字符串和数值 / 布尔等类型之间互相转换字符串 → 基本类型使用对应包装类的parseXxx()方法基本类型 → 字符串方式 1String.valueOf(基本类型值)方式 2基本类型值 数值与字符 / 包装类之间的转换int→char直接强转基于 ASCII/Unicode 编码char→int直接赋值或强转。数值类型之间的包装类转换通过包装类提供的方法实现例如Integer→LongInteger.intValue()后再装箱Double→FloatDouble.doubleValue()后再装箱。5. BigDecimal与DoubleDouble的局限性在计算机底层以二进制科学计数法存储无法精确表示十进制小数如0.1会导致精度丢失和溢出问题尤其在金融计算中风险极高。BigDecimal的优势BigDecimal是Java提供的高精度数值类型使用字符串作为底层存储能够精确表示任意精度的十进制小数完全避免精度丢失问题。6. 自动装箱与拆箱概念将基本数据类型与对应的包装类如int与Integer之间进行自动转换。自动装箱基本类型 - 包装类。使用Integer.valueof()方法。自动拆箱包装类 - 基本类型。使用intvalue()方法。128陷阱Integer.valueOf()方法会对-128到127范围内的整数进行缓存复用new Integer()创建的对象不会复用缓存中的对象。7.面向对象三大特征封装把属性私有化对外提供公共方法访问。。继承子类可以继承父类的属性和方法实现代码的复用。本质是代码的复用。java只支持单继承防止资源浪费多态父类引用指向子类对象调用重写方法时执行子类的逻辑。主要体现为方法重载、方法重写、接口实现及向上转型向下转型。8.多态多态是面向对象编程的核心特性主要体现在以下四个方面方法重载编译时多态定义同一类中存在多个同名方法参数列表类型、数量、顺序不同。绑定时机编译器在编译阶段根据传入参数确定调用版本。核心作用实现 “同名不同参” 的方法复用提升代码可读性。示例add(int a, int b)与add(double a, double b)会根据参数类型被分别调用。方法重写运行时多态核心实现方式定义子类对父类同名方法提供具体实现方法签名方法名、参数列表必须与父类一致。绑定时机JVM 在运行阶段根据对象的实际类型确定调用哪个子类的方法版本。核心作用实现 “父类引用指向子类对象调用子类实现”是多态最典型的表现形式。示例父类Animal定义sound()子类Dog重写为bark()Cat重写为meow()运行时自动匹配。接口与实现多态的扩展体现定义多个类实现同一个接口用接口类型引用指向不同实现类对象。调用特点调用接口方法时会自动执行对应实现类的具体逻辑调用方式保持一致。核心作用解耦 “规范” 与 “实现”便于扩展和替换不同业务实现。示例Dog、Cat都实现Animal接口用Animal animal new Dog()调用makeSound()时执行Dog的实现。向上转型与向下转型多态的类型转换基础向上转型父类引用指向子类对象自动完成屏蔽子类差异统一调用父类 / 接口方法。例Animal a new Dog();向下转型将父类引用转回子类类型需手动强转用于调用子类特有方法。风险需用instanceof判断类型否则可能抛出ClassCastException。核心作用支撑 “父类 / 接口调用、子类实现” 的多态场景实现类型灵活切换。重载与重写有什么区别重载Overloading指的是在同一个类中可以有多个同名方法它们具有不同的参数列表参数类型、参数个数或参数顺序不同编译器根据调用时的参数类型来决定调用哪个方法。重写Overriding指的是子类可以重新定义父类中的方法方法名、参数列表和返回类型必须与父类中的方法一致通过 Override 注解来明确表示这是对父类方法的重写。重载是指在同一个类中定义多个同名方法而重写是指子类重新定义父类中的方法。9.抽象类与接口抽象类用于描述类的共同性可以包含成员变量、构造方法、具体方法和抽象方法。不能被直接实例化只能被继承。抽象类当中可以定义抽象方法抽象方法子类必须重写。接口用于对行为进行规范定义了常量和抽象方法。一个类可以实现多个接口。接口当中的变量都是常量。区别抽象类描述的是“是什么”接口描述的是“做什么”。抽象类可以有方法实现接口则不能Java 8后接口可有default方法。10.final关键字修饰类该类不能被继承。修饰方法该方法不能被重写。修饰变量对于基本数据类型值不能被改变对于引用类型引用地址不能改变但可以改变引用指向对象的内容。11.抽象类能加final修饰吗不能Java 中的抽象类是用来被继承的而 final 修饰符用于禁止类被继承或方法被重写因此抽象类和 final 修饰符是互斥的不能同时使用。12.静态变量与静态方法静态变量属于类所有实例共享一个副本通过类名或对象均可访问但推荐通过类名访问。静态方法属于类不依赖于实例可通过类名直接调用。加载时机静态变量和静态方法在类加载时初始化只分配一次内存。13.static的作用static核心作用是将类成员与类本身关联而非与类实例对象关联让成员属于类、所有实例共享。修饰变量静态变量归属属于类本身所有对象共享同一份数据内存中仅存一份副本。访问方式通过类名.变量名直接访问无需创建对象。修饰方法静态方法归属属于类不依赖任何实例因此不能直接访问非静态成员非静态成员依赖对象存在但可访问静态成员。访问方式通过类名.方法名直接调用无需创建对象。修饰代码块静态代码块执行时机在类加载时执行且仅执行一次执行顺序优先于构造方法和非静态代码块。修饰内部类静态内部类特性不依赖外部类实例可独立存在不能直接访问外部类非静态成员需通过外部类实例访问。14.深拷贝与浅拷贝浅拷贝复制对象本身及其内部的值字段但对象内部的引用字段仍指向原对象不进行复制。浅拷贝的逻辑是 只拷贝对象表层对「值类型字段」直接复制值新对象和原对象的这个字段互不影响对「引用类型字段」只复制 “内存地址”新对象和原对象的这个字段指向同一个数据改一个会影响另一个。深拷贝复制对象本身及其内部的所有引用对象确保新旧对象相互独立。深拷贝的三种核心实现方法手动递归拷贝通过序列化 / 反序列化实现实现Cloneable接口并重写clone()方法15.序列化与反序列化概念将对象转换为字节流序列化以便在网络或文件间传输再将字节流还原为对象反序列化。实现需让类实现Serializable接口并使用ObjectOutputStream进行序列化ObjectInputStream进行反序列化。局限性存在安全漏洞、不支持跨语言、序列化后的数据体积较大等问题。16. 泛型作用允许类、接口和方法在定义时使用参数化类型提高代码的通用性和安全性在编译期进行类型检查避免了运行时的强制类型转换ClassCastException。类型擦除Java 的泛型是“伪泛型”在编译成字节码期间所有的泛型信息都会被擦除掉变成 Object 或者其限定的边界类型。16.1 对象的创建与垃圾回收GC机制创建对象的方式主要包括new关键字、反射、克隆Cloneable接口和反序列化。对象回收的原则无论通过哪种方式创建在堆内存中的对象当它不再被任何“有效引用”指向时就会成为 GC 的回收目标。如何判断对象已死核心考点引用计数法已淘汰给对象维护一个计数器。致命缺点无法解决两个对象互相引用循环引用的问题导致这俩对象永远无法被回收内存泄漏。可达性分析算法正在使用以GC Roots为起点顺着引用链往下找。如果一个对象到所有 GC Roots 都没有任何路径相连即不可达说明它死了可以被回收。哪些对象可以作为 GC Roots八股文必背虚拟机栈方法中的局部变量中引用的对象。方法区中类静态变量static引用的对象。方法区中常量final引用的对象。本地方法栈Native 方法中引用的对象。finalize() 机制的坑如果对象重写了finalize()GC 回收前理论上会调用它。注意避坑绝对不要依赖它去清理资源如关闭文件、数据库连接由于它优先级极低、执行时机完全不确定甚至有可能导致对象“复活”还会严重拖慢 GC 的性能。在 JDK 9 以后已被彻底标记为不再推荐使用Deprecated。17. 反射机制反射的本质在运行时动态获取类信息如字段、方法、构造器并操作对象的能力。获取类对象的方式主要有三种分别对应类加载的三个阶段通过Class.forName(全类名)、通过类名.class、通过对象.getClass()。反射的特点运行时数据访问、动态数据创建、动态方法获取。方法类型访问权限范围是否包含继承成员getDeclaredXXX()所有访问权限private/protected/default/public不包含getXXX()仅公有public包含暴力反射通过设置Field对象的setAccessible(true)来访问和修改private修饰的字段称为暴力反射。反射的应用在JDBC连接池Class.forName加载驱动、Spring框架通过配置文件动态创建Bean对象中有广泛应用。18.代理1. 代理模式定义:不直接访问目标对象而是通过一个 “代理对象” 作为中间层既可以控制对目标对象的访问比如权限校验又能在访问前后增加额外功能比如日志、计时。。2. 静态代理实现方式: 代理类与目标类实现相同的接口代理类中需要为每一个目标类编写一个独立的代理类。优点: 逻辑清晰易于理解和实现。缺点: 违反了开闭原则。当目标类增多或接口功能增多时需要频繁地编写和修改代理类导致代码冗余且维护困难。3. 动态代理实现方式: 代理类不直接实现接口而是实现一个公共的接口如java.lang.reflect.InvocationHandler由JDK在运行时动态生成代理对象。JDK 动态代理Java 原生CGLIB 动态代理第三方库核心思想: 代理对象的创建依赖于外部传入的目标对象使得代理类可以灵活地代理任意一个实现了特定接口的对象。实现步骤:代理类通过构造函数接收目标对象。通过反射技术获取目标对象所实现的接口从而得知其核心方法。重写接口中的invoke()方法在调用目标对象方法前后插入业务增强逻辑如权限验证。最终通过invoke方法调用目标对象的核心方法。19.Java注解原理注解的本质是继承了interface接口的特殊接口其具体实现类由JVM在运行时动态生成。通过反射机制可以获取注解返回的是一个动态代理对象。注解分为三种类型源码级别编译后不保留、类文件级别运行时不可见和运行时级别可通过反射解析。元注解TargetRetentionDocumentedInherited自定义注解若要通过反射获取其生命周期必须声明为Retention(RetentionPolicy.RUNTIME)。21.IO模型BIO (Blocking IO): 主线程负责监听和处理请求采用同步阻塞模式。效率较低但实现简单。NIO (Non-blocking IO): 使用Selector选择器管理多个Channel通道将任务分发给多个子线程处理是同步非阻塞模式效率更高。Netty: 基于NIO的高性能网络框架常用于处理WebSocket等实时通信场景。22. Object类有哪些方法clone()保护方法实现对象的浅拷贝。只有实现了Cloneable接口才可以调用该方法否则抛出CloneNotSupportedException异常。getClass()final方法获得运行时类型。toString()返回对象的字符串表示一般子类都会被重写。finalize()用于释放资源。因为无法确定该方法什么时候被调用目前已不推荐使用。equals()用于比较对象的值是否相等。默认比较内存地址一般需配合业务逻辑重写。hashCode()用于哈希查找重写了equals方法一般都要重写hashCode方法。此方法在一些具有哈希功能的集合如HashMap、HashSet中用到。wait()使当前线程等待该对象的锁当前线程必须是该对象的拥有者。notify()/notifyAll()唤醒在该对象上等待的某个或所有线程。23. 与 equals 有什么区别** 运算符对于基本数据类型比较的是它们的值。对于引用数据类型比较的是它们在内存中的地址即是否为同一个对象。equals() 方法equals是Object类提供的方法默认实现与相同即也是比较对象的内存地址。许多类如String、Integer等都重写了equals()方法将其改为比较对象**内部的内容值**是否相等而非仅比较内存地址。24. hashcode和equals方法有什么关系答案 先执行hashcode 一样的话再执行equals在使用哈希表结构的集合比如HashMap、HashSet时它们的工作原理是先通过hashCode()计算对象存放在哈希表中的位置如果位置一样哈希冲突再通过equals()判断对象内容是否真的相等。如果你只重写了equals()而不重写hashCode()那么两个逻辑上“相等”的对象它们的hashCode()默认是根据内存地址计算的却不一样。导致的后果在把对象存入HashMap或HashSet时会被存放到两个完全不同的格子里导致集合里存放了重复的逻辑对象破坏了集合去重和键唯一性的原则。25. Java里String的常用方法有哪些获取与查找length()返回字符串长度。charAt(int index)返回指定索引处的字符。indexOf(String str)返回子串第一次出现的索引位置。如未找到返回 -1。substring(int beginIndex, int endIndex)截取字符串左闭右开区间。判断与比较equals(Object anObject)比较字符串内容是否相等。equalsIgnoreCase(String anotherString)忽略大小写比较字符串内容。startsWith(String prefix)/endsWith(String suffix)判断是否以指定前缀/后缀开头或结尾。isEmpty()判断字符串是否为空长度为0。转换与截取replace(CharSequence target, CharSequence replacement)替换字符串中的指定字符或序列。trim()去除字符串首尾的空白字符。split(String regex)根据正则表达式拆分字符串返回字符串数组。toLowerCase()/toUpperCase()转换为小写/大写形式。toCharArray()将字符串转换为字符数组。26. 为什么说字符串不可变27. String、StringBuffer、StringBuilder的区别和联系String特性不可变的字符序列底层是由final修饰的char[]或byte[]数组。效率每次修改操作都会生成一个新的String对象效率最低浪费内存。线程安全由于不可变天然是线程安全的。StringBuffer特性可变的字符序列相对String修改时不会创建新对象。效率相比String效率较高但在单线程环境下不如StringBuilder。线程安全所有修改数据的方法如append都加了synchronized同步锁是线程安全的。StringBuilder特性可变的字符序列与StringBuffer的 API 完全一致。效率没有使用同步锁执行效率最高。线程安全非线程安全。总结与联系三者都实现了CharSequence接口用于处理字符串。使用场景如果字符串内容很少变化优先使用String如果在单线程中频繁拼接修改字符串使用StringBuilder如果在多线程中频繁拼接修改字符串使用StringBuffer。28. 异常体系Error 与 Exception 的区别顶级父类Java 所有异常和错误的超类是Throwable。它有两个重要子类Error和Exception。Error错误指 JVM 系统级别的重大问题程序无法通过代码处理恢复。比如内存溢出OutOfMemoryError、栈溢出StackOverflowError。通俗解释病入膏肓只能罢工拔电源。Exception异常指程序运行中出现的可预见、可处理的问题程序可以通过catch捕获并恢复。通俗解释小感冒吃点药catch还能接着干活。29. 受查异常Checked与非受查异常Unchecked的区别非受查异常RuntimeException 及其子类编译器不要求强制处理。通常是由代码逻辑错误引起的。常见的有NullPointerException空指针、IndexOutOfBoundsException数组越界、ClassCastException类型转换异常。通俗解释代码没写好导致的低级错误运行时才会炸。受查异常非 RuntimeException 的其他 Exception编译器强制要求必须处理要么try-catch捕获要么throws抛出否则编译报错无法运行。常见的有IOExceptionIO异常、SQLException数据库异常、ClassNotFoundException。通俗解释老天爷外部环境带来的风险比如文件不存在写代码时必须提前买好保险。30. throw 和 throws 的区别是什么位置不同throw用在方法内部throws用在方法声明处方法签名的末尾。作用不同throw是主动抛出一个具体的异常对象真正制造异常的动作throws是高呼“我这个方法可能会出这个异常”把它甩锅给调用者处理。数量不同throw一次只能抛出一个异常对象throws后面可以跟多个异常类名用逗号隔开。31. try-catch-finally 执行顺序陷阱带有 return 时核心规则finally块中的代码一定会执行除非在前面执行了System.exit(0)强行退出 JVM。带有 return 的执行顺序执行try或catch中的逻辑。遇到return时会先把返回值暂存起来。执行finally块中的代码。最后把刚才暂存的返回值返回给调用者。神仙打架覆盖陷阱如果finally块里面也有return语句那么它会覆盖掉try或catch中的return值。实际开发中极度反感在 finally 里写 return32. String s new String(“abc”) 到底创建了几个对象这是考察对**字符串常量池String Pool**的理解情况 A创建了 1 个对象。如果字符串常量池中已经存在abc这个字面量那么只会在堆内存Heap中创建一个String对象并且这个堆对象指向常量池中的abc。情况 B创建了 2 个对象常考点。如果字符串常量池中还没有abc那么首先在字符串常量池中创建一个abc对象。然后在堆内存中再创建一个String对象其实是对常量池对象的拷贝/包装并把堆中这个对象的地址返回给变量s。通俗解释new关键字就像是个强迫症只要有它堆里必定会建个新房子对象。但里面的家具字符串内容要不要去厂家常量池现做就看之前有没有人做过同样的款式了。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2416066.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!