Advertisement

JAVA基础面试题汇总 ~~持续更新中

阅读量:

面向对象编程

面向过程:注重事情在每一个步骤及顺序
面向对象:注重事情有哪些参与者,以及个参与者需要做什么

  1. 封装(Encapsulation):封装是将数据和方法绑定在一起的机制,对象的内部状态对外部是隐藏的,只有通过对象的公共接口才能访问和操作内部状态,这样可以确保数据的安全性和一致性。
  2. 继承(Inheritance):继承是指一个对象(子类)可以从另一个对象(父类)继承属性和行为的能力。通过继承,子类可以重用父类的代码,同时可以在不修改父类的情况下增加新的功能或修改现有功能。
  3. 多态(Polymorphism):多态性允许不同类的对象对同一消息作出不同的响应。通过多态,可以编写出更加灵活和通用的代码,使得代码具有更好的扩展性和可维护性

三大特征

  • 封装
    明确标识出允许外部使用的所有成员函数数据项
    内部细节对外部调用透明,外部调用无需修改或者关心内部实现

封装好的类,无需关心内部如何处理,需要时直接调用即可

  • 继承
    继承基类的方法,并做出自己的改变或扩展
    子类共性的方法或者属性直接使用父类的,而不需要自己再定义,只需扩展自己个性化的

子类重用父类代码,在不修改父类功能情况下对其补充

  • 多态
    基于对象所属类的不同,外部对同一个方法的调用,实际执行的逻辑不同。
    继承,方法重写,父类引用指向子类对象

代码灵活,更好的扩展和维护

接口和抽象类的区别

  1. 接口是对“行为”的抽象,而抽象类是对“类”的抽象。
  2. 接口只能定义 抽象方法和常量,而抽象类可以定义抽象方法、普通方法、成员变量等。Java8中接口类中可用有default修饰的方法实现。
  3. 一个类只能继承一个抽象类,但可以实现多个接口。抽象类可以有构造器,而接口不能有构造器。

值传递和引用传递

在 Java 语言中,本质只有值传递,而无引用传递,方法传参时只会传递变量副本而非原内容。
java中分为值类型(基本数据类型)和引用类型(类、接口、数组、字符串、包装类)

  • 值类型:在赋值时,直接在栈中(Java 虚拟机栈)生成值的类型
  • 引用类型:在初始化时将引用生成栈上,而值生成在堆上的这些数据类型
    什么是值传递,什么是引用传递
    指的是方法传参时,传递的是原内容的副本,因此对副本进行如何修改都不会影响原内容。
    引用传递指的是方法传参时,传递的是参数本身,因此对参数进行任意修改都会影响原内容。
    为什么在JAVA中只有值传递?
复制代码
    public class PassByValue {
    public static void main(String[] args) {
        char[] name = {'你', '好'};
        System.out.println("调用方法前:" + new String(name));
        change(name);
        System.out.println("调用方法后:" + new String(name));
    }
    private static void change(char[] n) {
        n = new char[2]; // 修改引用传递
        n[0] = '您';
        n[1] = '好';
        System.out.println("方法中修改为:" + new String(n));
    }
    }
    
    
    java
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/inw04gIposN83HP7yqVedLASJUxR.png)

代码最后输出的还是“你好”
在调用 new char[] 之后,可以看出 n 对象有了新地址,而原内容并未被修改,如果按照引用传递的思路来看的话,不管执行任何方式的修改都会改变原内容,但没有改变,因此我们可以更加确认 Java 语言中只有值传递。
在change方法中传递的引用类型,实际不是真正的引用,而是栈中地址
所以在 Java 语言中本质上只有值传递,也就说 Java 的传参只会传递它的副本,并不会传递参数本身。

Integer的整数缓存

当在范围[-128, 127]内创建Integer对象时,JVM会检查是否已经存在相同值的Integer对象。
Integer a = new Integer(66);
Integer b = new Integer(66);
System.out.println(a == b);
a和b均为新new出来的对象,并且==比较的是地址,两个new出来的对象永远不可能相等,因此输出false
Integer a = 66;
Integer b = 66;
System.out.println(a == b);
答案是true,直接将两个int类型赋值给Integer,Java会先进行自动装箱,也就是调用 valueOf方法。走缓存,不会新建对象
Integer a = new Integer(66);
int b = 66;
System.out.println(a == b);
答案是true,基本类型和Integer类型比较,Java会先自动进行拆箱操作,将包装类型转化为基本类型,然后再进行比较,所以比较的是两个int值是否相同
Integer a = 128;
Integer b = 128;
System.out.println(a == b);
答案是false,Java会进行装箱操作,但由于值不在[-127, 128]范围内,因此valueOf方法会返回一个new Integer(i);常量池对应的值的对象不是同一对象
因此,对于范围内的整数值,应该使用equals()方法来比较它们的值是否相等,而不是==运算符。

==和equals

==对比的是栈内存中的值,比较基本数据类型是比较变量值,引用类型在堆中存储的是内存对象的地址
equals:object中默认也是采用==比较,通常会重写

复制代码
    public class StringTest {
       public static void main(String args[]) {
     String str1 = "Hello";
     String str2 = new String("Hello");
     String str3 = str2; // 引用传递
     System.out.println(str1 == str2); // false
     System.out.println(str1 == str3); // false
     System.out.println(str2 == str3); // true
     System.out.println(str1.equals(str2)); // true
     System.out.println(str1.equals(str3)); // true
     System.out.println(str2.equals(str3)); // true
      }
    }
    
    
    java
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-07-13/O654oTxdtGlfL7BwsHUiVvaFrAMI.png)

equales和hashcode

