Java基础编程500题——综合练习

💥 该系列属于【Java基础编程500题】专栏,如您需查看Java基础的其他相关题目,请您点击左边的连接

目录

1. 【数组,字符串,StringBuider,循环】给定一个字符串,在不使用Map集合的情况下,统计并输出每个字符出现的频率。

2. 【Arrays,数组,循环】该程序输入一个包含10个的数字整数数组,对整数数组升序排序,并查找数组中的指定元素,输出该元素的位置。

3. 【数组,字符串,循环,异常处理,Integer】该程序输入一行含10个数字的字符串,数字和数字之间用空格分割,例如输入"1 2 3 4 5 6 7 8 9 10",将它转换成整数数组,如果输入错误需要抛出异常并中断进程。转换后再计算数组中所有偶数的平均值和所有奇数的平均值,并输出结果。

4. 【数组,字符串,循环,Character,方法】定义一个方法,该方法接受一个字符串作为参数,并返回该字符串中的所有大写字母和小写字母的数量。

5. 【Math,数组,循环,Integer】使用Math的方法生成一个长度为10的随机整数数组,每个数字的取值范围是[-100,100],并找出数组中的最大值和最小值。

6. 【数组,字符串,循环,Arrays】输入一个字符串数组(用split(" ")分割)和一个字符串。如果输入的字符串是"reverse",则输出数组中每个字符串的逆序版本;如果输入的字符串是"normalized",则输出数组中每个字符串,并将字符串首字母大写其余字母小写;如果输入的字符串是"sort",则输出数组中字符串升序排序的结果;否则将字符数组连成一个字符串打印。

7. 【数组,循环,Math,StringBuilder】使用StringBuilder和Math类,计算并输出1到10每个数字的平方和立方,格式如下:“数字1的平方是X,立方是Y”。

8. 【面向对象,Arrays】定义一个学生类,包含姓名和成绩属性。创建一个学生数组,使用Arrays.sort方法对学生数组按成绩进行排序,并输出排序后的学生信息。

9. 【面向对象,匿名内部类,lambda表达式】定义一个接口Compute,包含一个方法int compute(int a, int b)。使用匿名内部类和lambda表达式分别实现加法和乘法运算,并输出结果。

10. 【枚举类,方法】定义一个枚举类Color,包含红色、绿色、蓝色。编写一个方法,根据传入的颜色枚举值,使用switch-case语句输出对应的颜色名称。

11. 【枚举类,泛型,异常处理】定义一个枚举类Operation,包含加、减、乘、除四种操作。编写一个方法,根据枚举值和两个操作数(均为Number的子类)进行计算,并输出结果。请使用泛型。

12. 【面向对象,匿名内部类,lambda表达式,Stream,Collections】使用匿名内部类、lambda表达式和Stream API对员工(含有年龄和部门)列表对年龄进行降序排序和过滤(筛选出“研发部门的员工”)。

13. 【面向对象,枚举类,集合,Collections】使用枚举类、List接口和Collections工具类,实现一个简单的扑克牌游戏。生成52张牌,并发牌给两个玩家。

14. 【集合,Stream,匿名内部类】使用Map接口存储学生成绩,并对成绩进行降序排序和统计平均分。

15. 【集合,Collections,匿名内部类,Stream,字符串】字符串用List存储,实现一个简单的字符串处理程序,包括字符串的连接,过滤出含有"a"的字符串,根据字符串长度排序。

16. 【泛型,集合,Stream,Collections】实现一个泛型工具类,该类包含两个方法,一个用于计算泛型数组的平均值,另一个可对数组进行降序排序。

17. 【面向对象,集合】使用Queue接口和PriorityQueue实现一个简单的任务调度系统。要求: 存储一系列任务,每个任务有一个优先级。 根据优先级执行任务,优先级高的任务先执行。

18. 【日期API,集合】使用TreeSet实现一个简单的日程管理器。要求:存储会议时间,自动按时间顺序排序,最后输出所有会议时间。

19. 【注解,反射,动态代理】定义一个注解@MethodInfo,包含方法描述和作者信息。使用反射和动态代理,在调用方法前后输出方法描述和作者信息。

20. 【正则表达式,字符串】编写一个程序,从一段HTML文本中去除所有的HTML标签,只保留文本内容。

21. 【正则表达式,字符串】编写一个程序,从一段HTML文本中提取出所有的URL链接。

