方法是 Java 程式碼復用的基本單元。掌握方法的定義、重載、遞迴、可變參數及異常處理等核心技巧,能顯著提升程式碼品質。本文整理了從入門到進階的實戰範例,涵蓋基礎語法、常見工具類封裝、Java 8 函數式編程新特性等內容。
[修飾符] 返回值類型 方法名([參數列表]) [throws 異常列表] {
// 方法體
return 返回值; // void 類型可省略
}
Java 只有值傳遞。基本類型傳值副本;引用類型傳引用副本(指向同一堆對象)。
public void swapPrimitive(int a, int b) { /* 無法交換 */ }
public void swapObjectRef(MyObj a, MyObj b) { /* 無法交換引用指向 */ }
public void modifyObjectState(MyObj obj) { obj.setField("new"); /* 可修改對象內部狀態 */ }
public double average(double... numbers) {
if (numbers.length == 0) throw new IllegalArgumentException("至少需一個數值");
return Arrays.stream(numbers).average().orElse(0.0);
}
// 呼叫:average(1,2,3) 或 average(new double[]{1,2,3})
// 階乘(含尾遞迴優化建議)
public long factorial(int n) {
if (n < 0) throw new IllegalArgumentException();
return factTail(n, 1);
}
private long factTail(int n, long acc) {
return n == 0 ? acc : factTail(n - 1, n * acc);
}
// 檔案目錄深度遍歷
public void listFilesRecursive(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) listFilesRecursive(f);
else System.out.println(f.getAbsolutePath());
}
}
}
// 檢查型異常:強制調用者處理
public void readConfig(String path) throws IOException, ConfigParseException {
try (InputStream in = Files.newInputStream(Paths.get(path))) {
// 解析邏輯
} catch (IOException e) {
throw new ConfigParseException("配置讀取失敗", e); // 異常鏈保留原始堆疊
}
}
// 運算時異常:編程錯誤,不建議捕獲
public int divide(int a, int b) {
if (b == 0) throw new ArithmeticException("除數不能為零");
return a / b;
}
public final class StringUtils {
private StringUtils() {} // 防止實例化
public static boolean isBlank(CharSequence cs) {
return cs == null || cs.toString().trim().isEmpty();
}
public static String join(CharSequence delimiter, CharSequence... elements) {
return Stream.of(elements)
.filter(Objects::nonNull)
.map(CharSequence::toString)
.collect(Collectors.joining(delimiter));
}
// 更多:驗證手機/郵箱、脫敏、格式化等
}
public final class DateUtils {
private DateUtils() {}
public static String format(LocalDateTime dt, String pattern) {
return dt.format(DateTimeFormatter.ofPattern(pattern));
}
public static long daysBetween(LocalDate start, LocalDate end) {
return ChronoUnit.DAYS.between(start, end);
}
public static LocalDateTime startOfDay(LocalDate date) {
return date.atStartOfDay();
}
}
public final class CollectionUtils {
private CollectionUtils() {}
@SafeVarargs
public static <T> List<T> newArrayList(T... elements) {
return new ArrayList<>(Arrays.asList(elements));
}
public static <K, V> Map<K, V> toMap(List<V> list, Function<V, K> keyMapper) {
return list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(keyMapper, v -> v, (v1, v2) -> v1));
}
public static <T> boolean isEmpty(Collection<T> coll) {
return coll == null || coll.isEmpty();
}
}
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 方法引用替代 Lambda
names.forEach(System.out::println);
names.stream()
.filter(StringUtils::isNotBlank)
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
@FunctionalInterface
public interface DiscountStrategy {
BigDecimal calculate(BigDecimal originalPrice);
// 預設實現:無折扣
static DiscountStrategy none() {
return price -> price;
}
}
// 使用
DiscountStrategy vip = price -> price.multiply(new BigDecimal("0.8"));
DiscountStrategy holiday = price -> price.subtract(BigDecimal.TEN);
BigDecimal finalPrice = vip.calculate(BigDecimal.valueOf(100)); // 80
方法設計的藝術在於「高內聚、低耦合、語義清晰」。善用現代 Java 特性(Stream、Optional、Record、Pattern Matching),配合靜態分析工具,能寫出既優雅又高效的業務代碼。建議收藏本文作為開發速查手冊,持續精進工程化能力。