java常见面试题整理(持续更新)

本文深入解析Java的面向对象特性,包括继承、封装、多态,以及final、finally、finalize的区别,探讨了基本数据类型与包装类、ArrayList与LinkedList的区别,分析了String、StringBuilder、StringBuffer的使用场景,揭示了HashMap的实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java 基础

1. 面向对象的特征:


  • 继承
    在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

例:
公共父类:

public class Animal { 
    private String name;  
    private int id; 
    public Animal(String myName, int myid) { 
        name = myName; 
        id = myid;
    } 
    public void eat(){ 
        System.out.println(name+"正在吃"); 
    }
    public void sleep(){
        System.out.println(name+"正在睡");
    }
    public void introduction() { 
        System.out.println("大家好!我是"         + id + "号" + name + "."); 
    } 
}

子类(企鹅继承了动物类的属性和行为):

public class Penguin extends Animal { 
    public Penguin(String myName, int myid) { 
        super(myName, myid); 
    } 
}
  • 封装
      在面向对象程式设计方法中,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。
      封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

例:对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问,

public class Person{
    private String name;
    private int age;
    public int getAge(){
      return age;
    }
    public String getName(){
      return name;
    }
    public void setAge(int age){
      this.age = age;
    }
    public void setName(String name){
      this.name = name;
    }
}
  • 多态
    多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性

多态存在的三个必要条件

  • 继承
  • 重写
  • 父类引用指向子类对象
    例:
public class Test {
    public static void main(String[] args) {
      show(new Cat());  // 以 Cat 对象调用 show 方法
      show(new Dog());  // 以 Dog 对象调用 show 方法
                
      Animal a = new Cat();  // 向上转型  
      a.eat();               // 调用的是 Cat 的 eat
      Cat c = (Cat)a;        // 向下转型  
      c.work();        // 调用的是 Cat 的 work
  }  
            
    public static void show(Animal a)  {
      a.eat();  
        // 类型判断
        if (a instanceof Cat)  {  // 猫做的事情 
            Cat c = (Cat)a;  
            c.work();  
        } else if (a instanceof Dog) { // 狗做的事情 
            Dog c = (Dog)a;  
            c.work();  
        }  
    }  
}
 
abstract class Animal {  
    abstract void eat();  
}  
  
class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void work() {  
        System.out.println("抓老鼠");  
    }  
}  
  
class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void work() {  
        System.out.println("看家");  
    }  
}

执行以上程序,输出结果为:

吃鱼
抓老鼠
吃骨头
看家
吃鱼
抓老鼠

  • 抽象和接口区别
    接口和抽象类是 Java 面向对象设计的两个基础机制。接口是对行为的抽象,它是抽象方法的集合,利用接口可以达到 API 定义和实现分离的目的。接口,不能实例化;不能包含任何非常量成员,任何 field 都是隐含着 public static final 的意义;同时,没有非静态方法实现,也就是说要么是抽象方法,要么是静态方法。Java 标准类库中,定义了非常多的接口,比如 java.util.List。抽象类是不能实例化的类,用 abstract 关键字修饰 class,其目的主要是代码重用。除了不能实例化,形式上和一般的 Java 类并没有太大区别,可以有一个或者多个抽象方法,也可以没有抽象方法。抽象类大多用于抽取相关 Java 类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。Java 标准库中,比如 collection 框架,很多通用部分就被抽取成为抽象类,例如 java.util.AbstractList。Java 类实现 interface 使用 implements 关键词,继承 abstract class 则是使用 extends 关键词,我们可以参考 Java 标准库中的 ArrayList。

2. final, finally, finalize 的区别


  • final 可以用来修饰类、方法、变量,分别有不同的意义。

final 修饰的class表示不可以被继承和扩展,没有子类,final类中的 方法默认都是final的,final修饰的变量是不可被修改的,final修饰的方法是不可以被重写的。

  • finally 是try/catch语句块中保证一定会执行的代码块,一般用来保证重要代码的执行、资源的释放等操作。
  • finalize 是基础类的一个方法,是为了保证对象在垃收集完成前完成特定的资源回收。(现在已经不推荐使用)

3. int 和 Integer 有什么区别,Integer的值缓存范围以及自动拆装箱

int 和 Integer 常见面试题讲解

4. String、StringBuilder、StringBuffer区别

  • String是Java非常基础的类,是字符串常量,是使用final修饰的不可变类,对象一旦生成之后不可变更,也是因为它的不可变特性,像字符串的拼接、裁剪等动作都会产生新的对象,应为一般的应用会经常对String进行这类操作,所以对性能会有明显影响
  • StringBuilder和StringBuffers都是字符串变量,对象生成之后是可变的,其中StringBuilder是线程不安全的,StringBuffers是线程安全的。

5. ArrayList和LinkedList区别

  • ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构
  • 对于随机访问ArrayList优于LinkedList:
    因为 LinkedList底层是双向列表,在读取数据时要移动指针,从链表头节点开始依次向后遍历,而ArrayList动态数组,因为数组在存储数据时是按顺序存储的,存储数据的内存也是连续的,所以在随机读取诗句可以很方便得到对象的内存地址,寻址比较容易。
  • 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList是动态数组,在插入和删除数据时,要移动插入位置以及其后的所有数组元素,而LinedList 只需要变更节点中的引用地址即可

6. “==”与“equals()”的区别

  • 比较简单,不赘述:“==”比较的是对象的内存地址判断对象是否相同,equals()是调用 Object的equals(可重写)方法判断

7. Java中的原始数据类型以及对应的包装类

(1)boolean——1 byte——Boolean
(2)byte——1 byte——Byte
(3)short——2 bytes——Short
(4)int——4 bytes——Integer
(5)long——8 bytes——Long
(6)float——4 bytes——Float
(7)double——8 bytes——Double
(8)char——2 bytes——Character

8. HashMap的实现原理

9. ConcurrentHashMap的实现原理

10. volatile、synchronized、ReentrantLock 原理(AQS相关)

11. ThreadLocal的原理

12. 为什么要有线程池

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值