Java 8中接口方法与类方法有何差异?如何实现字符串掩码?
Great question! Let's break this down into two clear parts: first, the differences between interface methods (static ones, as shown in your example) and class methods in Java 8, then multiple practical implementations of string masking—including a completed version of the interface snippet you provided.
The biggest distinctions revolve around inheritance, accessibility, and intended use:
- Interface Static Methods (Java 8+): These are utility methods tied directly to the interface. You don't need an instance of an implementing class to call them, and they cannot be overridden by implementing classes. They're meant to provide helper logic related to the interface's contract, but implementing classes don't inherit them—you must call them using the interface name (e.g.,
StringUtil.maskString(...)). - Class Static Methods: These belong to the class itself, are accessible via the class name, and can be inherited by subclasses (though subclasses can "hide" them by defining a static method with the same signature). They're the traditional way to create utility functions in Java.
- Key Takeaway: Interface static methods are scoped strictly to the interface, while class static methods are part of the class hierarchy. For pure utility logic, a class is often more intuitive, but Java 8 allows interfaces to include static helpers for completeness.
Let's look at several ways to implement string masking, starting with your interface example.
1. Interface Static Method (Completed)
Your original code was missing the final step of building the masked string. Here's the full, functional version:
import org.apache.commons.lang3.StringUtils; public interface StringUtil { static String maskString(String strText, int start, int end, char maskChar) throws Exception { if (StringUtils.isNullOrEmpty(strText)) return ""; // Adjust bounds to stay within valid range if (start < 0) start = 0; if (end > strText.length()) end = strText.length(); // Validate logical bounds if (start > end) throw new IllegalArgumentException("End index cannot be less than start index"); int maskLength = end - start; if (maskLength == 0) return strText; // Create masked segment and combine with original string parts String mask = StringUtils.repeat(maskChar, maskLength); return strText.substring(0, start) + mask + strText.substring(end); } }
Note: We use StringUtils from Apache Commons Lang for easy string repetition, but you could implement this manually with a StringBuilder if you don't want external dependencies.
2. Class Static Method (Traditional Utility)
For most utility scenarios, a dedicated class is more commonly used than an interface. Here's an equivalent implementation:
public class StringMasker { public static String maskString(String strText, int start, int end, char maskChar) { if (strText == null || strText.isEmpty()) return ""; // Safely adjust bounds int adjustedStart = Math.max(0, start); int adjustedEnd = Math.min(strText.length(), end); if (adjustedStart >= adjustedEnd) return strText; // Build mask manually with StringBuilder StringBuilder maskBuilder = new StringBuilder(); for (int i = 0; i < adjustedEnd - adjustedStart; i++) { maskBuilder.append(maskChar); } return strText.substring(0, adjustedStart) + maskBuilder + strText.substring(adjustedEnd); } }
This avoids exceptions by gracefully adjusting bounds, and uses a StringBuilder to create the mask without external libraries.
3. Configurable Instance Method
If you need to reuse masking settings (like a default mask character), an instance method is ideal:
public class ConfigurableMasker { private final char defaultMask; public ConfigurableMasker(char defaultMask) { this.defaultMask = defaultMask; } // Overloaded method for using default mask public String mask(String text, int start, int end) { return mask(text, start, end, defaultMask); } public String mask(String text, int start, int end, char maskChar) { if (text == null || text.isEmpty()) return ""; int adjustedStart = Math.max(0, start); int adjustedEnd = Math.min(text.length(), end); if (adjustedStart >= adjustedEnd) return text; // Modify the string directly with StringBuilder StringBuilder maskedText = new StringBuilder(text); for (int i = adjustedStart; i < adjustedEnd; i++) { maskedText.setCharAt(i, maskChar); } return maskedText.toString(); } }
This lets you create a masker instance with a default character (e.g., *) and reuse it across your codebase.
内容的提问来源于stack exchange,提问作者NoobEditor