22. 【文件,IO流,正则表达式,异常处理】从当前目录下的文本文件phones.txt中读取电话号码,使用正则表达式验证电话号码格式,并将格式正确的电话号码输出到另一个文件phones.txt中。如果遇到格式错误的电话号码,捕获异常并输出错误信息。

23. 【多线程,时间和日期API】编写一个程序,使用两个线程打印当前时间,每秒更新一次,持续10秒。

24. 【异常处理,文件,IO流】记录用户操作日志。当用户进行非法操作时,抛出自定义异常,并将异常信息及操作时间记录到日志文件中。

25. 【多线程,网络编程,文件,IO流】编写一个多线程下载器,可以同时下载多个文件。要求使用线程池来管理下载任务,并在每个文件下载完成后输出下载信息。

26. 【多线程,文件,IO流】编写一个程序,使用两个线程将一个文本文件的内容复制到另一个文件中。要求使用同步方法保证线程安全。

27. 【异常处理,反射,动态代理】编写一个程序,使用动态代理记录方法调用的开始和结束时间,如果方法执行时间超过一定阈值,则抛出自定义异常。

28. 【面向对象,注解,反射,文件,IO流】实现对象的序列化和反序列化。

29. 【枚举类,注解,异常处理,动态代理】定义一个员工枚举类,使用自定义注解标记员工角色,通过动态代理实现权限校验。


✨✨  返回题目目录 ✨ ✨ 

Java基础编程500题


1. 【数组,字符串,StringBuider,循环】给定一个字符串,在不使用Map集合的情况下,统计并输出每个字符出现的频率。

public class Main {
    public static void main(String[] args) {
        String str = "aabbbcccc";
        StringBuilder sb = new StringBuilder();
        int[] frequency = new int[256]; // Assuming ASCII character set

        for (int i = 0; i < str.length(); i++) {
            frequency[str.charAt(i)]++;
        }

        for (int i = 0; i < frequency.length; i++) {
            if (frequency[i] > 0) {
                sb.append((char) i).append(": ").append(frequency[i]).append("\n");
            }
        }
        System.out.println("字符频率统计:\n" + sb.toString());
    }
}

2. 【Arrays,数组,循环】该程序输入一个包含10个的数字整数数组,对整数数组升序排序,并查找数组中的指定元素,输出该元素的位置。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
        System.out.println("请输入要在排序后的数组中查找索引的元素:");
        int target = sc.nextInt();
        int index = Arrays.binarySearch(arr, target);
        System.out.println(index);
    }
}

3. 【数组,字符串,循环,异常处理,Integer】该程序输入一行含10个数字的字符串,数字和数字之间用空格分割,例如输入"1 2 3 4 5 6 7 8 9 10",将它转换成整数数组,如果输入错误需要抛出异常并中断进程。转换后再计算数组中所有偶数的平均值和所有奇数的平均值,并输出结果。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();

        String[] strNums = str.split(" ");
        int[] nums = new int[strNums.length];
        for (int i = 0; i < strNums.length; i++) {
            try {
                nums[i] = Integer.parseInt(strNums[i]);
            } catch (NumberFormatException e) {
                System.out.println("转换失败!" + e.getMessage());
            }
        }

        int odd_sum = 0, even_sum = 0;
        int odd_num = 0, even_num = 0;
        int odd_avg, even_avg;

        for (int i : nums) {
            if (i % 2 == 0) {
                even_sum += i;
                even_num++;
            } else {
                odd_sum += i;
                odd_num++;
            }
        }

        odd_avg = odd_num > 0 ? odd_sum / odd_num : 0;
        even_avg = even_num > 0 ? even_sum / even_num : 0;

        System.out.println("偶数平均值:" + even_avg);
        System.out.println("奇数平均值:" + odd_avg);
    }
}

4. 【数组,字符串,循环,Character,方法】定义一个方法,该方法接受一个字符串作为参数,并返回该字符串中的所有大写字母和小写字母的数量。

public class Main {
    public static void main(String[] args) {
        String text = "Hello World! Java Programming.";
        int[] ans = Count(text);
        System.out.println("大写字母数量" + ans[0]);
        System.out.println("小写字母数量" + ans[1]);
    }

    public static int[] Count(String str) {
        int[] arr = new int[2];
        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            if (Character.isUpperCase(charArray[i])) {
                arr[0]++; //存储大写数量
            } else if (Character.isLowerCase(charArray[i])) {
                arr[1]++; //存储小写数量
            }
        }
        return arr;
    }
}

