手记

Java面试题精讲:从零开始掌握面试必备技能

本文详细讲解了Java基础知识、设计模式、集合框架、并发编程以及JVM与性能优化等方面的面试题,旨在帮助读者全面掌握相关技术要点。通过本文的学习,读者可以更好地准备面试,提升自己的技术水平。面试题精讲涵盖了从基本概念到实战技巧的各个方面,确保读者能够应对各种面试挑战。

Java基础知识面试题精讲

基本概念与语法

1. 变量与类型

  • 基本类型:Java 中有八种基本类型,分为四种数值类型 (byte, short, int, long)、两种浮点类型 (float, double)、布尔类型 (boolean) 和字符类型 (char)。
byte b = 127;
short s = 32767;
int i = 2147483647;
long l = 9223372036854775807L;
float f = 3.14f;
double d = 3.14159;
boolean bool = true;
char c = 'A';
  • 引用类型:引用类型指的是类 (class)、接口 (interface)、数组等。引用类型存储的是对象的引用。
String str = "Hello";
List<String> list = new ArrayList<>();
String[] arr = {"a", "b", "c"};

2. 控制结构

  • 条件语句if...else 用于做简单的条件分支判断。
int age = 18;
if (age >= 18) {
    System.out.println("成年人");
} else {
    System.out.println("未成年人");
}
  • 循环语句for 循环用于遍历数组或集合,while 循环用于条件未知时的循环。
for (int i = 0; i < 5; i++) {
    System.out.println(i);
}

int j = 0;
while (j < 5) {
    System.out.println(j);
    j++;
}

3. 方法与类

  • 方法:方法用于封装一段可重用的代码,通过方法名、参数列表和返回类型来定义。
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

Calculator calc = new Calculator();
int result = calc.add(3, 4);
  • :类是对象的模板,用于定义对象的属性和行为。
public class Person {
    String name;
    int age;

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

    public void introduce() {
        System.out.println("我是" + name + ",今年" + age + "岁");
    }
}

Person p = new Person("张三", 25);
p.introduce();

Java面向对象特性

1. 类与对象

  • :定义对象的结构和行为。
  • 对象:类的一个实例。
public class Car {
    String brand;
    int year;

    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }

    public void start() {
        System.out.println("启动了" + brand + "品牌的汽车");
    }

    public void stop() {
        System.out.println("停止了" + brand + "品牌的汽车");
    }
}

Car myCar = new Car("丰田", 2022);
myCar.start();
myCar.stop();

项目案例: 在一个简单的电子商务系统中,我们可以定义 UserProduct 类来表示用户和商品。

public class User {
    String username;
    String password;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public void login() {
        System.out.println("用户 " + username + " 登录");
    }
}

public class Product {
    String name;
    double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public void display() {
        System.out.println("商品名称:" + name + ",价格:" + price);
    }
}

User user = new User("张三", "123456");
user.login();

Product p = new Product("iPhone", 5800);
p.display();

2. 继承与多态

  • 继承:子类继承自父类,可以继承父类的属性和方法。
  • 多态:子类可以覆盖父类的方法,实现不同的行为。
public class Animal {
    public void sound() {
        System.out.println("动物发出声音");
    }
}

public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("汪汪");
    }
}

Animal myAnimal = new Dog();
myAnimal.sound();  // 输出:汪汪

常见数据类型与异常处理

1. 常见数据类型

  • 数值类型:用于存储数值。
  • 字符串类型String 类用于存储文本。
  • 日期时间java.util.Datejava.time 包下的类用于日期时间操作。
public class DataTypeExample {
    public static void main(String[] args) {
        int num = 100;
        String text = "Hello";
        Date date = new Date();

        System.out.println("整数:" + num);
        System.out.println("字符串:" + text);
        System.out.println("日期:" + date);
    }
}

项目案例: 在一个数据处理工具中,可以使用这些数据类型来处理用户输入的数据。

public class DataProcessor {
    public static void processData() {
        int id = 12345;
        String name = "张三";
        Date dob = new Date();

        System.out.println("ID:" + id + ",姓名:" + name + ",出生日期:" + dob);
    }
}

DataProcessor.processData();

2. 异常处理

  • 异常处理机制:Java 使用 try...catch...finally 语句来处理异常。
public class ExceptionHandlingExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.out.println("除数不能为0");
        } finally {
            System.out.println("清理资源");
        }
    }
}
Java常用设计模式面试题精讲

单例模式

  • 单例模式:确保一个类只有一个实例,并提供一个全局访问点。
public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Singleton singleton = Singleton.getInstance();

项目案例: 在一个日志记录工具中,可以使用单例模式设计日志记录器。

public class Logger {
    private static Logger instance;

    private Logger() {}

    public static Logger getInstance() {
        if (instance == null) {
            instance = new Logger();
        }
        return instance;
    }

