Java基础编程500题——阶段练习2

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

目录

1. 【正则表达式,日期API,异常】编写一个程序,使用正则表达式验证输入的字符串是否为合法的日期格式(如:yyyy-MM-dd),如果是,将其转换为日期对象并输出。

2. 【面向对象,注解,反射】定义一个注解@MethodInfo,包含一个String类型的字段description。使用反射获取一个类的所有方法,并输出带有@MethodInfo注解的方法描述。

3. 【文件,IO流,异常】在当前目录下创建一个"example.txt"文件,里面有5行,每行一个数字。然后编写一个程序,读取"example.txt",并将文件内容输出到控制台。如果文件不存在或读取过程中发生异常,请捕获异常并输出相应的错误信息。

4. 【多线程,动态代理】使用动态代理创建一个简单的线程安全的计数器代理,使用完一次计数器处理器要输出"计数器+1",并使用两个线程进行测试,每个线程增加计数器100次,最后输出计数器的最终值。

5. 【网络编程】编写一个简单的网络客户端程序,连接到本地服务器(例如,使用localhost和指定端口),并发送当前系统时间和用户输入的消息。服务器应回显消息,客户端打印服务器回显的消息。

6. 【线程,异常】编写一个程序,使用一个线程计算一个整数数组中所有元素的和。如果数组中包含负数,则抛出自定义异常NegativeNumberException,并在主线程中捕获该异常。

7. 【String,正则表达式】给定一个字符串数组,使用正则表达式找出所有包含手机号码的字符串,并将手机号码提取出来。

8. 【集合,Stream,String,正则表达式】给定一个字符串集合,使用Stream API和正则表达式过滤出所有包含电子邮箱地址的字符串。

9. 【Stream,正则表达式,动态代理】创建一个动态代理对象,该对象对字符串数组进行遍历,使用Stream API找出所有包含数字的字符串。

10. 【泛型,反射】编写一个泛型方法,该方法接受任意类的对象和一个字段名作为参数。方法应使用反射API来获取并输出该对象指定字段的值。

11. 【反射,注解,动态代理,日期和时间API】定义一个名为@TimeOrLog的注解,用于标记需要统计执行时间或者记录日志的方法。使用动态代理来拦截被注解标记的方法,并计算其执行时间或者记录日志。

12. 【面向对象,枚举类,多线程】请你使用枚举类实现一个基于角色(管理员、用户、访客)的并发访问控制,三个角色线程需要访问一个资源,资源只能被一个角色的线程访问。


✨✨  返回题目目录 ✨ ✨ 

Java基础编程500题


1. 【正则表达式,日期API,异常】编写一个程序,使用正则表达式验证输入的字符串是否为合法的日期格式(如:yyyy-MM-dd),如果是,将其转换为日期对象并输出。

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        if (str.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
            try {
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                LocalDate localDate = LocalDate.parse(str, dateTimeFormatter);
                System.out.println("输入的日期符合格式要求");
                System.out.println(localDate);
            } catch (DateTimeParseException e) {
                System.out.println("输入的日期不符合格式要求");
            }
        } else {
            System.out.println("输入的日期不符合格式要求");
        }
    }
}

2. 【面向对象,注解,反射】定义一个注解@MethodInfo,包含一个String类型的字段description。使用反射获取一个类的所有方法,并输出带有@MethodInfo注解的方法描述。

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

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

class MyClass {
    @MethodInfo(description = "这是第一个方法")
    void method1() {
        System.out.println("method1有注解");
    }

    @MethodInfo(description = "这是第二个方法")
    void method2() {
        System.out.println("method2有注解");
    }

    void method3() {
        System.out.println("method3没有注解");
    }
}

public class Main {
    public static void main(String[] args) {
        //获取一个类的所有信息
        Class<MyClass> myClassClass = MyClass.class;
        //获取这个类的所有方法信息
        Method[] declaredMethods = myClassClass.getDeclaredMethods();

        for (Method method : declaredMethods) {
            // 获取这个方法上的注解
            MethodInfo annotation = method.getAnnotation(MethodInfo.class);
            if (annotation != null) {
                System.out.println("方法名:" + method.getName() + ",描述:" + annotation.description());
            }
        }

    }
}

3. 【文件,IO流,异常】在当前目录下创建一个"example.txt"文件,里面有5行,每行一个数字。然后编写一个程序,读取"example.txt",并将文件内容输出到控制台。如果文件不存在或读取过程中发生异常,请捕获异常并输出相应的错误信息。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        // 使用 try-with-resources 语句自动关闭资源,避免了显示关闭资源
        try (FileReader fileReader = new FileReader("example.txt");
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            System.out.println("文件未找到:" + e.getMessage());
        } catch (IOException e) {
            System.out.println("读取文件时发生错误:" + e.getMessage());
        }
    }
}

4. 【多线程,动态代理】使用动态代理创建一个简单的线程安全的计数器代理,使用完一次计数器处理器要输出"计数器+1",并使用两个线程进行测试,每个线程增加计数器100次,最后输出计数器的最终值。

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

