是什么让 Java 编程水平实现质的飞跃?中级秘籍大公开!

引言

在掌握了 Java 基础之后,踏入中级编程的领域就意味着要处理更复杂的问题,运用更高级的特性。中级 Java 编程包含了面向对象的高级特性、异常处理、集合框架、多线程编程等内容。这些特性能够让你编写出更高效、更具可维护性和可扩展性的程序。本教程将通过详细且专业的代码示例和深入浅出的讲解,带你逐步掌握 Java 中级编程的核心要点。

1. 面向对象的高级特性

1.1 抽象类和接口

抽象类

抽象类是一种不能被实例化的类,它主要用于为子类提供一个通用的模板。抽象类可以包含抽象方法和具体方法。抽象方法只有声明,没有实现,需要子类来实现。

java

// 定义一个抽象类 Animal
abstract class Animal {
    // 成员变量
    protected String name;

    // 构造方法
    public Animal(String name) {
        this.name = name;
    }

    // 抽象方法,用于发出声音
    public abstract void makeSound();

    // 具体方法,用于睡觉
    public void sleep() {
        System.out.println(name + " is sleeping");
    }
}

// 定义一个子类 Dog 继承自 Animal
class Dog extends Animal {
    // 构造方法
    public Dog(String name) {
        super(name);
    }

    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + " says Woof!");
    }
}

// 定义一个子类 Cat 继承自 Animal
class Cat extends Animal {
    // 构造方法
    public Cat(String name) {
        super(name);
    }

    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + " says Meow!");
    }
}

public class AbstractClassExample {
    public static void main(String[] args) {
        // 创建 Dog 对象
        Dog dog = new Dog("Buddy");
        dog.makeSound();
        dog.sleep();

        // 创建 Cat 对象
        Cat cat = new Cat("Whiskers");
        cat.makeSound();
        cat.sleep();
    }
}

在上述代码中,Animal 是一个抽象类,包含一个成员变量 name、一个构造方法、一个抽象方法 makeSound() 和一个具体方法 sleep()Dog 和 Cat 类继承自 Animal 类,并实现了 makeSound() 方法。

接口

接口是一种完全抽象的类型,它只包含抽象方法和常量。一个类可以实现多个接口,从而实现多重继承的效果。

java

// 定义一个接口 Flyable
interface Flyable {
    // 常量
    int MAX_ALTITUDE = 10000;

    // 抽象方法,用于飞行
    void fly();
}

// 定义一个接口 Swimmable
interface Swimmable {
    // 抽象方法,用于游泳
    void swim();
}

// 定义一个类 Duck 实现 Flyable 和 Swimmable 接口
class Duck implements Flyable, Swimmable {
    private String name;

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

    @Override
    public void fly() {
        System.out.println(name + " is flying at altitude up to " + MAX_ALTITUDE + " meters");
    }

    @Override
    public void swim() {
        System.out.println(name + " is swimming gracefully");
    }
}

public class InterfaceExample {
    public static void main(String[] args) {
        Duck duck = new Duck("Donald");
        duck.fly();
        duck.swim();
    }
}

在上述代码中,Flyable 和 Swimmable 是两个接口,Duck 类实现了这两个接口,并实现了接口中的抽象方法。接口中的常量 MAX_ALTITUDE 可以在实现类中直接使用。

1.2 多态

多态是指同一个方法调用可以根据对象的不同类型而表现出不同的行为。多态主要通过继承和接口实现。

java

// 定义一个父类 Shape
class Shape {
    // 计算面积的方法
    public double area() {
        return 0;
    }
}

// 定义一个子类 Circle 继承自 Shape
class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
}

// 定义一个子类 Rectangle 继承自 Shape
class Rectangle extends Shape {
    private double length;
    private double width;

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    @Override
    public double area() {
        return length * width;
    }
}

public class PolymorphismExample {
    public static void printArea(Shape shape) {
        System.out.println("The area of the shape is: " + shape.area());
    }

    public static void main(String[] args) {
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);

        printArea(circle);
        printArea(rectangle);
    }
}

在上述代码中,Shape 是父类,Circle 和 Rectangle 是子类。printArea() 方法接受一个 Shape 类型的参数,根据传入的实际对象类型调用相应的 area() 方法,实现了多态。

2. 异常处理