5. 【Math,数组,循环,Integer】使用Math的方法生成一个长度为10的随机整数数组,每个数字的取值范围是[-100,100],并找出数组中的最大值和最小值。

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] arr = new int[10];
        int max_value = Integer.MIN_VALUE;
        int min_value = Integer.MAX_VALUE;

        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) (Math.random() * 201) - 100;
        }
        System.out.println(Arrays.toString(arr));
        for (int i = 0; i < arr.length; i++) {
            if (max_value < arr[i]) {
                max_value = arr[i];
            }
            if (min_value > arr[i]) {
                min_value = arr[i];
            }
        }
        System.out.println("最大值" + max_value);
        System.out.println("最小值" + min_value);
    }
}

6. 【数组,字符串,循环,Arrays】输入一个字符串数组(用split(" ")分割)和一个字符串。如果输入的字符串是"reverse",则输出数组中每个字符串的逆序版本;如果输入的字符串是"normalized",则输出数组中每个字符串,并将字符串首字母大写其余字母小写;如果输入的字符串是"sort",则输出数组中字符串升序排序的结果;否则将字符数组连成一个字符串打印。

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        System.out.println("请输入一个字符数组(请用空格分割每一个字符串):");
        Scanner sc = new Scanner(System.in);
        String strArr = sc.nextLine();
        String[] strs = strArr.split(" ");

        System.out.println("请输入一个字符串:");
        String str = sc.nextLine();

        if (str.equals("reverse")) {
            for (int i = strs.length - 1; i >= 0; i--) {
                System.out.print(strs[i] + " ");
            }
        } else if (str.equals("normalized")) {
            for (String s : strs) {
                System.out.print(Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase() + " ");
            }
        } else if (str.equals("sort")) {
            Arrays.sort(strs);
            System.out.println(Arrays.toString(strs));
        } else {
            String join = String.join("", strs);
            System.out.println(join);
        }
    }
}

7. 【数组,循环,Math,StringBuilder】使用StringBuilder和Math类,计算并输出1到10每个数字的平方和立方,格式如下:“数字1的平方是X,立方是Y”。

public class Main {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= 10; i++) {
            int x = (int) Math.pow(i,2);
            int y = (int) Math.pow(i,3);
            sb.append("数字")
                    .append(i)
                    .append("的平方是")
                    .append(x)
                    .append(",立方是")
                    .append(y)
                    .append("\n");
        }
        System.out.println(sb);
    }
}

8. 【面向对象,Arrays】定义一个学生类,包含姓名和成绩属性。创建一个学生数组,使用Arrays.sort方法对学生数组按成绩进行排序,并输出排序后的学生信息。

import java.util.Arrays;

class Student implements Comparable<Student> {
    private String name;
    private double score;