interface Counter {
    void increment();
    int getValue();
}

class CounterImpl implements Counter {
    private int value = 0;
    public synchronized void increment() {
        value++;
    }
    public int getValue() {
        return value;
    }
}

class CounterProxy implements InvocationHandler {
    private Counter counter; // 要代理的接口

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

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object invoke = method.invoke(counter, args);
        System.out.println("计数器+1");
        return invoke;
    }
}

public class Main {
    public static void main(String[] args) {
        Counter counter = new CounterImpl();
        Counter proxyCounter = (Counter) Proxy.newProxyInstance(
                Counter.class.getClassLoader(),
                new Class[]{Counter.class},
                new CounterProxy(counter)
        );

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                proxyCounter.increment();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                proxyCounter.increment();
            }
        });

        t1.start();
        t2.start();

        try { // 等待两个线程执行完毕
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            System.out.println("线程被中断:" + e.getMessage());
        }

        System.out.println("计数器的最终值为:" + proxyCounter.getValue());
    }
}

5. 【网络编程】编写一个简单的网络客户端程序,连接到本地服务器(例如,使用localhost和指定端口),并发送当前系统时间和用户输入的消息。服务器应回显消息,客户端打印服务器回显的消息。

Server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        int port = 12345;
        try (ServerSocket serverSocket = new ServerSocket(port);
             Socket clientSocket = serverSocket.accept();
             PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                System.out.println("客户端发送的消息:" + inputLine);
                out.println(inputLine); // Echo back to the client
            }
        }
    }
}

Client:

import java.io.*;
import java.net.Socket;
import java.time.LocalDateTime;

public class Client {
    public static void main(String[] args) {
        String host = "localhost";
        int port = 12345;
        try (Socket socket = new Socket(host, port);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {

            String userInput;
            System.out.println("请输入消息:");
            while ((userInput = stdIn.readLine()) != null) {
                out.println("当前时间:" + LocalDateTime.now() + ",用户输入:" + userInput);
                System.out.println("服务器回显:" + in.readLine());
            }
        } catch (IOException e) {
            System.out.println("网络通信发生异常:" + e.getMessage());
        }
    }
}

6. 【线程,异常】编写一个程序,使用一个线程计算一个整数数组中所有元素的和。如果数组中包含负数,则抛出自定义异常NegativeNumberException,并在主线程中捕获该异常。

import java.util.Arrays;

class NegativeNumberException extends Exception {
    NegativeNumberException(String message) {
        super(message);
    }
}

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

        int[] a = new int[100];
        Arrays.fill(a, 100);

        Thread thread = new Thread(() -> {
            int sum = 0;
            for (int i = 0; i < a.length; i++) {
                try {
                    if (a[i] < 0) {
                        throw new NegativeNumberException("数组中有负数");
                    } else {
                        sum += a[i];
                    }
                } catch (NegativeNumberException e) {
                    System.out.println("捕获到自定义异常:" + e.getMessage());
                } catch (Exception e) {
                    System.out.println("捕获到其他异常:" + e.getMessage());
                }
            }
            System.out.println(sum);

        });

        thread.start();

    }
}

7. 【String,正则表达式】给定一个字符串数组,使用正则表达式找出所有包含手机号码的字符串,并将手机号码提取出来。

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

public class Main {
    public static void main(String[] args) {
        String[] strs = {
                "我的电话不告诉你!",
                "我的电话是13888888888",
                "有空拨打我电话:13666666666"
        };

        Pattern pattern = Pattern.compile("(\\d{11})");
        //方法一
        for (String str : strs) {
            Matcher matcher = pattern.matcher(str);
            if (matcher.find()) {
                System.out.println("找到电话号码:" + matcher.group(1));
            }
        }

        //方法二
        Arrays.stream(strs)
                .map(pattern::matcher)
                .filter(Matcher::find)
                .map(matcher -> matcher.group(1))
                .forEach(phoneNumber -> System.out.println("找到电话号码:" +
phoneNumber));
    }
}

8. 【集合,Stream,String,正则表达式】给定一个字符串集合,使用Stream API和正则表达式过滤出所有包含电子邮箱地址的字符串。

import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> emails = List.of(
                "邮箱:example@qq.com",
                "这是一个测试字符串",
                "联系邮箱:test@163.com"
        );
        Pattern pattern = Pattern.compile("\\w+@\\w+\\.\\w+");
        List<String> collect = emails.stream()
                .filter(s -> pattern.matcher(s).find())
                .collect(Collectors.toList());
        System.out.println(collect);

    }
}

9. 【Stream,正则表达式,动态代理】创建一个动态代理对象,该对象对字符串数组进行遍历,使用Stream API找出所有包含数字的字符串。

import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

interface StringFilter {
    List<String> filter(String[] strs, Pattern pattern);
}

class StringFilterImpl implements StringFilter {
    @Override
    public List<String> filter(String[] strs, Pattern pattern) {
        List<String> collect = Arrays.stream(strs)
                .filter(s -> pattern.matcher(s).find())
                .collect(Collectors.toList());
        return collect;
    }
}