    public void log(String message) {
        System.out.println("日志记录:" + message);
    }
}

Logger logger = Logger.getInstance();
logger.log("这是一个日志记录");

工厂模式

  • 工厂模式:提供一个创建对象的接口,但由子类决定实例化哪一个类。
public interface Shape {
    void draw();
}

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("画圆");
    }
}

public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("画正方形");
    }
}

public class ShapeFactory {
    public Shape getShape(String shapeType) {
        if ("circle".equals(shapeType)) {
            return new Circle();
        } else if ("square".equals(shapeType)) {
            return new Square();
        }
        return null;
    }
}

ShapeFactory factory = new ShapeFactory();
Shape shape = factory.getShape("circle");
shape.draw();  // 输出:画圆

项目案例: 在一个图形界面框架中,可以使用工厂模式创建按钮和文本框。

public interface Button {
    void render();
}

public class WindowsButton implements Button {
    @Override
    public void render() {
        System.out.println("渲染Windows样式按钮");
    }
}

public class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("渲染Mac样式按钮");
    }
}

public class ButtonFactory {
    public Button createButton(String buttonType) {
        if ("windows".equals(buttonType)) {
            return new WindowsButton();
        } else if ("mac".equals(buttonType)) {
            return new MacButton();
        }
        return null;
    }
}

ButtonFactory factory = new ButtonFactory();
Button button = factory.createButton("windows");
button.render();  // 输出:渲染Windows样式按钮

观察者模式

  • 观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。
import java.util.ArrayList;
import java.util.List;

public interface Observer {
    void update(String message);
}

public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(String message);
}

public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

public class ConcreteObserver implements Observer {
    @Override
    public void update(String message) {
        System.out.println("观察者收到消息:" + message);
    }
}

public class ObserverPatternExample {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        ConcreteObserver observer1 = new ConcreteObserver();
        ConcreteObserver observer2 = new ConcreteObserver();

        subject.registerObserver(observer1);
        subject.registerObserver(observer2);

        subject.notifyObservers("消息1");
        subject.notifyObservers("消息2");
    }
}

项目案例: 在一个新闻订阅系统中,可以使用观察者模式实现用户订阅功能。

public interface NewsSubscriber {
    void notify(String message);
}

public class ConcreteNewsSubscriber implements NewsSubscriber {
    @Override
    public void notify(String message) {
        System.out.println("订阅者收到消息:" + message);
    }
}

public class NewsAgency {
    private List<NewsSubscriber> subscribers = new ArrayList<>();

    public void registerSubscriber(NewsSubscriber subscriber) {
        subscribers.add(subscriber);
    }

    public void removeSubscriber(NewsSubscriber subscriber) {
        subscribers.remove(subscriber);
    }

    public void publish(String message) {
        for (NewsSubscriber subscriber : subscribers) {
            subscriber.notify(message);
        }
    }
}

NewsAgency agency = new NewsAgency();
NewsSubscriber subscriber1 = new ConcreteNewsSubscriber();
NewsSubscriber subscriber2 = new ConcreteNewsSubscriber();

agency.registerSubscriber(subscriber1);
agency.registerSubscriber(subscriber2);

agency.publish("新闻1");
agency.publish("新闻2");
Java集合框架面试题精讲

常用集合类介绍

  • List 接口ArrayListLinkedList
  • Set 接口HashSetTreeSet
  • Map 接口HashMapTreeMap
import java.util.*;

public class CollectionExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        System.out.println("List: " + list);

        Set<String> set = new HashSet<>();
        set.add("a");
        set.add("b");
        System.out.println("Set: " + set);

        Map<String, String> map = new HashMap<>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        System.out.println("Map: " + map);
    }
}

集合类的内部实现

  • ArrayList:基于数组实现,提供快速的随机访问。
  • LinkedList:基于双向链表实现,插入和删除操作速度快。
  • HashSet:基于哈希表实现,查找速度快。
  • TreeSet:基于红黑树实现,元素有序。

集合类的使用场景

  • ArrayList:适用于频繁的随机访问和修改。
  • LinkedList:适用于频繁的插入和删除操作。
  • HashSet:适用于需要快速查找操作的场景。
  • TreeSet:适用于需要有序元素的场景。

项目案例: 在一个电商网站的购物车功能中,可以使用集合类来存储用户添加的商品。

import java.util.*;

public class ShoppingCartExample {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        cart.addItem("商品1");
        cart.addItem("商品2");
        cart.addItem("商品3");

        cart.displayItems();
    }
}

class ShoppingCart {
    private List<String> items = new ArrayList<>();

    public void addItem(String item) {
        items.add(item);
    }

    public void displayItems() {
        System.out.println("购物车中的商品:");
        for (String item : items) {
            System.out.println("- " + item);
        }
    }
}