    public Student(String name, double score) {
        this.name = name;
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    // 方法一:
    @Override
    public int compareTo(Student o) {
        return Double.compare(this.score, o.score); //升序排序
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}


public class Main {
    public static void main(String[] args) {
        Student[] students = {
                new Student("张三", 90.5),
                new Student("李四", 85.0),
                new Student("王五", 92.3)
        };
        // 方法一:
        Arrays.sort(students);

        // 方法二:
        /*
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return Double.compare(o1.getScore(), o2.getScore());
            }
        });
        */
        System.out.println(Arrays.toString(students));
    }
}

9. 【面向对象,匿名内部类,lambda表达式】定义一个接口Compute,包含一个方法int compute(int a, int b)。使用匿名内部类和lambda表达式分别实现加法和乘法运算,并输出结果。

interface Compute {
    int compute(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        Compute add = new Compute() {
            @Override
            public int compute(int a, int b) {
                return a + b;
            }
        };
        System.out.println("加法结果:" + add.compute(5, 3));

        Compute multiply = (a, b) -> a * b;
        System.out.println("乘法结果:" + multiply.compute(5, 3));
    }
}

10. 【枚举类,方法】定义一个枚举类Color,包含红色、绿色、蓝色。编写一个方法,根据传入的颜色枚举值,使用switch-case语句输出对应的颜色名称。

enum Color {
    RED("红色"),
    GREEN("绿色"),
    BLUE("蓝色");

    private String color;

    Color(String color) {
        this.color = color;
    }

    public String getColor() {
        return color;
    }
}


public class Main {
    public static void main(String[] args) {
        judge(Color.RED);
        judge(Color.GREEN);
        judge(Color.BLUE);
    }

    public static void judge(Color color) {
        switch (color) {
            case RED:
            case GREEN:
            case BLUE:
                System.out.println(color.getColor());
                break;
            default:
                System.out.println("不存在该颜色");
        }
    }
}

11. 【枚举类,泛型,异常处理】定义一个枚举类Operation,包含加、减、乘、除四种操作。编写一个方法,根据枚举值和两个操作数(均为Number的子类)进行计算,并输出结果。请使用泛型。

enum Operation {

    ADD {
        @Override
        <T extends Number, K extends Number> double apply(T a, K b) {
            return a.doubleValue() + b.doubleValue();
        }
    },
    SUBTRACT {
        @Override
        <T extends Number, K extends Number> double apply(T a, K b) {
            return a.doubleValue() - b.doubleValue();
        }
    },
    MULTIPLY {
        <T extends Number, K extends Number> double apply(T a, K b) {
            return a.doubleValue() * b.doubleValue();
        }
    },
    DIVIDE {
        @Override
        <T extends Number, K extends Number> double apply(T a, K b) {
            if (b.doubleValue() == 0) {
                throw new ArithmeticException("除数不能为0");
            }
            return a.doubleValue() / b.doubleValue();
        }
    };

    abstract <T extends Number, K extends Number> double apply(T a, K b);

}

public class Main {
    public static void main(String[] args) {
        System.out.println("加法结果:" + calculate(Operation.ADD, 10, 5.5));
        System.out.println("减法结果:" + calculate(Operation.SUBTRACT, 10, 5.5));
        System.out.println("乘法结果:" + calculate(Operation.MULTIPLY, 10, 5.5));
        System.out.println("除法结果:" + calculate(Operation.DIVIDE, 10, 2));
    }

    public static <T extends Number, K extends Number> double calculate(Operation operation, T a, K b) {
        return operation.apply(a, b);
    }
}

12. 【面向对象,匿名内部类,lambda表达式,Stream,Collections】使用匿名内部类、lambda表达式和Stream API对员工(含有年龄和部门)列表对年龄进行降序排序和过滤(筛选出“研发部门的员工”)。

import java.util.*;
import java.util.stream.Collectors;

class Employee {
    private String name;
    private int age;
    private String department;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getDepartment() {
        return department;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Employee> employees = Arrays.asList(
                new Employee("张三", 30, "研发部"),
                new Employee("李四", 25, "市场部"),
                new Employee("王五", 35, "研发部"),
                new Employee("赵六", 28, "人事部")
        );

        // 使用匿名内部类对员工按年龄排序
        Collections.sort(employees, new Comparator<Employee>() {
            @Override
            public int compare(Employee e1, Employee e2) {
                return Integer.compare(e1.getAge(), e2.getAge());
            }
        });

        // 使用lambda表达式过滤出研发部的员工
        List<Employee> filteredEmployees = employees.stream()
                .filter(e -> "研发部".equals(e.getDepartment()))
                .collect(Collectors.toList());

        // 输出结果
        filteredEmployees.forEach(e -> System.out.println("姓名:" + e.getName() + ",年龄:" + e.getAge() + ",部门:" + e.getDepartment()));
    }
}

13. 【面向对象,枚举类,集合,Collections】使用枚举类、List接口和Collections工具类,实现一个简单的扑克牌游戏。生成52张牌,并发牌给两个玩家。

import java.util.*;

enum Suit { //花色
    HEART, DIAMOND, CLUB, SPADE
}

enum Rank { //牌面大小
    ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING
}

class Card { //一张扑克牌
    private Suit suit;
    private Rank rank;

    public Card(Suit suit, Rank rank) {
        this.suit = suit;
        this.rank = rank;
    }

    @Override
    public String toString() {
        return "花色:" + suit + ",牌面:" + rank;
    }
}


public class Main {
    public static void main(String[] args) {
        List<Card> deck = new ArrayList<>();
        for (Suit suit : Suit.values()) {
            for (Rank rank : Rank.values()) {
                deck.add(new Card(suit, rank));
            }
        }

        // 洗牌
        Collections.shuffle(deck);

        // 发牌
        Queue<Card> player1 = new LinkedList<>();
        Queue<Card> player2 = new LinkedList<>();
        for (int i = 0; i < deck.size(); i++) {
            if (i % 2 == 0) {
                player1.offer(deck.get(i));
            } else {
                player2.offer(deck.get(i));
            }
        }

        // 输出玩家手中的牌
        System.out.println("玩家1的牌:");
        player1.forEach(System.out::println);
        System.out.println("玩家2的牌:");
        player2.forEach(System.out::println);
    }
}

14. 【集合,Stream,匿名内部类】使用Map接口存储学生成绩,并对成绩进行降序排序和统计平均分。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三", 86);
        map.put("李四", 83);
        map.put("王五", 97);
        map.put("赵六", 93);

        ArrayList<Map.Entry<String, Integer>> entries = new ArrayList<>(map.entrySet());
        entries.sort(new Comparator<Map.Entry<String, Integer>>() {
            @Override
            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                return -o1.getValue() + o2.getValue(); //成绩降序排序
            }
        });
        System.out.println(entries);