在 Java 中,异常是指程序在运行过程中出现的错误或意外情况。异常处理可以让程序在出现异常时能够继续执行,提高程序的健壮性。

2.1 异常的分类

Java 中的异常分为两类:受检查异常(Checked Exception)和非受检查异常(Unchecked Exception)。受检查异常必须在方法签名中声明或捕获,非受检查异常不需要。

2.2 异常处理的语法

异常处理使用 try-catch-finally 语句块。此外,还可以使用 throws 关键字在方法签名中声明可能抛出的异常。

java

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ExceptionHandlingExample {
    public static void readFile(String filePath) throws FileNotFoundException {
        File file = new File(filePath);
        Scanner scanner = new Scanner(file);

        while (scanner.hasNextLine()) {
            System.out.println(scanner.nextLine());
        }

        scanner.close();
    }

    public static void main(String[] args) {
        try {
            readFile("nonexistent.txt");
        } catch (FileNotFoundException e) {
            System.out.println("Error: File not found - " + e.getMessage());
        } finally {
            System.out.println("This block always executes");
        }
    }
}

在上述代码中,readFile() 方法使用 throws 关键字声明可能抛出 FileNotFoundException 异常。在 main() 方法中,调用 readFile() 方法并使用 try-catch-finally 语句块进行异常处理。

2.3 自定义异常

除了 Java 提供的异常类,我们还可以自定义异常类。自定义异常类通常继承自 Exception 或其子类。

java

// 自定义异常类
class NegativeNumberException extends Exception {
    public NegativeNumberException(String message) {
        super(message);
    }
}

// 计算平方根的类
class SquareRootCalculator {
    public static double calculateSquareRoot(double number) throws NegativeNumberException {
        if (number < 0) {
            throw new NegativeNumberException("Cannot calculate square root of a negative number");
        }
        return Math.sqrt(number);
    }
}

public class CustomExceptionExample {
    public static void main(String[] args) {
        try {
            double result = SquareRootCalculator.calculateSquareRoot(-4);
            System.out.println("Square root: " + result);
        } catch (NegativeNumberException e) {
            System.out.println("Exception caught: " + e.getMessage());
        }
    }
}

在上述代码中,NegativeNumberException 是自定义异常类,继承自 ExceptionSquareRootCalculator 类的 calculateSquareRoot() 方法在遇到负数时抛出 NegativeNumberException 异常。

3. 集合框架

Java 集合框架提供了一组用于存储和操作数据的类和接口。常用的集合类有 ListSet 和 Map

3.1 List

List 是一个有序的集合,允许存储重复的元素。常用的实现类有 ArrayList 和 LinkedList

java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class ListExample {
    public static void main(String[] args) {
        // 创建一个 ArrayList 对象
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Apple");
        arrayList.add("Banana");
        arrayList.add("Cherry");

        // 使用迭代器遍历 ArrayList
        Iterator<String> arrayListIterator = arrayList.iterator();
        while (arrayListIterator.hasNext()) {
            System.out.println(arrayListIterator.next());
        }

        // 创建一个 LinkedList 对象
        List<String> linkedList = new LinkedList<>();
        linkedList.add("Dog");
        linkedList.add("Cat");
        linkedList.add("Bird");

        // 使用增强 for 循环遍历 LinkedList
        for (String animal : linkedList) {
            System.out.println(animal);
        }
    }
}

在上述代码中,我们创建了 ArrayList 和 LinkedList 对象,并向其中添加元素。使用迭代器和增强 for 循环分别遍历这两个列表。

3.2 Set

Set 是一个不允许存储重复元素的集合。常用的实现类有 HashSet 和 TreeSet

java

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class SetExample {
    public static void main(String[] args) {
        // 创建一个 HashSet 对象
        Set<String> hashSet = new HashSet<>();
        hashSet.add("Apple");
        hashSet.add("Banana");
        hashSet.add("Apple"); // 重复元素,不会被添加

        // 使用迭代器遍历 HashSet
        Iterator<String> hashSetIterator = hashSet.iterator();
        while (hashSetIterator.hasNext()) {
            System.out.println(hashSetIterator.next());
        }

        // 创建一个 TreeSet 对象
        Set<String> treeSet = new TreeSet<>();
        treeSet.add("Dog");
        treeSet.add("Cat");
        treeSet.add("Bird");

        // 使用增强 for 循环遍历 TreeSet
        for (String animal : treeSet) {
            System.out.println(animal);
        }
    }
}

