常见java题目

基础题

题目 1:Java中的==equals()方法有什么区别?

问题描述:
解释 ==equals() 方法在比较两个对象时的区别,并举例说明。

答案:

public class EqualsVsEqualsOperator {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");

        // 使用 ==
        System.out.println(s1 == s2); // 输出: false (比较的是引用地址)

        // 使用 equals()
        System.out.println(s1.equals(s2)); // 输出: true (比较的是内容)
    }
}

解析:

  • == 比较的是两个对象的引用地址是否相同。
  • equals() 方法默认比较的是引用地址(除非被重写),但在 String 等类中被重写为比较内容是否相等。

题目 2:Java中的final关键字有哪些用法?

问题描述:
请解释 final 关键字在Java中的三种主要用法,并提供代码示例。

答案:

// 1. final变量:一旦赋值后不可更改
final int x = 10;
// x = 20; // 编译错误

// 2. final方法:不能被子类重写
class Parent {
    final void display() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // @Override
    // void display() { } // 编译错误:无法重写final方法
}

// 3. final类:不能被继承
final class FinalClass {
    void show() {
        System.out.println("This is a final class.");
    }
}

// class SubClass extends FinalClass { } // 编译错误:无法继承final类

解析:

  • final 变量:表示常量,赋值后不可修改。
  • final 方法:防止子类重写该方法。
  • final 类:防止其他类继承该类。

题目 3:Java中的异常处理机制是什么样的?

问题描述:
请解释 try-catch-finally 的作用,并编写一个示例程序来展示如何处理异常。

答案:

public class ExceptionHandling {
    public static void main(String[] args) {
        try {
            int result = 10 / 0; // 抛出 ArithmeticException
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Caught an exception: " + e.getMessage());
        } finally {
            System.out.println("This will always execute.");
        }
    }
}

输出:

Caught an exception: / by zero
This will always execute.

解析:

  • try 块用于包裹可能抛出异常的代码。
  • catch 块用于捕获并处理特定类型的异常。
  • finally 块无论是否发生异常都会执行,通常用于释放资源。

题目 4:Java中的多线程是如何实现的?

问题描述:
请列举两种实现多线程的方式,并分别给出代码示例。

答案:

// 方式1:继承 Thread 类
class MyThread extends Thread {
    public void run() {
        System.out.println("Thread running via extending Thread class.");
    }
}

// 方式2:实现 Runnable 接口
class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Thread running via implementing Runnable interface.");
    }
}

public class MultiThreadingExample {
    public static void main(String[] args) {
        // 使用继承 Thread 类的方式
        MyThread thread1 = new MyThread();
        thread1.start();

        // 使用实现 Runnable 接口的方式
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();
    }
}

解析:

  • 继承 Thread 类:通过重写 run() 方法实现线程逻辑。
  • 实现 Runnable 接口:将 Runnable 对象传递给 Thread 构造器,推荐这种方式,因为 Java 不支持多重继承。

题目 5:什么是Java中的装箱和拆箱?

问题描述:
请解释装箱(Boxing)和拆箱(Unboxing)的概念,并提供代码示例。

答案:

public class BoxingUnboxingExample {
    public static void main(String[] args) {
        // 装箱:将基本数据类型转换为对应的包装类
        Integer boxedInt = 10; // 自动装箱
        System.out.println("Boxed Integer: " + boxedInt);

        // 拆箱:将包装类转换为对应的基本数据类型
        int unboxedInt = boxedInt; // 自动拆箱
        System.out.println("Unboxed int: " + unboxedInt);
    }
}

解析:

  • 装箱:将基本数据类型(如 int)转换为对应的包装类(如 Integer)。
  • 拆箱:将包装类(如 Integer)转换为对应的基本数据类型(如 int)。
    Java 提供了自动装箱和拆箱的功能,简化了开发者的操作。

编程题

题目 1:反转一个单链表

问题描述:
给定一个单链表,编写一个方法来反转它。

示例:
输入: 1 -> 2 -> 3 -> 4 -> 5
输出: 5 -> 4 -> 3 -> 2 -> 1

答案:

class ListNode {
    
    int val;
    ListNode next;
    ListNode(int val) { this.val = val; }
}