        //求平均分
        double average = entries.stream()
                .mapToInt(s -> s.getValue())
                .average()
                .orElse(0);
        System.out.println(average);

    }
}

15. 【集合,Collections,匿名内部类,Stream,字符串】字符串用List存储,实现一个简单的字符串处理程序,包括字符串的连接,过滤出含有"a"的字符串,根据字符串长度排序。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {

        List<String> list = List.of("Python", "C++", "Java", "Golang", "JavaScript");

        //字符串的连接
        String collect1 = list.stream().collect(Collectors.joining(""));
        System.out.println(collect1);

        //字符串的过滤
        List<String> collect2 = list.stream().filter(n -> n.contains("a")).collect(Collectors.toList());
        System.out.println(collect2);

        //字符串按照长度排序
        ArrayList<String> strings = new ArrayList<>(list); //List.of生成的列表不可修改
        Collections.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Integer.compare(o1.length(), o2.length()); //根据长度排序
            }
        });
        System.out.println(strings);
    }
}

16. 【泛型,集合,Stream,Collections】实现一个泛型工具类,该类包含两个方法,一个用于计算泛型数组的平均值,另一个可对数组进行降序排序。

import java.util.*;

class ArraysUtil<T extends Comparable<T>> { //必须写 Comparable<T> ,否则无法使用compareTo
    private List<T> list;

    ArraysUtil(List<T> list) {
        this.list = list;
    }

    public List<T> sort() {
        list.sort(new Comparator<T>() {
            @Override
            public int compare(T o1, T o2) {
                return o2.compareTo(o1); //降序排序
            }
        });
        return null;
    }

    public Double avg() {
        return list.stream()
                .mapToDouble(s -> Double.parseDouble(String.valueOf(s))) // 将 Number 转换为 double
                .average()
                .orElse(Double.NaN); // 如果列表为空,返回 Double.NaN
    }

    @Override
    public String toString() {
        return list.toString();
    }
}


public class Main {
    public static void main(String[] args) {
        List<Integer> integerList1 = new ArrayList<>();
        Collections.addAll(integerList1, 1, 2, 3, 4, 5);

        List<Double> integerList2 = new ArrayList<>();
        Collections.addAll(integerList2, 1.0, 2.0, 3.0, 4.0, 5.0);

        ArraysUtil<Integer> arraysUtil1 = new ArraysUtil<>(integerList1);
        System.out.println("integerList1平均值: " + arraysUtil1.avg());

        ArraysUtil<Double> arraysUtil2 = new ArraysUtil<>(integerList2);
        arraysUtil2.sort();
        System.out.println("integerList2排序后: " + arraysUtil2);

    }
}

17. 【面向对象,集合】使用Queue接口和PriorityQueue实现一个简单的任务调度系统。要求: 存储一系列任务,每个任务有一个优先级。 根据优先级执行任务,优先级高的任务先执行。

import java.util.*;

class Task implements Comparable<Task> {
    private String name;
    private int priority;

    Task(String name, int priority) {
        this.name = name;
        this.priority = priority;
    }

    public String getName() {
        return name;
    }

    @Override
    public int compareTo(Task other) {
        return Integer.compare(other.priority, this.priority); // 优先级高的先执行
    }
}

public class Main {
    public static void main(String[] args) {
        PriorityQueue<Task> taskQueue = new PriorityQueue<>();
        taskQueue.add(new Task("任务A", 3));
        taskQueue.add(new Task("任务B", 1));
        taskQueue.add(new Task("任务C", 2));
        while (!taskQueue.isEmpty()) {
            Task task = taskQueue.poll();
            System.out.println("执行任务:" + task.getName());
        }
    }
}

18. 【日期API,集合】使用TreeSet实现一个简单的日程管理器。要求:存储会议时间,自动按时间顺序排序,最后输出所有会议时间。