在上述代码中,我们创建了 HashSet 和 TreeSet 对象,并向其中添加元素。由于 Set 不允许重复元素,所以重复的元素不会被添加。使用迭代器和增强 for 循环分别遍历这两个集合。

3.3 Map

Map 是一种键值对的集合,每个键对应一个值。常用的实现类有 HashMap 和 TreeMap

java

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class MapExample {
    public static void main(String[] args) {
        // 创建一个 HashMap 对象
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("Apple", 1);
        hashMap.put("Banana", 2);
        hashMap.put("Cherry", 3);

        // 使用迭代器遍历 HashMap 的键值对
        Iterator<Map.Entry<String, Integer>> hashMapIterator = hashMap.entrySet().iterator();
        while (hashMapIterator.hasNext()) {
            Map.Entry<String, Integer> entry = hashMapIterator.next();
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // 创建一个 TreeMap 对象
        Map<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("Dog", 1);
        treeMap.put("Cat", 2);
        treeMap.put("Bird", 3);

        // 使用增强 for 循环遍历 TreeMap 的键值对
        for (Map.Entry<String, Integer> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

在上述代码中,我们创建了 HashMap 和 TreeMap 对象,并向其中添加键值对。使用迭代器和增强 for 循环分别遍历这两个 Map

4. 多线程编程

多线程编程可以让程序同时执行多个任务,提高程序的性能和响应速度。

4.1 创建线程的两种方式

在 Java 中,创建线程有两种方式:继承 Thread 类和实现 Runnable 接口。

继承 Thread 类

java

class MyThread extends Thread {
    private String threadName;

    public MyThread(String name) {
        threadName = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(threadName + ": " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread("Thread 1");
        MyThread thread2 = new MyThread("Thread 2");

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread finished");
    }
}

在上述代码中,MyThread 类继承自 Thread 类,并重写了 run() 方法。在 main() 方法中,创建了 MyThread 对象并调用 start() 方法启动线程。使用 join() 方法等待线程执行完毕。

实现 Runnable 接口

java

class MyRunnable implements Runnable {
    private String threadName;

    public MyRunnable(String name) {
        threadName = name;
    }

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(threadName + ": " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable1 = new MyRunnable("Runnable 1");
        MyRunnable myRunnable2 = new MyRunnable("Runnable 2");

        Thread thread1 = new Thread(myRunnable1);
        Thread thread2 = new Thread(myRunnable2);

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Main thread finished");
    }
}

在上述代码中,MyRunnable 类实现了 Runnable 接口,并重写了 run() 方法。在 main() 方法中,创建了 MyRunnable 对象,并将其作为参数传递给 Thread 类的构造函数,然后调用 start() 方法启动线程。使用 join() 方法等待线程执行完毕。

4.2 线程同步

当多个线程访问共享资源时,可能会出现数据不一致的问题。线程同步可以解决这个问题。

java

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized void decrement() {
        count--;
    }

    public int getCount() {
        return count;
    }
}

class IncrementThread implements Runnable {
    private Counter counter;

    public IncrementThread(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.increment();
        }
    }
}

class DecrementThread implements Runnable {
    private Counter counter;

    public DecrementThread(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            counter.decrement();
        }
    }
}

public class ThreadSynchronizationExample {
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();

        Thread incrementThread = new Thread(new IncrementThread(counter));
        Thread decrementThread = new Thread(new DecrementThread(counter));

        incrementThread.start();
        decrementThread.start();

        incrementThread.join();
        decrementThread.join();

        System.out.println("Final count: " + counter.getCount());
    }
}

在上述代码中,Counter 类的 increment() 和 decrement() 方法使用了 synchronized 关键字,确保同一时间只有一个线程可以访问这些方法,从而避免了数据不一致的问题。

结论

通过本教程的学习,你已经深入掌握了 Java 中级编程的核心内容,包括面向对象的高级特性、异常处理、集合框架和多线程编程。这些知识将帮助你编写出更高效、更复杂、更具可维护性的 Java 程序。希望你在今后的学习和实践中不断巩固和提高自己的编程能力,挑战更复杂的项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值