class StringProxy implements InvocationHandler {
    private StringFilter filter;
    public StringProxy(StringFilter filter) {
        this.filter = filter;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("filter")) {
            // 为filter进行代理
            Object invoke = method.invoke(filter, args);
            return invoke;
        }
        return null;
    }
}

public class Main {
    public static void main(String[] args) {
        StringFilter stringFilter = new StringFilterImpl();
        StringFilter proxyStringFilter = (StringFilter) Proxy.newProxyInstance(
                StringFilter.class.getClassLoader(),
                new Class[]{StringFilter.class},
                new StringProxy(stringFilter)
        );
        Pattern pattern = Pattern.compile(".*\\d.*");
        String[] strings = {"abc", "123", "def456", "ghi"};
        List<String> filter = proxyStringFilter.filter(strings, pattern);
        System.out.println(filter);
    }
}

10. 【泛型,反射】编写一个泛型方法,该方法接受任意类的对象和一个字段名作为参数。方法应使用反射API来获取并输出该对象指定字段的值。

import java.lang.reflect.Field;

class Person {
    private String name;
    private int age;

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

public class Main {
    public static void main(String[] args) {
        Person person = new Person("张三", 20);
        show(person, "name");
        show(person, "age");
    }

    public static <T> void show(T object, String fieldName) {
        Class<?> clz = object.getClass();
        try {
            Field field = clz.getDeclaredField(fieldName);
            field.setAccessible(true);
            System.out.println(fieldName + "字段的值是" + field.get(object));
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

11. 【反射,注解,动态代理,日期和时间API】定义一个名为@TimeOrLog的注解,用于标记需要统计执行时间或者记录日志的方法。使用动态代理来拦截被注解标记的方法,并计算其执行时间或者记录日志。

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface TimeOrLog {
    String value() default "";
}

interface Service {
    @TimeOrLog(value = "计算时间")
    public void sayHello();

    @TimeOrLog(value = "记录日志")
    public void sayBye();
}

class ServiceImpl implements Service {
    @Override
    @TimeOrLog(value = "计算时间")
    public void sayHello() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Hello");
    }

    @Override
    @TimeOrLog(value = "记录日志")
    public void sayBye() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Bye");
    }
}

class timeLogProxy implements InvocationHandler {
    private Service service;

    timeLogProxy(Service service) {
        this.service = service;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        TimeOrLog annotation = method.getAnnotation(TimeOrLog.class);
        if (annotation != null || !annotation.value().isEmpty()) {
            String value = annotation.value();
            String methodName = method.getName();
            if ("记录日志".equals(value)) {
                System.out.println("方法" + methodName + "开始执行");
                Object invoke = method.invoke(service, args);
                System.out.println("方法" + methodName + "执行结束");
                return invoke;
            } else if ("计算时间".equals(value)) {
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yy-MM-dd HH:mm:ss");
                LocalDateTime now = LocalDateTime.now();
                System.out.println(methodName + "执行于" + dateTimeFormatter.format(now));
                Object invoke = method.invoke(service, args);
                return invoke;
            }
        }
        return null;
    }
}


public class Main {
    public static void main(String[] args) {
        Service service = new ServiceImpl();
        Service serviceProxy = (Service) Proxy.newProxyInstance(
                Service.class.getClassLoader(),
                new Class[]{Service.class},
                new timeLogProxy(service)
        );
        System.out.println("==========================================");
        serviceProxy.sayHello();
        System.out.println("==========================================");
        serviceProxy.sayBye();
        System.out.println("==========================================");
    }
}

12. 【面向对象,枚举类,多线程】请你使用枚举类实现一个基于角色(管理员、用户、访客)的并发访问控制,三个角色线程需要访问一个资源,资源只能被一个角色的线程访问。

// 定义角色枚举
enum Role {
    ROLE_ADMIN("管理员"), ROLE_USER("用户"), ROLE_GUEST("访客");
    String name;

    Role(String name) {
        this.name = name;
    }

    String getName() {
        return name;
    }
}

// 资源类
class Resource {
    private final String name;

    public Resource(String name) {
        this.name = name; //资源的名字
    }

    public synchronized void access(Role role) {
        System.out.println(role.getName() + "正在访问" + name); //某个角色抢到了资源
    }
}

class GetResource implements Runnable {
    private Resource resource;
    private final Role role;

    GetResource(Resource resource, Role role) {
        this.resource = resource;
        this.role = role;
    }

    @Override
    public void run() {
        resource.access(role);
    }
}

public class Main {
    public static void main(String[] args) {
        // 创建资源
        Resource resource = new Resource("敏感数据");

        GetResource adminGetResource = new GetResource(resource, Role.ROLE_ADMIN);
        GetResource userGetResource = new GetResource(resource, Role.ROLE_USER);
        GetResource guestGetResource = new GetResource(resource, Role.ROLE_GUEST);

        Thread adminThread = new Thread(adminGetResource);
        Thread userThread = new Thread(userGetResource);
        Thread guestThread = new Thread(guestGetResource);

        adminThread.start();
        userThread.start();
        guestThread.start();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值