java快速学习速查(4)
尽快吧,这个毕竟得快点做完,本章是初级部分最后一篇了 主要内容为数组,日期时间,正则表达式,方法,构造方法,Stream和File和IO,scanner类,异常处理
Java 数组全面解析 数组是 Java 中存储固定大小同类型元素的数据结构。下面我将系统地讲解 Java 数组的各种功能和使用场景。
一、数组基础 1. 声明和初始化数组 1 2 3 4 5 6 7 8 int [] numbers1; int numbers2[]; int [] arr1 = new int [5 ]; int [] arr2 = {1 , 2 , 3 , 4 , 5 }; int [] arr3 = new int []{1 , 2 , 3 };
2. 访问数组元素 1 2 3 4 5 6 7 8 9 10 11 int [] numbers = {10 , 20 , 30 , 40 , 50 };int length = numbers.length; int first = numbers[0 ]; int last = numbers[numbers.length - 1 ]; numbers[1 ] = 25 ;
二、数组操作 1. 遍历数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int [] numbers = {1 , 2 , 3 , 4 , 5 };for (int i = 0 ; i < numbers.length; i++) { System.out.println(numbers[i]); } for (int num : numbers) { System.out.println(num); } System.out.println(Arrays.toString(numbers));
2. 数组复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int [] source = {1 , 2 , 3 , 4 , 5 };int [] dest1 = new int [5 ];System.arraycopy(source, 0 , dest1, 0 , source.length); int [] dest2 = Arrays.copyOf(source, source.length);int [] dest3 = source.clone();int [] dest4 = new int [source.length];for (int i = 0 ; i < source.length; i++) { dest4[i] = source[i]; }
3. 数组排序和搜索 1 2 3 4 5 6 7 8 9 10 int [] numbers = {5 , 3 , 9 , 1 , 7 };Arrays.sort(numbers); int index = Arrays.binarySearch(numbers, 5 ); Arrays.fill(numbers, 0 );
三、多维数组 1. 二维数组 1 2 3 4 5 6 7 8 9 10 11 12 int [][] matrix1 = new int [3 ][4 ]; int [][] matrix2 = {{1 , 2 }, {3 , 4 }, {5 , 6 }};int [][] irregular = new int [3 ][];irregular[0 ] = new int [2 ]; irregular[1 ] = new int [3 ]; irregular[2 ] = new int [1 ]; int value = matrix2[1 ][1 ];
2. 多维数组遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int [][] matrix = {{1 , 2 , 3 }, {4 , 5 , 6 }, {7 , 8 , 9 }};for (int i = 0 ; i < matrix.length; i++) { for (int j = 0 ; j < matrix[i].length; j++) { System.out.print(matrix[i][j] + " " ); } System.out.println(); } for (int [] row : matrix) { for (int num : row) { System.out.print(num + " " ); } System.out.println(); }
四、Arrays 工具类 1. 常用方法
方法
描述
示例
sort()
数组排序
Arrays.sort(arr)
binarySearch()
二分查找
Arrays.binarySearch(arr, key)
equals()
比较数组
Arrays.equals(arr1, arr2)
fill()
填充数组
Arrays.fill(arr, value)
copyOf()
复制数组
Arrays.copyOf(arr, newLength)
toString()
数组转字符串
Arrays.toString(arr)
asList()
数组转List
Arrays.asList(arr)
2. 使用示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Arrays;public class ArrayExample { public static void main (String[] args) { int [] numbers = {5 , 3 , 9 , 1 , 7 }; Arrays.sort(numbers); int index = Arrays.binarySearch(numbers, 5 ); int [] copy = Arrays.copyOf(numbers, numbers.length); boolean isEqual = Arrays.equals(numbers, copy); Arrays.fill(copy, 0 ); System.out.println(Arrays.toString(numbers)); } }
五、实际应用示例 1. 查找数组中的最大值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class ArrayMax { public static int findMax (int [] arr) { if (arr == null || arr.length == 0 ) { throw new IllegalArgumentException ("数组不能为空" ); } int max = arr[0 ]; for (int i = 1 ; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } public static void main (String[] args) { int [] numbers = {12 , 45 , 67 , 89 , 34 , 23 }; System.out.println("最大值: " + findMax(numbers)); } }
2. 数组反转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class ArrayReverse { public static void reverse (int [] arr) { for (int i = 0 , j = arr.length - 1 ; i < j; i++, j--) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } public static void main (String[] args) { int [] numbers = {1 , 2 , 3 , 4 , 5 }; System.out.println("原始数组: " + Arrays.toString(numbers)); reverse(numbers); System.out.println("反转后: " + Arrays.toString(numbers)); } }
3. 矩阵转置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class MatrixTranspose { public static int [][] transpose(int [][] matrix) { int rows = matrix.length; int cols = matrix[0 ].length; int [][] result = new int [cols][rows]; for (int i = 0 ; i < rows; i++) { for (int j = 0 ; j < cols; j++) { result[j][i] = matrix[i][j]; } } return result; } public static void main (String[] args) { int [][] matrix = {{1 , 2 , 3 }, {4 , 5 , 6 }}; System.out.println("原始矩阵:" ); printMatrix(matrix); int [][] transposed = transpose(matrix); System.out.println("转置矩阵:" ); printMatrix(transposed); } private static void printMatrix (int [][] matrix) { for (int [] row : matrix) { System.out.println(Arrays.toString(row)); } } }
六、注意事项与最佳实践
数组边界检查 :
1 2 int [] arr = new int [5 ];
数组长度固定 :
1 2 3 int [] arr = new int [5 ];
默认初始化值 :
数值类型:0
boolean:false
对象引用:null
数组与集合的选择 :
多维数组内存布局 :
1 2 3 4 5 int [][] arr = new int [3 ][];arr[0 ] = new int [2 ]; arr[1 ] = new int [3 ]; arr[2 ] = new int [4 ];
数组性能考虑 :
通过合理使用数组和Arrays工具类,可以高效地处理各种数据集合操作。对于固定大小的同类型数据集合,数组是最佳选择;对于需要动态调整大小的场景,应考虑使用Java集合框架中的类。
Java 日期时间全面解析 Java 提供了多种处理日期和时间的类,包括传统的 Date
、Calendar
和现代的 java.time
包(Java 8+)。下面我将系统地讲解 Java 日期时间处理的各种功能和使用场景。
一、传统日期时间类 1. Date 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Date;public class DateExample { public static void main (String[] args) { Date now = new Date (); System.out.println("当前时间: " + now); Date specificDate = new Date (1620000000000L ); System.out.println("特定时间: " + specificDate); System.out.println("now after specificDate? " + now.after(specificDate)); System.out.println("now before specificDate? " + now.before(specificDate)); System.out.println("now equals specificDate? " + now.equals(specificDate)); long timestamp = now.getTime(); System.out.println("时间戳: " + timestamp); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.text.SimpleDateFormat;import java.util.Date;public class DateFormatExample { public static void main (String[] args) { Date now = new Date (); SimpleDateFormat sdf1 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" ); SimpleDateFormat sdf2 = new SimpleDateFormat ("yyyy年MM月dd日 EEE a hh:mm:ss" ); System.out.println("格式1: " + sdf1.format(now)); System.out.println("格式2: " + sdf2.format(now)); try { String dateStr = "2023-05-15 14:30:00" ; Date parsedDate = sdf1.parse(dateStr); System.out.println("解析后的日期: " + parsedDate); } catch (Exception e) { e.printStackTrace(); } } }
3. Calendar 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.Calendar;import java.util.Date;public class CalendarExample { public static void main (String[] args) { Calendar calendar = Calendar.getInstance(); calendar.set(2023 , Calendar.MAY, 15 , 14 , 30 , 0 ); Date date = calendar.getTime(); System.out.println("设置的日期: " + date); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1 ; int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); System.out.printf("%d年%d月%d日 %d:%d\n" , year, month, day, hour, minute); calendar.add(Calendar.DAY_OF_MONTH, 7 ); calendar.add(Calendar.MONTH, -1 ); System.out.println("计算后的日期: " + calendar.getTime()); } }
二、Java 8 日期时间 API Java 8 引入了全新的日期时间 API (java.time
包),解决了传统类的各种问题。
1. 主要类介绍
类名
描述
LocalDate
只包含日期,不包含时间
LocalTime
只包含时间,不包含日期
LocalDateTime
包含日期和时间
ZonedDateTime
包含时区的日期和时间
Instant
时间戳(精确到纳秒)
Duration
时间段,以秒和纳秒为单位
Period
时间段,以年、月、日为单位
DateTimeFormatter
日期时间格式化类
2. 基本使用示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.time.*;import java.time.format.DateTimeFormatter;import java.time.temporal.ChronoUnit;public class Java8DateTime { public static void main (String[] args) { LocalDate currentDate = LocalDate.now(); LocalTime currentTime = LocalTime.now(); LocalDateTime currentDateTime = LocalDateTime.now(); System.out.println("当前日期: " + currentDate); System.out.println("当前时间: " + currentTime); System.out.println("当前日期时间: " + currentDateTime); LocalDate birthDate = LocalDate.of(1990 , Month.MAY, 15 ); LocalTime meetingTime = LocalTime.of(14 , 30 ); LocalDateTime projectDeadline = LocalDateTime.of(2023 , 12 , 31 , 23 , 59 ); LocalDate nextWeek = currentDate.plus(1 , ChronoUnit.WEEKS); LocalTime twoHoursLater = currentTime.plusHours(2 ); LocalDateTime yesterdaySameTime = currentDateTime.minusDays(1 ); System.out.println("今天在生日之后? " + currentDate.isAfter(birthDate)); System.out.println("现在在会议时间之前? " + currentTime.isBefore(meetingTime)); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss" ); String formattedDateTime = currentDateTime.format(formatter); System.out.println("格式化日期时间: " + formattedDateTime); LocalDateTime parsedDateTime = LocalDateTime.parse("2023/05/15 14:30:00" , formatter); System.out.println("解析后的日期时间: " + parsedDateTime); Period age = Period.between(birthDate, currentDate); System.out.printf("年龄: %d岁%d个月%d天\n" , age.getYears(), age.getMonths(), age.getDays()); Duration duration = Duration.between(meetingTime, currentTime); System.out.println("距离会议时间还有(秒): " + duration.getSeconds()); } }
三、实际应用示例 1. 计算两个日期之间的天数 1 2 3 4 5 6 7 8 9 10 11 12 import java.time.LocalDate;import java.time.temporal.ChronoUnit;public class DaysBetweenDates { public static void main (String[] args) { LocalDate startDate = LocalDate.of(2023 , 1 , 1 ); LocalDate endDate = LocalDate.of(2023 , 12 , 31 ); long daysBetween = ChronoUnit.DAYS.between(startDate, endDate); System.out.println("2023年有 " + daysBetween + " 天" ); } }
2. 判断闰年 1 2 3 4 5 6 7 8 9 10 11 12 import java.time.LocalDate;public class LeapYearCheck { public static void main (String[] args) { int [] years = {2000 , 2020 , 2023 , 2100 }; for (int year : years) { boolean isLeap = LocalDate.of(year, 1 , 1 ).isLeapYear(); System.out.println(year + " 年是闰年吗? " + isLeap); } } }
3. 工作时间计算器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.time.Duration;import java.time.LocalTime;import java.time.format.DateTimeFormatter;public class WorkingHoursCalculator { public static void main (String[] args) { DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm" ); LocalTime startTime = LocalTime.of(9 , 0 ); LocalTime endTime = LocalTime.of(18 , 30 ); LocalTime lunchStart = LocalTime.of(12 , 0 ); LocalTime lunchEnd = LocalTime.of(13 , 30 ); Duration morningWork = Duration.between(startTime, lunchStart); Duration afternoonWork = Duration.between(lunchEnd, endTime); Duration totalWork = morningWork.plus(afternoonWork); System.out.println("上午工作时间: " + morningWork.toHours() + "小时" + morningWork.toMinutesPart() + "分钟" ); System.out.println("下午工作时间: " + afternoonWork.toHours() + "小时" + afternoonWork.toMinutesPart() + "分钟" ); System.out.println("总工作时间: " + totalWork.toHours() + "小时" + totalWork.toMinutesPart() + "分钟" ); } }
四、注意事项与最佳实践
时区处理 :
1 2 3 4 5 ZonedDateTime beijingTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai" ));ZonedDateTime newYorkTime = beijingTime.withZoneSameInstant(ZoneId.of("America/New_York" ));System.out.println("北京时间: " + beijingTime); System.out.println("纽约时间: " + newYorkTime);
新旧API转换 :
1 2 3 4 5 6 7 8 9 10 Date legacyDate = new Date ();Instant instant = legacyDate.toInstant();Date newDate = Date.from(instant);Calendar calendar = Calendar.getInstance();LocalDateTime ldt = LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
日期格式化线程安全 :
1 2 3 4 5 public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd" );
性能考虑 :
对于高频率的日期操作,使用 java.time
包性能更好
避免在循环中重复创建格式化对象
日期验证 :
1 2 3 4 5 try { LocalDate.parse("2023-02-30" ); } catch (Exception e) { System.out.println("无效日期" ); }
时间精度 :
Instant
精确到纳秒
传统 Date
精确到毫秒
根据需求选择合适的时间精度
通过合理使用 Java 的日期时间 API,可以准确、高效地处理各种日期时间相关的业务需求。对于新项目,建议直接使用 Java 8 的 java.time
包;对于维护旧系统,可能需要与传统 API 交互。
Java 正则表达式全面解析 正则表达式是处理字符串的强大工具,Java 通过 java.util.regex
包提供了完整的正则表达式支持。下面我将系统地讲解 Java 中正则表达式的各种功能和使用场景。
一、正则表达式基础 1. Pattern 和 Matcher 类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import java.util.regex.*;public class RegexBasic { public static void main (String[] args) { String text = "Hello, my email is example@email.com and my phone is 123-456-7890" ; boolean isMatch = Pattern.matches(".*email.*" , text); System.out.println("Contains 'email'? " + isMatch); Pattern emailPattern = Pattern.compile("\\w+@\\w+\\.\\w+" ); Matcher emailMatcher = emailPattern.matcher(text); while (emailMatcher.find()) { System.out.println("Found email: " + emailMatcher.group()); } Pattern phonePattern = Pattern.compile("\\d{3}-\\d{3}-\\d{4}" ); Matcher phoneMatcher = phonePattern.matcher(text); if (phoneMatcher.find()) { System.out.println("Phone number: " + phoneMatcher.group()); } } }
2. 常用正则表达式元字符
元字符
描述
示例
.
匹配任意字符
a.c
匹配 “abc”, “a1c” 等
\d
数字 [0-9]
\d\d
匹配 “12”, “34” 等
\D
非数字 [^0-9]
\D\D
匹配 “ab”, “#$” 等
\w
单词字符 [a-zA-Z0-9_]
\w+
匹配单词
\W
非单词字符
\W
匹配 “@”, “!” 等
\s
空白字符 [ \t\n\x0B\f\r]
\s+
匹配空白
\S
非空白字符
\S+
匹配非空白序列
^
行开头
^Java
匹配行开头的 “Java”
$
行结尾
end$
匹配行结尾的 “end”
*
0次或多次
a*b
匹配 “b”, “ab”, “aab” 等
+
1次或多次
a+b
匹配 “ab”, “aab” 但不匹配 “b”
?
0次或1次
a?b
匹配 “b”, “ab”
{n}
恰好n次
a{3}
匹配 “aaa”
{n,}
至少n次
a{2,}
匹配 “aa”, “aaa” 等
{n,m}
n到m次
a{2,4}
匹配 “aa”, “aaa”, “aaaa”
二、分组与捕获 1. 捕获组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.util.regex.*;public class RegexGroups { public static void main (String[] args) { String dateStr = "2023-05-15, 1999-12-31" ; Pattern datePattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})" ); Matcher dateMatcher = datePattern.matcher(dateStr); while (dateMatcher.find()) { System.out.println("Full match: " + dateMatcher.group(0 )); System.out.println("Year: " + dateMatcher.group(1 )); System.out.println("Month: " + dateMatcher.group(2 )); System.out.println("Day: " + dateMatcher.group(3 )); } Pattern namedPattern = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})" ); Matcher namedMatcher = namedPattern.matcher(dateStr); while (namedMatcher.find()) { System.out.println("\nNamed groups:" ); System.out.println("Year: " + namedMatcher.group("year" )); System.out.println("Month: " + namedMatcher.group("month" )); System.out.println("Day: " + namedMatcher.group("day" )); } } }
2. 非捕获组 1 2 3 4 5 6 Pattern pattern = Pattern.compile("(?:Mr|Ms|Mrs)\\.\\s(\\w+)" );Matcher matcher = pattern.matcher("Mr. Smith and Ms. Doe" );while (matcher.find()) { System.out.println("Name: " + matcher.group(1 )); }
三、边界匹配与零宽断言 1. 边界匹配 1 2 3 4 5 6 7 8 9 10 11 Pattern wordBoundary = Pattern.compile("\\bcat\\b" );Matcher wbMatcher = wordBoundary.matcher("cat concatenate cat" );while (wbMatcher.find()) { System.out.println("Found at: " + wbMatcher.start()); } Pattern linePattern = Pattern.compile("^\\d+$" ); System.out.println("123 matches: " + linePattern.matcher("123" ).matches()); System.out.println("123a matches: " + linePattern.matcher("123a" ).matches());
2. 零宽断言 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Pattern positiveLookahead = Pattern.compile("\\w+(?=\\=)" );Matcher plaMatcher = positiveLookahead.matcher("key=value" );if (plaMatcher.find()) { System.out.println("Key before '=': " + plaMatcher.group()); } Pattern negativeLookahead = Pattern.compile("\\d{3}(?!-)" );Matcher nlaMatcher = negativeLookahead.matcher("123-456 789" );while (nlaMatcher.find()) { System.out.println("3 digits not followed by '-': " + nlaMatcher.group()); } Pattern positiveLookbehind = Pattern.compile("(?<=\\$)\\d+" );Matcher plbMatcher = positiveLookbehind.matcher("Price: $100" );if (plbMatcher.find()) { System.out.println("Number after '$': " + plbMatcher.group()); } Pattern negativeLookbehind = Pattern.compile("(?<!\\$)\\d+" );Matcher nlbMatcher = negativeLookbehind.matcher("Price: $100 200" );while (nlbMatcher.find()) { System.out.println("Number not after '$': " + nlbMatcher.group()); }
四、常用正则表达式示例 1. 验证电子邮件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class EmailValidator { private static final String EMAIL_REGEX = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@" + "(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$" ; public static boolean isValid (String email) { return Pattern.compile(EMAIL_REGEX).matcher(email).matches(); } public static void main (String[] args) { String[] emails = { "test@example.com" , "user.name@domain.co" , "invalid@.com" , "another@test" }; for (String email : emails) { System.out.println(email + ": " + isValid(email)); } } }
2. 提取URL 1 2 3 4 5 6 7 8 9 10 11 public class UrlExtractor { public static void main (String[] args) { String text = "Visit https://www.example.com or http://test.org for more info" ; Pattern urlPattern = Pattern.compile("https?://(?:[\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?" ); Matcher matcher = urlPattern.matcher(text); while (matcher.find()) { System.out.println("Found URL: " + matcher.group()); } } }
3. 密码强度验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class PasswordValidator { private static final String PASSWORD_REGEX = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$" ; public static boolean isValid (String password) { return Pattern.compile(PASSWORD_REGEX).matcher(password).matches(); } public static void main (String[] args) { String[] passwords = { "Weakpass1" , "Strong@Pass123" , "noSpecialChar1" , "Short1@" }; for (String pwd : passwords) { System.out.println(pwd + ": " + isValid(pwd)); } } }
五、高级用法 1. 替换操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class RegexReplacement { public static void main (String[] args) { String text = "User: john, Age: 30; User: jane, Age: 25" ; String replaced = text.replaceAll("\\d+" , "XX" ); System.out.println("After age masking: " + replaced); String nameReplaced = text.replaceAll("User: (\\w+)" , "Name: $1" ); System.out.println("After name format: " + nameReplaced); Pattern pattern = Pattern.compile("(\\w+): (\\w+)" ); Matcher matcher = pattern.matcher(text); StringBuffer sb = new StringBuffer (); while (matcher.find()) { String field = matcher.group(1 ); String value = matcher.group(2 ); String replacement = field.equals("Age" ) ? "**masked**" : value; matcher.appendReplacement(sb, field + ": " + replacement); } matcher.appendTail(sb); System.out.println("Selective masking: " + sb.toString()); } }
2. 分割字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class RegexSplit { public static void main (String[] args) { String text = "apple,orange,,banana;grape" ; String[] fruits1 = text.split("[,;]" ); System.out.println("Simple split: " + Arrays.toString(fruits1)); String[] fruits2 = text.split("[,;]+" ); System.out.println("No empty strings: " + Arrays.toString(fruits2)); Pattern pattern = Pattern.compile("[,;]" ); String[] fruits3 = pattern.split(text); System.out.println("Using Pattern.split: " + Arrays.toString(fruits3)); String[] fruits4 = text.split("[,;]" , 3 ); System.out.println("Limited split: " + Arrays.toString(fruits4)); } }
六、性能优化与最佳实践
预编译正则表达式 :
1 2 private static final Pattern EMAIL_PATTERN = Pattern.compile("your_email_regex" );
避免贪婪匹配 :
1 2 3 4 Pattern greedy = Pattern.compile("<.*>" ); Pattern reluctant = Pattern.compile("<.*?>" );
使用非捕获组提高性能 :
1 2 Pattern pattern = Pattern.compile("(?:Mr|Ms|Mrs)\\.\\s\\w+" );
边界匹配优化 :
1 2 Pattern exactMatch = Pattern.compile("^\\d{5}$" );
处理多行文本 :
1 2 3 4 5 6 7 Pattern multiLine = Pattern.compile("^\\w+" , Pattern.MULTILINE);String text = "first line\nsecond line\nthird line" ;Matcher m = multiLine.matcher(text);while (m.find()) { System.out.println("Line starts with: " + m.group()); }
异常处理 :
1 2 3 4 5 6 7 8 try { Pattern.compile("invalid[regex" ); } catch (PatternSyntaxException e) { System.out.println("Invalid regex: " + e.getMessage()); System.out.println("Description: " + e.getDescription()); System.out.println("Index: " + e.getIndex()); System.out.println("Pattern: " + e.getPattern()); }
通过合理使用 Java 的正则表达式功能,可以高效地处理各种复杂的字符串匹配、查找、替换和分割操作。
Java 方法全面解析 方法是 Java 编程中的基本构建块,用于封装可重用的代码逻辑。下面我将系统地讲解 Java 方法的各种功能和使用场景。
一、方法基础 1. 方法定义与调用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class MethodBasics { public static void greet () { System.out.println("Hello, World!" ); } public static void greetUser (String name) { System.out.println("Hello, " + name + "!" ); } public static int add (int a, int b) { return a + b; } public static double average (double ... numbers) { if (numbers.length == 0 ) return 0 ; double sum = 0 ; for (double num : numbers) { sum += num; } return sum / numbers.length; } public static void main (String[] args) { greet(); greetUser("Alice" ); int sum = add(5 , 3 ); System.out.println("5 + 3 = " + sum); double avg = average(1.5 , 2.5 , 3.5 ); System.out.println("Average: " + avg); } }
2. 方法参数传递 Java 中只有值传递(传递的是值的副本):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class ParameterPassing { public static void modifyPrimitive (int num) { num = 100 ; System.out.println("Inside method - primitive: " + num); } public static void modifyReference (StringBuilder sb) { sb.append(" World" ); System.out.println("Inside method - reference: " + sb); } public static void main (String[] args) { int x = 10 ; modifyPrimitive(x); System.out.println("After method - primitive: " + x); StringBuilder builder = new StringBuilder ("Hello" ); modifyReference(builder); System.out.println("After method - reference: " + builder); } }
二、方法重载 方法重载允许一个类中有多个同名方法,只要参数列表不同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class MethodOverloading { public static int max (int a, int b) { return a > b ? a : b; } public static double max (double a, double b) { return a > b ? a : b; } public static int max (int a, int b, int c) { return max(max(a, b), c); } public static void main (String[] args) { System.out.println("Max of 5 and 3: " + max(5 , 3 )); System.out.println("Max of 5.5 and 3.3: " + max(5.5 , 3.3 )); System.out.println("Max of 5, 3 and 7: " + max(5 , 3 , 7 )); } }
三、递归方法 方法调用自身称为递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Recursion { public static int factorial (int n) { if (n <= 1 ) return 1 ; return n * factorial(n - 1 ); } public static int fibonacci (int n) { if (n <= 1 ) return n; return fibonacci(n - 1 ) + fibonacci(n - 2 ); } public static void main (String[] args) { System.out.println("5! = " + factorial(5 )); System.out.println("Fibonacci(7) = " + fibonacci(7 )); } }
四、构造方法 构造方法用于初始化对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 public class Student { private String name; private int age; public Student () { this ("Unknown" , 18 ); } public Student (String name, int age) { this .name = name; this .age = age; } public Student (Student other) { this (other.name, other.age); } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } @Override public String toString () { return "Student{name='" + name + "', age=" + age + "}" ; } public static void main (String[] args) { Student s1 = new Student (); Student s2 = new Student ("Alice" , 20 ); Student s3 = new Student (s2); System.out.println(s1); System.out.println(s2); System.out.println(s3); } }
五、静态方法 vs 实例方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class MethodTypes { private int instanceVar = 10 ; private static int staticVar = 20 ; public void instanceMethod () { System.out.println("实例方法可以访问实例变量: " + instanceVar); System.out.println("实例方法可以访问静态变量: " + staticVar); } public static void staticMethod () { System.out.println("静态方法可以访问静态变量: " + staticVar); } public static void main (String[] args) { MethodTypes obj = new MethodTypes (); obj.instanceMethod(); MethodTypes.staticMethod(); staticMethod(); } }
六、方法最佳实践 1. 方法设计原则
单一职责原则 :一个方法只做一件事
合理命名 :方法名应准确描述其功能
适当长度 :通常不超过20-30行代码
参数数量控制 :最好不超过5个参数
避免副作用 :除非必要,方法不应修改传入参数
2. 方法文档注释 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static int gcd (int a, int b) throws IllegalArgumentException { if (a <= 0 || b <= 0 ) { throw new IllegalArgumentException ("参数必须为正整数" ); } while (b != 0 ) { int temp = b; b = a % b; a = temp; } return a; }
3. 实用方法示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import java.util.Arrays;public class UtilityMethods { public static boolean isPrime (int num) { if (num <= 1 ) return false ; if (num == 2 ) return true ; if (num % 2 == 0 ) return false ; for (int i = 3 ; i * i <= num; i += 2 ) { if (num % i == 0 ) return false ; } return true ; } public static <T> void reverseArray (T[] array) { for (int i = 0 ; i < array.length / 2 ; i++) { T temp = array[i]; array[i] = array[array.length - 1 - i]; array[array.length - 1 - i] = temp; } } public static int binarySearch (int [] array, int key) { int low = 0 ; int high = array.length - 1 ; while (low <= high) { int mid = (low + high) >>> 1 ; int midVal = array[mid]; if (midVal < key) { low = mid + 1 ; } else if (midVal > key) { high = mid - 1 ; } else { return mid; } } return -(low + 1 ); } public static void main (String[] args) { System.out.println("Is 17 prime? " + isPrime(17 )); Integer[] nums = {1 , 2 , 3 , 4 , 5 }; reverseArray(nums); System.out.println("Reversed array: " + Arrays.toString(nums)); int [] sorted = {2 , 5 , 8 , 12 , 16 , 23 , 38 , 56 , 72 , 91 }; int index = binarySearch(sorted, 23 ); System.out.println("Found 23 at index: " + index); } }
七、高级方法特性 1. 方法引用 (Java 8+) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.util.Arrays;import java.util.List;public class MethodReferences { public static void print (String s) { System.out.println(s); } public static void main (String[] args) { List<String> names = Arrays.asList("Alice" , "Bob" , "Charlie" ); names.forEach(MethodReferences::print); names.forEach(System.out::println); names.stream() .map(String::new ) .forEach(System.out::println); } }
2. 默认方法 (Java 8+) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public interface Vehicle { void start () ; default void stop () { System.out.println("Vehicle stopped" ); } static void honk () { System.out.println("Honk honk!" ); } } public class Car implements Vehicle { @Override public void start () { System.out.println("Car started" ); } public static void main (String[] args) { Car car = new Car (); car.start(); car.stop(); Vehicle.honk(); } }
Java I/O、Stream与异常处理全面解析 下面我将整合Java I/O流、文件操作和异常处理的核心知识,并提供实用的代码示例。
一、Java I/O 流体系 1. 流的基本分类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.io.*;import java.util.Scanner;public class IOOverview { public static void main (String[] args) { } }
2. 常用流类关系图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 字节流: InputStream |-- FileInputStream |-- FilterInputStream |-- BufferedInputStream |-- DataInputStream |-- ObjectInputStream OutputStream |-- FileOutputStream |-- FilterOutputStream |-- BufferedOutputStream |-- DataOutputStream |-- ObjectOutputStream |-- PrintStream 字符流: Reader |-- InputStreamReader |-- FileReader |-- BufferedReader Writer |-- OutputStreamWriter |-- FileWriter |-- BufferedWriter |-- PrintWriter
二、文件操作与Scanner 1. 文件基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.Scanner;public class FileOperations { public static void main (String[] args) { File file = new File ("test.txt" ); try { if (file.createNewFile()) { System.out.println("文件创建成功" ); } else { System.out.println("文件已存在" ); } System.out.println("文件路径: " + file.getAbsolutePath()); System.out.println("文件大小: " + file.length() + " bytes" ); } catch (IOException e) { e.printStackTrace(); } Path path = Paths.get("test.txt" ); try { if (!Files.exists(path)) { Files.createFile(path); } System.out.println("文件属性: " + Files.getAttribute(path, "basic:size" )); } catch (IOException e) { e.printStackTrace(); } try (Scanner scanner = new Scanner (path)) { while (scanner.hasNextLine()) { System.out.println(scanner.nextLine()); } } catch (IOException e) { e.printStackTrace(); } } }
2. Scanner类详解 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import java.util.Scanner;public class ScannerDemo { public static void main (String[] args) { Scanner scanner = new Scanner (System.in); System.out.print("请输入整数: " ); if (scanner.hasNextInt()) { int num = scanner.nextInt(); System.out.println("读取的整数: " + num); } else { System.out.println("输入的不是整数" ); } scanner.nextLine(); System.out.print("请输入一行文本: " ); String line = scanner.nextLine(); System.out.println("读取的行: " + line); System.out.print("请输入用逗号分隔的数据: " ); scanner.useDelimiter("," ); while (scanner.hasNext()) { System.out.println(scanner.next().trim()); } scanner.close(); } }
三、字节流与字符流操作 1. 字节流文件复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.io.*;public class ByteStreamCopy { public static void copyFile (String src, String dest) { try (InputStream in = new BufferedInputStream (new FileInputStream (src)); OutputStream out = new BufferedOutputStream (new FileOutputStream (dest))) { byte [] buffer = new byte [8192 ]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1 ) { out.write(buffer, 0 , bytesRead); } System.out.println("文件复制完成" ); } catch (IOException e) { e.printStackTrace(); } } public static void main (String[] args) { copyFile("source.jpg" , "destination.jpg" ); } }
2. 字符流读写文本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 import java.io.*;public class CharacterStreamDemo { public static void writeToFile (String filename, String content) { try (Writer writer = new BufferedWriter (new FileWriter (filename))) { writer.write(content); System.out.println("内容写入成功" ); } catch (IOException e) { e.printStackTrace(); } } public static String readFromFile (String filename) { StringBuilder content = new StringBuilder (); try (Reader reader = new BufferedReader (new FileReader (filename))) { char [] buffer = new char [1024 ]; int charsRead; while ((charsRead = reader.read(buffer)) != -1 ) { content.append(buffer, 0 , charsRead); } } catch (IOException e) { e.printStackTrace(); } return content.toString(); } public static void main (String[] args) { writeToFile("demo.txt" , "这是使用字符流写入的文本内容\n第二行内容" ); System.out.println("读取内容:\n" + readFromFile("demo.txt" )); } }
四、异常处理机制 1. 异常处理基础 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import java.io.*;public class ExceptionHandling { public static void checkedExceptionDemo () throws IOException { FileReader reader = new FileReader ("nonexistent.txt" ); reader.close(); } public static void uncheckedExceptionDemo () { int [] arr = new int [3 ]; System.out.println(arr[5 ]); } public static void main (String[] args) { try { checkedExceptionDemo(); } catch (FileNotFoundException e) { System.err.println("文件未找到: " + e.getMessage()); } catch (IOException e) { System.err.println("IO错误: " + e.getMessage()); } finally { System.out.println("finally块总是执行" ); } try (InputStream in = new FileInputStream ("test.txt" )) { System.out.println("文件打开成功" ); } catch (IOException e) { System.err.println("处理文件时出错: " + e.getMessage()); } try { validateAge(15 ); } catch (InvalidAgeException e) { System.err.println("年龄验证失败: " + e.getMessage()); } } static class InvalidAgeException extends Exception { public InvalidAgeException (String message) { super (message); } } public static void validateAge (int age) throws InvalidAgeException { if (age < 18 ) { throw new InvalidAgeException ("年龄必须大于18岁" ); } } }
2. 异常处理最佳实践 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import java.io.*;import java.nio.file.*;public class ExceptionBestPractices { public static void readFile (String filename) { try { String content = Files.readString(Path.of(filename)); System.out.println(content); } catch (NoSuchFileException e) { System.err.println("文件不存在: " + e.getFile()); } catch (AccessDeniedException e) { System.err.println("没有访问权限: " + e.getFile()); } catch (IOException e) { System.err.println("读取文件时发生错误: " + e.getMessage()); } } public static void processUserInput () { Scanner scanner = new Scanner (System.in); System.out.print("请输入数字: " ); try { int num = Integer.parseInt(scanner.nextLine()); System.out.println("输入的数字是: " + num); } catch (NumberFormatException e) { System.err.println("输入的不是有效数字" ); } finally { scanner.close(); } } public static void main (String[] args) { readFile("test.txt" ); processUserInput(); } }
五、综合应用示例 1. 文件加密解密工具 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import java.io.*;import java.util.Scanner;public class FileEncryptor { private static final int KEY = 0x55 ; public static void encryptFile (String inputFile, String outputFile) throws IOException { try (InputStream in = new BufferedInputStream (new FileInputStream (inputFile)); OutputStream out = new BufferedOutputStream (new FileOutputStream (outputFile))) { int data; while ((data = in.read()) != -1 ) { out.write(data ^ KEY); } } } public static void decryptFile (String inputFile, String outputFile) throws IOException { encryptFile(inputFile, outputFile); } public static void main (String[] args) { Scanner scanner = new Scanner (System.in); System.out.println("1. 加密文件" ); System.out.println("2. 解密文件" ); System.out.print("请选择操作: " ); try { int choice = Integer.parseInt(scanner.nextLine()); System.out.print("输入文件路径: " ); String input = scanner.nextLine(); System.out.print("输出文件路径: " ); String output = scanner.nextLine(); if (choice == 1 ) { encryptFile(input, output); System.out.println("文件加密完成" ); } else if (choice == 2 ) { decryptFile(input, output); System.out.println("文件解密完成" ); } else { System.out.println("无效选择" ); } } catch (NumberFormatException e) { System.err.println("请输入有效数字" ); } catch (FileNotFoundException e) { System.err.println("文件未找到: " + e.getMessage()); } catch (IOException e) { System.err.println("处理文件时出错: " + e.getMessage()); } finally { scanner.close(); } } }
2. 日志记录系统 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.io.*;import java.time.*;import java.util.*;public class LoggerSystem { private static final String LOG_FILE = "app.log" ; public enum LogLevel { INFO, WARNING, ERROR } public static void log (LogLevel level, String message) { String logEntry = String.format("[%s][%s] %s%n" , LocalDateTime.now(), level, message); try (FileWriter fw = new FileWriter (LOG_FILE, true ); BufferedWriter bw = new BufferedWriter (fw); PrintWriter out = new PrintWriter (bw)) { out.print(logEntry); } catch (IOException e) { System.err.println("记录日志失败: " + e.getMessage()); } } public static List<String> readLogs () { List<String> logs = new ArrayList <>(); try (Scanner scanner = new Scanner (new File (LOG_FILE))) { while (scanner.hasNextLine()) { logs.add(scanner.nextLine()); } } catch (FileNotFoundException e) { System.err.println("日志文件不存在" ); } return logs; } public static void main (String[] args) { log(LogLevel.INFO, "应用程序启动" ); log(LogLevel.WARNING, "内存使用量过高" ); log(LogLevel.ERROR, "数据库连接失败" ); System.out.println("日志内容:" ); readLogs().forEach(System.out::println); } }
六、关键知识点总结
I/O流选择原则 :
文本数据:优先使用字符流(Reader/Writer)
二进制数据:使用字节流(InputStream/OutputStream)
需要缓冲:包装Buffered系列流
Java 7+:优先使用NIO的Files和Paths工具类
异常处理要点 :
受检异常必须处理或声明抛出
非受检异常通常表示编程错误
使用try-with-resources自动管理资源
捕获异常时应从具体到抽象
不要忽略捕获的异常
Scanner使用技巧 :
读取不同类型数据使用hasNextXxx()/nextXxx()
注意处理换行符问题(nextLine与其他方法混用时)
使用useDelimiter()设置自定义分隔符
读取完毕后调用close()释放资源
性能优化建议 :
使用缓冲区减少I/O操作次数
合理设置缓冲区大小(通常8KB)
大文件处理使用流式而非全部加载到内存
及时关闭资源防止内存泄漏