有几句话,重写equals必须重写hashcode
因为如果两个对象相等,则hashcode也必须相等,但hashcode相同,两个对象不一定相等
hascode作用:
以“HashSet如何检查重复”为例
对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,看该位置是否有
值,如果没有、HashSet会假设对象没有重复出现。但是如果发现有值,这时会调用equals()方法来检查两个对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会
重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。

重载和重写

重载: 在同一个类中,方法名必须相同参数类型不同、个数不同、顺序不同,方法返回值和访问
修饰符可以不同,发生在编译时。
重写: 在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于
等于父类,访问修饰符范围大于等于父类;
如果父类方法访问修饰符为private则子类就不能重写该方法。

Checked Exception,Runtime Exception的区别

  1. Checked Exception 的基类是Exception ; Runtime Exception 的基类是RuntimeException (不过 RuntimeException 的父类也是 Exception).
  2. Checked Exception 要求必须捕获. 一个方法内如果抛出了 Checked Exception, 必须要么 catch, 要么给方法声明 throws 以交给上一层去处理, 如果漏写了 catch 会直接通不过编译. (IOException、SQLException、ParseException,NullPointerException)Runtime Exception 就没这个要求, 不强制 catch 或 throws, 这样对于明显不会异常的代码段就不必处理了.
常见的受检异常

IO异常、文件未找到异常

常见的时异常

● NullPointerException:当试图访问一个空对象的成员时抛出。
● ArrayIndexOutOfBoundsException:当数组访问索引超出范围时抛出。
● IllegalArgumentException:当方法接收到不合法的参数时抛出。
● IllegalStateException:当对象的状态不符合方法的调用要求时抛出。
● ClassCastException:当试图将对象强制转换为不兼容的类时抛出。
● ArithmeticException:当出现算术错误时抛出,例如除数为零。

什么是反射

指在程序时 动态地获取类的信息调用对象的方法操作对象的属性 的能力。
通过反射,程序可以在编译时未知类的情况下操作这些类,实现更灵活和动态的代码结构

  1. 通过new对象实现反射机制 new Student().getClass()
  2. 通过路径实现反射机制 Class.forName(“”)
  3. 通过类名实现反射机制 Student.class

new String() 和 String s = “”;

当执行’string s1=“hello”; 和 ‘string s2:=new string(“world”); 这两条语句时,会发生以下过程:
● String s1=“hello”;
○ JVM 首先会在常量池中查找是否已经存在值为"hello"的字符串对象。
○ 如果常量池中已经存在 "hello"字符串对象,则直接将引用赋给’s1’,不会创建新的字符串对象。
○ 如果常量池中不存在 "hello"字符串对象,则会在常量池中创建一个新的字符串对象,并将引用赋给’s1’。
● String s2= new String(“world”);
○ 使用’new’关键字创建一个新的字符串对象,其中的"world"字符串会被放入堆内存中。
○ 即使常量池中已经存在"world"字符串对象,使用’new string()`构造方法创建的字符串对象也会在堆内存中单独创建一个新的对象,而不是直接引用常量池中的字符串对象。
○ 将新创建的字符串对象的引用赋给 s2;
● 综上所述,'string s1=“hello”;会直接使用常量池中的字符串对象,而’string s2 = newstring(“world”);会在堆内存中创建一个新的字符串对象。

集合

集合和数组

集合类的特点:提供一种存储空间可变的存储模型,存储的数据 容量可以发生改变
集合和数组的区别:
● 共同点:都是存储数据的容器
● 不同点:数组的容量是固定的,集合的容量是可变的

ArrayList和数组[]的区别

● 数组:数组中只能存储 同一数据类型的数据,而且数组的长度一旦定义就不能改了,这就是为什么开发中直接用数组的情况很少。
● ArrayList:它是 可以存储任意数据类型的数据 的,而且 长度会随着元素的增加而增加,随着元素的减少而变短。
它的底层是一个动态数组,可以根据需要自动扩展数组的大小。

  1. 数组可以存储基本类型数据和引用类型数据(基本类型/引用类型),而list只能存储引用类型变量;
  2. 数组只能存储类型一样的数据,而list不做要求;
  3. list按放入的顺序来给数据排序,而数据按照下标排序;

ArrayList和LinkedList的区别

相同点:ArrayList和LinkedList都实现了List接口
不同点:
● ArrayList是 基于动态数组实现的,它可以自动扩容以容纳更多的元素。它可以以0(1)时间复杂度对元素进行随机访问。
○ 由于ArrayList内部是通过数组实现的,因此可以随机访问集合中的元素,这使得ArrayList在随机访问时具有很好的性能。
○ 但是,在插入和删除元素时,由于需要移动其他元素来填补空缺,因此性能较差。
● LinkedList是 基于双向链表实现的,它的每个元素都包含了对前一个和后一个元素的引用。查找某个元素的时间复杂度是O(n)。
○ 由于LinkedList内部是通过链表实现的,因此在插入和删除元素时,只需要修改相邻元素的引用即可,因此性能比ArrayList更好。
○ 但是,在随机访问时,由于需要从头开始遍历链表,因此性能较差。
● 如果需要 频繁进行随机访问 操作,应该使用ArrayList;
● 如果需要 频繁进行插入和删除 操作,应该使用LinkedList。
● LinkedList 比 ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

什么场景下更适宜使用 LinkedList,而不用ArrayList

● 应用不会随机访问数据。因为如果需要LinkedList中的第n个元素的时候,需要从第一个元素顺序数到第n个数据,然后读取数据。
● 应用更多的插入和删除元素,更少的读取数据。因为插入和删除元素不涉及重排数据,所以它要比ArrayList要快。

全部评论 (0)

还没有任何评论哟~