Java 面试十大烂问题

  1. 什么是面向对象

    面向对象编程(OOP)主要是基于四个原则:封装、集成、多态、抽象。

    这四个原则共同构成了面向对象编程的基础。在代码的提现上则会使得代码模块化、可重用以及更加容易维护。

    封装使得代码内部的细节实现得以屏蔽,隐藏了代码内部的复杂性,继承则可以使得代码重复使用以及职责单一化,多态则允许对象之间互相转换,抽象侧重于将复杂的业务模型化、简单化

  2. Java 中最快的搜索算法

    Java 中比较常见且最常使用的算法是二分搜索和 hash 搜索。二分搜索主要适用于已经有序的数组或者列表。时间复杂度是O(log n)。

    Java代码实现二分查找
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package com.toca.bjca;

    public class BinarySearchExample {
    public static int binarySearch(int[] array, int target) {
    int left = 0;
    int right = array.length - 1;

    while (left <= right) {
    int mid = left + (right - left) / 2;

    if (array[mid] == target) {
    return mid;
    } else if (array[mid] < target) {
    left = mid + 1;
    } else {
    right = mid - 1;
    }
    }

    return -1; // Target element not found
    }

    public static void main(String[] args) {
    int[] array = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
    int target = 23;

    int index = binarySearch(array, target);

    if (index != -1) {
    System.out.println("Element found at index: " + index);
    } else {
    System.out.println("Element not found");
    }
    }
    }

    hash 搜索则是基于 hash 值的定位进行查找数据。主要是使用 HashMap 或者 HashSet这种数据结构,时间复杂度是 O((1))。

    java 代码实现 Hash 搜索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("John", 25);
map.put("Jane", 30);
map.put("Alice", 42);
map.put("Bob", 35);

String key = "Jane";

if (map.containsKey(key)) {
int value = map.get(key);
System.out.println("Value for key " + key + ": " + value);
} else {
System.out.println("Key not found");
}
}

3 JDK 和 JRE 是什么

JDK 代表的是 Java 开发工具包,JRE 是 Java 的运行时环境。JDK 是一个软件包,包括 Java 开发所需的一些工具例如:编译器、调试器、Java API,JDK 中还包括 JRE。

JRE 则是Java运行时环境。但是不包含开发工具

4 谈谈多线程

多线程是指在单个应用程序中同时间可以运行一个以上的线程任务。线程是轻量级的执行单元,它允许任务同时执行,从而提高应用程序的执行性能和响应能力。多线程执行任务还可以更大限度的利用多核 CPU 实现并行的任务处理,例如 I/O 操等

Java 中的多线程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String[] args) {
// Create two threads
Thread thread1 = new Thread(new MyRunnable("Thread 1"));
Thread thread2 = new Thread(new MyRunnable("Thread 2"));
// Start the threads
thread1.start();
thread2.start();
}
static class MyRunnable implements Runnable {
private String threadName;

public MyRunnable(String threadName) {
this.threadName = threadName;
}
//process bus
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + ": " + i);
try {
Thread.sleep(1000); // Pause for 1 second
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

5 java中创建对象的方法

在 Java 中创建对象的方法有四种:使用 new 关键字、调用 clone()、使用反射创建对象、使用反序列化创建对象。

Java 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
// Using the new keyword
MyObject obj = new MyObject();

// Cloning an object
MyObject obj2 = obj.clone();

// Creating an object using reflection
Class<MyObject> clazz = MyObject.class;
MyObject obj3 = clazz.newInstance();

// Creating an object through deserialization
ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"));
MyObject obj4 = (MyObject) in.readObject();

6比较 Java 中的接口和抽象类。为什么更喜欢接口而不是抽象类?

接口和抽象类都允许定义类的共同行为。然而,接口提供了纯粹的抽象,允许类实现多个接口,而一个类只能扩展一个抽象类。接口定义契约,从而实现组件之间的松散耦合。抽象类提供部分实现,并且可以具有实例变量、构造函数和非抽象方法。当类需要支持多种行为或创建公共 API 时,接口是首选。

7 解释一下Java中Comparator和Comparable接口的区别

Java中Comparator和Comparable都是用于对象比较的。 Comparable 接口由类实现,以定义其对象的自然顺序。它提供了一个 compareTo() 方法来比较对象。 Comparator 接口允许对可能没有自然排序的对象进行自定义比较逻辑。它提供了一个 compare() 方法来执行比较。虽然 Comparable 强加了自然排序,但 Comparator 允许灵活地定义不同的比较策略。

Java 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Person implements Comparable<Person> {
private String name;

public int compareTo(Person other) {
return this.name.compareTo(other.name);
}
}

// Comparator interface
public class AgeComparator implements Comparator<Person> {
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}

8HashMap 与 HashTable

HashMap和HashTable都是用来存储键值对的。然而,HashTable 是一个同步类,使其线程安全,但可能速度较慢。 HashMap 不是同步的,提供了更好的性能,但本质上不是线程安全的。 HashMap 允许空键和值,而 HashTable 不允许空值。在大多数情况下,除非明确要求线程安全,否则 HashMap 是首选

9 Java 中 LinkedList 和 List 接口的区别

List 接口是 Java Collections Framework 中的一个基本接口,表示有序集合。 LinkedList 是 List 接口的实现,它将元素存储在双向链表中。 LinkedList提供了高效的两端元素插入和删除,但随机访问速度较慢。 ArrayList 是另一种 List 实现,它将元素存储在动态调整大小的数组中,与 LinkedList 相比,提供更快的随机访问,但插入和删除速度更慢

10 解释一下Java中引用值和变量值的区别。

在 Java 引用值是指向对象内存地址的。它允许访问和操作对象的属性和方法。变量值则是变量所保存的实际值。对于原始数据类型(例如 int boolean)变量值是直接分配给变量的值。对于引用类型(例如 new User())变量值就是引用值指向内存地址。

Java 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.toca.bjca;

public class ReferenceValueVsVariableValueExample {
public static void main(String[] args) {
int variableValue = 10;
int anotherVariableValue = variableValue;

System.out.println("Variable Value: " + variableValue);
System.out.println("Another Variable Value: " + anotherVariableValue);

anotherVariableValue = 20;

System.out.println("Variable Value: " + variableValue);
System.out.println("Another Variable Value: " + anotherVariableValue);

Person person1 = new Person("John");
Person person2 = person1;

System.out.println("Person 1: " + person1.getName());
System.out.println("Person 2: " + person2.getName());

person2.setName("Jane");

System.out.println("Person 1: " + person1.getName());
System.out.println("Person 2: " + person2.getName());
}

static class Person {
private String name;

public Person(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
}

上述代码表明:变量的值是相互独立的,引用值指向内存地址中的一个对象。修改引用值则会影响到此对象的所有引用,因为内存地址发生了变化。