import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        Set<LocalDate> meetings = new TreeSet<>();
        meetings.add(LocalDate.of(2024, 7, 26));
        meetings.add(LocalDate.of(2024, 7, 31));
        meetings.add(LocalDate.of(2024, 8, 5));
        meetings.add(LocalDate.of(2024, 8, 3));

        System.out.println("会议时间顺序:");
        meetings.forEach(time -> System.out.print(time + " "));

    }
}

19. 【注解,反射,动态代理】定义一个注解@MethodInfo,包含方法描述和作者信息。使用反射和动态代理,在调用方法前后输出方法描述和作者信息。

import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MethodInfo {
    String description() default "";

    String author() default "";
}

class Test {
    @MethodInfo(description = "这是一个测试方法", author = "张三")
    public void test() {
        System.out.println("执行测试方法");
    }
}

class MyProxy implements InvocationHandler {
    private Object target;

    public MyProxy(Object target) {
        this.target = target;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
        if (methodInfo != null) {
            System.out.println("方法描述:" + methodInfo.description());
            System.out.println("作者:" + methodInfo.author());
        }
        return method.invoke(target, args);
    }
}

public class Main {
    public static void main(String[] args) {
        Test test = new Test();
        MyProxy proxy = new MyProxy(test);
        Test proxyTest = (Test) Proxy.newProxyInstance(
                test.getClass().getClassLoader(),
                test.getClass().getInterfaces(),
                proxy
        );
        proxyTest.test();
    }
}

20. 【正则表达式,字符串】编写一个程序,从一段HTML文本中去除所有的HTML标签,只保留文本内容。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String htmlContent = "<div>Hello, <b>World</b>! <a href='#'>click here</a></div>";
        String regex = "<[^>]+>";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(htmlContent);

        String plainText = matcher.replaceAll("");
        System.out.println("去除HTML标签后的文本:");
        System.out.println(plainText);
    }
}

21. 【正则表达式,字符串】编写一个程序,从一段HTML文本中提取出所有的URL链接。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args) {
        String htmlContent = "<a href='http://www.example.com'>链接1</a>" +
                "<a href='https://www.example.org'>链接2</a>";
        String regex = "href='(.*?)'";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(htmlContent);

        System.out.println("提取的URL链接:");
        while (matcher.find()) {
            System.out.println(matcher.group(1));
        }
    }
}

22. 【文件,IO流,正则表达式,异常处理】从当前目录下的文本文件phones.txt中读取电话号码,使用正则表达式验证电话号码格式,并将格式正确的电话号码输出到另一个文件phones.txt中。如果遇到格式错误的电话号码,捕获异常并输出错误信息。

import java.io.*;
import java.util.regex.*;

public class Main {
    public static void main(String[] args) {
        // 定义正则表达式,匹配中国大陆的手机号码
        String phoneRegex = "\\b(1[3-9]\\d{9})\\b";
        Pattern pattern = Pattern.compile(phoneRegex);

        // 使用 try-with-resources 自动关闭资源
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"));
             BufferedWriter bw = new BufferedWriter(new FileWriter("valid_phones.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                Matcher matcher = pattern.matcher(line);
                if (matcher.find()) {
                    bw.write(matcher.group()); // 写入匹配到的有效电话号码
                    bw.newLine(); // 添加换行符,保持跨平台兼容性
                } else {
                    System.out.println("格式错误的电话号码:" + line);    // 输出格式错误的电话号码
                }
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + e.getMessage());
        } catch (IOException e) {
            System.out.println("读取或写入文件时发生异常:" + e.getMessage());
        }
    }
}

23. 【多线程,时间和日期API】编写一个程序,使用两个线程打印当前时间,每秒更新一次,持续10秒。

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

class MyThread implements Runnable {

    @Override
    public void run() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss");
        for (int i = 0; i < 10; i++) {
            String format = dateTimeFormatter.format(LocalDateTime.now());
            System.out.println("当前时间:" + format);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("线程中断异常:" + e.getMessage());
            }
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();

        Thread thread1 = new Thread(myThread);
        Thread thread2 = new Thread(myThread);

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

24. 【异常处理,文件,IO流】记录用户操作日志。当用户进行非法操作时,抛出自定义异常,并将异常信息及操作时间记录到日志文件中。

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;

class IllegalOperationException extends Exception {
    public IllegalOperationException(String message) {
        super(message);
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            performOperation("非法操作");
        } catch (IllegalOperationException e) {
            logException(e);
        }
    }