public class ReverseLinkedList {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next; // 保存下一个节点
            curr.next = prev;             // 当前节点指向前一个节点
            prev = curr;                  // 前一个节点移动到当前节点
            curr = nextTemp;              // 当前节点移动到下一个节点
        }
        return prev;                     // 返回新的头节点
    }
}

解析:
通过迭代的方式,逐步将每个节点的 next 指针指向前一个节点,最终完成链表的反转。


题目 2:判断一个字符串是否是回文(使用栈)

问题描述:
给定一个字符串,判断它是否是回文(忽略大小写和非字母字符)。

示例:
输入: "A man, a plan, a canal: Panama"
输出: true

答案:

import java.util.Stack;

public class PalindromeChecker {
    public boolean isPalindrome(String s) {
        StringBuilder filtered = new StringBuilder();
        for (char c : s.toCharArray()) {
            if (Character.isLetterOrDigit(c)) {
                filtered.append(Character.toLowerCase(c));
            }
        }

        Stack<Character> stack = new Stack<>();
        String filteredStr = filtered.toString();

        // 将字符串的前半部分压入栈中
        for (int i = 0; i < filteredStr.length() / 2; i++) {
            stack.push(filteredStr.charAt(i));
        }

        // 从中间开始,与栈中的字符进行比较
        int startIdx = (filteredStr.length() + 1) / 2;
        for (int i = startIdx; i < filteredStr.length(); i++) {
            if (stack.pop() != filteredStr.charAt(i)) {
                return false;
            }
        }
        return true;
    }
}

解析:
利用栈的特性(先进后出),先将字符串的前半部分压入栈中,然后逐一弹出并与后半部分进行比较,从而判断是否为回文。


题目 3:实现一个LRU缓存(最近最少使用)

问题描述:
设计并实现一个LRU缓存机制。它应该支持以下操作:获取数据 get(key) 和写入数据 put(key, value)

  • get(key):如果关键字存在,返回其对应的值;否则返回 -1
  • put(key, value):如果关键字已经存在,更新其值;如果关键字不存在且缓存已满,则移除最近最少使用的元素,并插入新元素。

示例:

LRUCache cache = new LRUCache(2); // 缓存容量为2
cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回 1
cache.put(3, 3);    // 移除关键字 2
cache.get(2);       // 返回 -1 (未找到)
cache.put(4, 4);    // 移除关键字 1
cache.get(1);       // 返回 -1 (未找到)
cache.get(3);       // 返回 3
cache.get(4);       // 返回 4

答案:

import java.util.HashMap;
import java.util.Map;

class LRUCache {
    class Node {
        int key, value;
        Node prev, next;
        Node(int key, int value) { this.key = key; this.value = value; }
    }

    private Map<Integer, Node> map = new HashMap<>();
    private int capacity;
    private Node head, tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        head = new Node(0, 0);
        tail = new Node(0, 0);
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            remove(node);
            add(node);
            return node.value;
        }
        return -1;
    }

    public void put(int key, int value) {
        if (map.containsKey(key)) {
            remove(map.get(key));
        }
        if (map.size() == capacity) {
            remove(tail.prev);
        }
        add(new Node(key, value));
    }

    private void add(Node node) {
        Node nextNode = head.next;
        head.next = node;
        node.prev = head;
        node.next = nextNode;
        nextNode.prev = node;
        map.put(node.key, node);
    }

    private void remove(Node node) {
        map.remove(node.key);
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
}

解析:
使用双向链表维护访问顺序,head 表示最近使用的节点,tail 表示最久未使用的节点。结合哈希表快速定位节点位置,保证 getput 操作的时间复杂度为 O(1)。


题目 4:合并两个有序数组

问题描述:
给定两个按升序排列的整数数组 nums1nums2,以及它们的长度 mn,请将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

示例:
输入:
nums1 = [1, 2, 3, 0, 0, 0], m = 3
nums2 = [2, 5, 6], n = 3
输出: [1, 2, 2, 3, 5, 6]

答案:

public class MergeSortedArray {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1, j = n - 1, k = m + n - 1;
        while (i >= 0 && j >= 0) {
            if (nums1[i] > nums2[j]) {
                nums1[k--] = nums1[i--];
            } else {
                nums1[k--] = nums2[j--];
            }
        }
        while (j >= 0) {
            nums1[k--] = nums2[j--];
        }
    }
}

解析:
从两个数组的末尾开始比较,将较大的元素放到 nums1 的末尾,直到所有元素都合并完成。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值