💥 该系列属于【Java基础编程500题】专栏,如您需查看Java基础的其他相关题目,请您点击左边的连接
目录
1. 【正则表达式,日期API,异常】编写一个程序,使用正则表达式验证输入的字符串是否为合法的日期格式(如:yyyy-MM-dd),如果是,将其转换为日期对象并输出。
2. 【面向对象,注解,反射】定义一个注解@MethodInfo,包含一个String类型的字段description。使用反射获取一个类的所有方法,并输出带有@MethodInfo注解的方法描述。
4. 【多线程,动态代理】使用动态代理创建一个简单的线程安全的计数器代理,使用完一次计数器处理器要输出"计数器+1",并使用两个线程进行测试,每个线程增加计数器100次,最后输出计数器的最终值。
5. 【网络编程】编写一个简单的网络客户端程序,连接到本地服务器(例如,使用localhost和指定端口),并发送当前系统时间和用户输入的消息。服务器应回显消息,客户端打印服务器回显的消息。
6. 【线程,异常】编写一个程序,使用一个线程计算一个整数数组中所有元素的和。如果数组中包含负数,则抛出自定义异常NegativeNumberException,并在主线程中捕获该异常。
7. 【String,正则表达式】给定一个字符串数组,使用正则表达式找出所有包含手机号码的字符串,并将手机号码提取出来。
8. 【集合,Stream,String,正则表达式】给定一个字符串集合,使用Stream API和正则表达式过滤出所有包含电子邮箱地址的字符串。
9. 【Stream,正则表达式,动态代理】创建一个动态代理对象,该对象对字符串数组进行遍历,使用Stream API找出所有包含数字的字符串。
10. 【泛型,反射】编写一个泛型方法,该方法接受任意类的对象和一个字段名作为参数。方法应使用反射API来获取并输出该对象指定字段的值。
11. 【反射,注解,动态代理,日期和时间API】定义一个名为@TimeOrLog的注解,用于标记需要统计执行时间或者记录日志的方法。使用动态代理来拦截被注解标记的方法,并计算其执行时间或者记录日志。
12. 【面向对象,枚举类,多线程】请你使用枚举类实现一个基于角色(管理员、用户、访客)的并发访问控制,三个角色线程需要访问一个资源,资源只能被一个角色的线程访问。
✨✨ 返回题目目录 ✨ ✨
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();
}
}