    public static void performOperation(String operation) throws IllegalOperationException {
        if (operation.contains("非法")) {
            throw new IllegalOperationException("用户进行了非法操作:" + operation);
        }
    }

    public static void logException(Exception e) {
        try (FileWriter fw = new FileWriter("log.txt", true);
             PrintWriter pw = new PrintWriter(fw)) {
            pw.println(LocalDateTime.now() + " - " + e.getMessage());
        } catch (IOException ioException) {
            System.out.println("日志文件写入失败:" + ioException.getMessage());
        }
    }
}

25. 【多线程,网络编程,文件,IO流】编写一个多线程下载器,可以同时下载多个文件。要求使用线程池来管理下载任务,并在每个文件下载完成后输出下载信息。

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

class DownloadTask implements Runnable {
    private String fileURL;
    private String saveDir;

    public DownloadTask(String fileURL, String saveDir) {
        this.fileURL = fileURL;
        this.saveDir = saveDir;
    }

    @Override
    public void run() {
        try {
            URL url = new URL(fileURL);
            String fileName = fileURL.substring(fileURL.lastIndexOf('/') + 1);
            try (BufferedInputStream bis = new BufferedInputStream(url.openStream());
                 FileOutputStream fos = new FileOutputStream(saveDir + fileName)) {
                byte[] buffer = new byte[1024];
                int count = 0;
                while ((count = bis.read(buffer, 0, 1024)) != -1) {
                    fos.write(buffer, 0, count);
                }
                System.out.println("文件 " + fileName + " 下载完成");
            }
        } catch (IOException e) {
            System.out.println("下载失败:" + e.getMessage());
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        String[] fileURLs = {
                "http://example.com/file1.zip",
                "http://example.com/file2.zip",
                "http://example.com/file3.zip"
        };
        String saveDir = "/path/to/save/dir/";

        for (String fileURL : fileURLs) {
            Runnable downloader = new DownloadTask(fileURL, saveDir);
            executorService.execute(downloader);
        }

        executorService.shutdown();
    }
}

26. 【多线程,文件,IO流】编写一个程序,使用两个线程将一个文本文件的内容复制到另一个文件中。要求使用同步方法保证线程安全。

import java.io.*;

class FileCopyTask implements Runnable {
    private String source;
    private String target;

    public FileCopyTask(String source, String target) {
        this.source = source;
        this.target = target;
    }

    @Override
    public void run() {
        try {
            copyFile(source, target);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private synchronized void copyFile(String source, String target) throws IOException {
        try (InputStream in = new FileInputStream(source);
             OutputStream out = new FileOutputStream(target)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
            System.out.println("文件复制完成!");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(new FileCopyTask("example.txt", "target.txt"));
        Thread t2 = new Thread(new FileCopyTask("example.txt", "target.txt"));
        t1.start();
        t2.start();
    }
}

27. 【异常处理,反射,动态代理】编写一个程序,使用动态代理记录方法调用的开始和结束时间,如果方法执行时间超过一定阈值,则抛出自定义异常。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

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

// 一个简单的服务类,用于测试
interface Service {
    void performService() throws ExecutionTimeExceededException;
}

class RealService implements Service {
    @Override
    public void performService() {
        // 模拟方法执行时间
        try {
            Thread.sleep(100); // 100毫秒
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

// 动态代理的处理器
class MethodExecutionTimeHandler implements InvocationHandler {
    private Object target;
    private long threshold; // 阈值(毫秒)

    public MethodExecutionTimeHandler(Object target, long threshold) {
        this.target = target;
        this.threshold = threshold;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            // 调用实际的方法
            return method.invoke(target, args);
        } finally {
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;
            // 检查执行时间是否超过阈值
            if (duration > threshold) {
                throw new ExecutionTimeExceededException("方法执行时间超过阈值: " + threshold + "ms, 实际执行时间: " + duration + "ms");
            }
            // 输出方法执行时间
            System.out.println("方法 " + method.getName() + " 执行时间: " + duration + "ms");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建真实对象
        Service realService = new RealService();
        // 创建代理对象
        Service proxyService = (Service) Proxy.newProxyInstance(
                Service.class.getClassLoader(),
                new Class<?>[]{Service.class},
                new MethodExecutionTimeHandler(realService, 50) // 设置阈值为50毫秒
        );

        try {
            // 通过代理对象调用方法
            proxyService.performService();
        } catch (ExecutionTimeExceededException e) {
            System.out.println(e.getMessage());
        }
    }
}

28. 【面向对象,注解,反射,文件,IO流】实现对象的序列化和反序列化。

  1. 实现一个名为Person的类,包含三个字段:name(字符串类型)、age(整数类型)和address(字符串类型)。其中,nameage字段需要被序列化,而address字段不需要被序列化。

  2. 使用@Serialize注解来标记需要序列化的字段。

  3. 编写一个名为serializeObject的方法,该方法接收一个Object类型的对象和一个字符串类型的文件名作为参数,将对象的序列化数据写入指定的文件。

  4. 编写一个名为deserializeObject的方法,该方法接收一个字符串类型的文件名作为参数,从指定的文件中读取序列化数据,并返回一个Person对象。

  5. main方法中,创建一个Person对象,将其序列化到名为person.ser的文件中,然后从该文件中反序列化出一个新的Person对象,并打印出该对象的详细信息。

import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Serialize {
}

class Person {
    @Serialize
    private String name;
    @Serialize
    private int age;
    private String address; // Not serialized

    public Person() {
    }

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

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

    public void setAge(int age) {
        this.age = age;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person("张三", 30, "北京");
        String FileName = "person.ser";
        serializeObject(person, FileName);
        Person person1 = deserializeObject(FileName);
        System.out.println(person1.toString());
    }

    public static void serializeObject(Object obj, String FileName) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FileName))) {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Serialize.class)) {
                    field.setAccessible(true);
                    oos.writeObject(field.get(obj));
                }
            }
            System.out.println("对象序列化完成");
        } catch (Exception e) {
            System.out.println("序列化失败:" + e.getMessage());
        }
    }