ShoppingCart cart = new ShoppingCart();
cart.addItem("商品1");
cart.addItem("商品2");
cart.addItem("商品3");
cart.displayItems();
Java并发编程面试题精讲

基本概念与原理

  • 线程:一个程序的多个执行流。
  • 线程安全:确保多个线程访问时不会发生数据不一致的情况。
  • 锁机制:用于实现线程之间的同步。

同步机制与并发工具类

  • synchronized:关键字用于实现方法或代码块的同步。
  • Lock:接口提供了更细粒度的锁控制。
  • Semaphore:信号量用于控制同时访问资源的线程数量。
  • CountDownLatch:倒计时锁存器用于等待多个线程完成。
import java.util.concurrent.*;

public class ConcurrencyExample {
    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(2);
        new Thread(() -> {
            System.out.println("线程1开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程1结束");
            latch.countDown();
        }).start();

        new Thread(() -> {
            System.out.println("线程2开始");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程2结束");
            latch.countDown();
        }).start();

        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("主线程继续执行");
    }
}

项目案例: 在一个多线程爬虫项目中,可以使用 LockSemaphore 处理并发访问问题。

import java.util.concurrent.locks.*;

public class MultithreadedCrawlerExample {
    private static final int MAX_THREADS = 5;
    private static ReentrantLock lock = new ReentrantLock();
    private static Semaphore semaphore = new Semaphore(MAX_THREADS);

    public static void startCrawling() {
        for (int i = 0; i < MAX_THREADS; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    try {
                        System.out.println("线程" + Thread.currentThread().getId() + "开始爬取");
                        Thread.sleep(1000);
                        System.out.println("线程" + Thread.currentThread().getId() + "结束爬取");
                    } finally {
                        semaphore.release();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    public static void main(String[] args) {
        startCrawling();
    }
}

常见并发问题与解决方案

  • 死锁:两个或多个线程互相等待对方持有的锁。
  • 活锁:线程不断尝试获取锁但一直失败。
  • 饥饿:某线程长时间无法获取资源。

死锁示例

public class DeadlockExample {
    public static void main(String[] args) {
        Object resource1 = new Object();
        Object resource2 = new Object();

        new Thread(() -> {
            synchronized (resource1) {
                System.out.println("线程1获取resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resource2) {
                    System.out.println("线程1获取resource2");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (resource2) {
                System.out.println("线程2获取resource2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resource1) {
                    System.out.println("线程2获取resource1");
                }
            }
        }).start();
    }
}

项目案例: 在设计一个在线交易系统时,可以避免死锁,确保并发操作的安全性。

import java.util.concurrent.*;

public class OnlineTransactionSystem {
    private static Object resource1 = new Object();
    private static Object resource2 = new Object();

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (resource1) {
                System.out.println("线程1获取resource1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resource2) {
                    System.out.println("线程1获取resource2");
                }
            }
        }).start();

        new Thread(() -> {
            synchronized (resource2) {
                System.out.println("线程2获取resource2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resource1) {
                    System.out.println("线程2获取resource1");
                }
            }
        }).start();
    }
}
Java虚拟机与性能优化面试题精讲

JVM工作原理

  • JVM架构:JVM 包含类加载器、运行时数据区、字节码解释器和本地接口。
  • 类加载器:负责加载类文件的机制。
  • 运行时数据区:包括堆、栈、方法区、程序计数器和本地方法栈。

垃圾回收机制

  • 垃圾回收算法:标记-清除、复制、标记-整理。
  • 垃圾回收器:Serial、Parallel、CMS、G1。

垃圾回收示例

public class GarbageCollectionExample {
    public static void main(String[] args) {
        while (true) {
            Object obj = new Object();
            System.gc();  // 提示JVM进行垃圾回收
        }
    }
}

项目案例: 在高并发系统中,可以通过优化 JVM 参数和垃圾回收策略提高系统性能。

public class HighConcurrencySystem {
    public static void main(String[] args) {
        // 设置JVM参数
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "4");
        System.setProperty("java.util.concurrent.ForkJoinPool.maximumParallelism", "8");

        // 启动任务
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        for (int i = 0; i < 10; i++) {
            executorService.submit(new Task());
        }

        // 关闭线程池
        executorService.shutdown();
    }

    static class Task implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println("任务完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

性能优化策略

  • 减少对象创建:减少不必要的对象创建。
  • 重用对象:通过对象池减少对象创建。
  • 使用合适的数据结构:选择合适的数据结构提高效率。
  • 减少锁的使用:使用无锁数据结构或减少锁的粒度。

通过以上内容的准备,可以更好地应对 Java 面试,提升自己的技术实力。希望这些知识能帮助你成功地通过面试。

0人推荐
随时随地看视频
慕课网APP