    public static Person deserializeObject(String filename) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
            Person person = new Person();
            Class<?> clazz = person.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.isAnnotationPresent(Serialize.class)) {
                    field.setAccessible(true);
                    Object value = ois.readObject();
                    if (field.getType() == String.class) {
                        person.setName((String) value);
                    } else if (field.getType() == int.class) {
                        person.setAge((int) value);
                    }
                }
            }
            System.out.println("对象反序列化完成");
            return person;
        } catch (Exception e) {
            System.out.println("反序列化失败:" + e.getMessage());
            return null;
        }
    }

}

29. 【枚举类,注解,异常处理,动态代理】定义一个员工枚举类,使用自定义注解标记员工角色,通过动态代理实现权限校验。

  1. 定义一个枚举类Employee,包含三个枚举值:MANAGER、ENGINEER、SALESMAN,分别代表经理、工程师和销售员。
  2. 创建一个自定义注解@Role,该注解用于标记方法,并包含一个枚举类型参数role,用于指定访问该方法所需的员工角色。
  3. 定义一个自定义异常类AccessDeniedException,当权限不足时抛出该异常。
  4. 实现一个动态代理类AccessHandler,用于在方法调用前进行权限校验。
  5. 定义一个员工接口EmployeeService,包含一个方法manage(),该方法使用@Role注解,并指定只有经理(MANAGER)角色可以访问。
  6. 实现员工接口的EmployeeServiceImpl类,实现manage()方法,并在方法内打印执行管理操作的提示。
  7. Main类的main方法中,使用动态代理创建EmployeeService对象,并调用manage()方法。如果权限不足,捕获AccessDeniedException异常并打印异常信息。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 员工枚举类
enum Employee {
    MANAGER, ENGINEER, SALESMAN
}

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Role {
    Employee role();
}

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

// 动态代理
class AccessHandler implements InvocationHandler {
    private Object target;

    public AccessHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Role role = method.getAnnotation(Role.class);
        if (role != null && role.role() == Employee.MANAGER) {
            System.out.println("管理员权限校验通过");
        } else {
            throw new AccessDeniedException("权限不足");
        }
        return method.invoke(target, args);
    }
}

// 员工接口
interface EmployeeService {
    @Role(role = Employee.MANAGER)
    void manage() throws AccessDeniedException;
}

// 实现类
class EmployeeServiceImpl implements EmployeeService {
    @Override
    public void manage() {
        System.out.println("执行管理操作");
    }
}

public class Main {
    public static void main(String[] args) {
        EmployeeService service = (EmployeeService) Proxy.newProxyInstance(
                EmployeeServiceImpl.class.getClassLoader(),
                EmployeeServiceImpl.class.getInterfaces(),
                new AccessHandler(new EmployeeServiceImpl())
        );
        try {
            service.manage();
        } catch (AccessDeniedException e) {
            System.out.println(e.getMessage());
        }
    }
}

  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值