Introduction
Java 8+ allows static methods in interfaces. Java 9+ allows private methods in interfaces.
Static Methods in Interfaces
Static methods belong to the interface, not implementing classes.
Syntax:
interface MyInterface {
static returnType methodName() {
// Method body
}
}
Simple Static Method Example
interface MathUtils {
// Static method
static int add(int a, int b) {
return a + b;
}
static int multiply(int a, int b) {
return a * b;
}
}
public class Main {
public static void main(String[] args) {
// Call using interface name
int sum = MathUtils.add(10, 20);
int product = MathUtils.multiply(5, 6);
System.out.println("Sum: " + sum); // 30
System.out.println("Product: " + product); // 30
}
}
Key Features of Static Methods
- Belongs to interface, not implementing class
- Called using interface name:
InterfaceName.method() - Cannot be overridden by implementing classes
- Must have body (not abstract)
- Can be inherited but not overridden
Static Method Rules
interface Example {
static void staticMethod() {
System.out.println("Static method");
}
}
class MyClass implements Example {
// Cannot override static method
// static void staticMethod() { } // Not overriding!
}
public class Main {
public static void main(String[] args) {
// ✓ Correct - call with interface name
Example.staticMethod();
// ✗ Wrong - cannot call with object
// MyClass obj = new MyClass();
// obj.staticMethod(); // Error
// ✗ Wrong - cannot call with class name
// MyClass.staticMethod(); // Error
}
}
Private Methods in Interfaces
Private methods (Java 9+) help avoid code duplication in default/static methods.
Syntax:
interface MyInterface {
// Private method
private returnType methodName() {
// Method body
}
// Private static method
private static returnType staticMethodName() {
// Method body
}
}
Private Method Example
interface Calculator {
// Private method - helper for default methods
private void log(String message) {
System.out.println("LOG: " + message);
}
// Default methods using private method
default int add(int a, int b) {
log("Adding " + a + " and " + b);
return a + b;
}
default int subtract(int a, int b) {
log("Subtracting " + b + " from " + a);
return a - b;
}
}
class MyCalculator implements Calculator { }
public class Main {
public static void main(String[] args) {
Calculator calc = new MyCalculator();
System.out.println(calc.add(10, 5)); // LOG: Adding 10 and 5 \n 15
System.out.println(calc.subtract(10, 5)); // LOG: Subtracting 5 from 10 \n 5
}
}
Private Static Methods
Private static methods help static methods avoid code duplication.
interface StringUtils {
// Private static helper method
private static boolean isNullOrEmpty(String str) {
return str == null || str.isEmpty();
}
// Static methods using private static method
static String reverse(String str) {
if (isNullOrEmpty(str)) {
return str;
}
return new StringBuilder(str).reverse().toString();
}
static String toUpperCase(String str) {
if (isNullOrEmpty(str)) {
return str;
}
return str.toUpperCase();
}
}
public class Main {
public static void main(String[] args) {
System.out.println(StringUtils.reverse("hello")); // olleh
System.out.println(StringUtils.toUpperCase("world")); // WORLD
System.out.println(StringUtils.reverse(null)); // null
}
}
Complete Example: Validation Interface
interface Validator {
// Private method - common validation logic
private boolean isValidLength(String str, int minLength, int maxLength) {
if (str == null) return false;
int length = str.length();
return length >= minLength && length <= maxLength;
}
// Private static method - helper for static methods
private static void printError(String field, String message) {
System.out.println("Error in " + field + ": " + message);
}
// Default methods using private method
default boolean validateUsername(String username) {
if (!isValidLength(username, 3, 20)) {
System.out.println("Username must be 3-20 characters");
return false;
}
return true;
}
default boolean validatePassword(String password) {
if (!isValidLength(password, 8, 30)) {
System.out.println("Password must be 8-30 characters");
return false;
}
return true;
}
// Static methods using private static method
static boolean validateEmail(String email) {
if (email == null || !email.contains("@")) {
printError("Email", "Invalid format");
return false;
}
return true;
}
static boolean validatePhone(String phone) {
if (phone == null || phone.length() != 10) {
printError("Phone", "Must be 10 digits");
return false;
}
return true;
}
}
class UserValidator implements Validator { }
public class Main {
public static void main(String[] args) {
UserValidator validator = new UserValidator();
// Using default methods
System.out.println("Username valid: " + validator.validateUsername("john")); // true
System.out.println("Password valid: " + validator.validatePassword("pass")); // false
// Using static methods
System.out.println("Email valid: " + Validator.validateEmail("test@mail.com")); // true
System.out.println("Phone valid: " + Validator.validatePhone("123")); // false
}
}
Comparison Table
| Feature | Static Method | Private Method | Private Static Method |
|---|---|---|---|
| Since | Java 8 | Java 9 | Java 9 |
| Access | Public | Private | Private |
| Call from | Outside interface | Inside interface only | Inside interface only |
| Body | Required | Required | Required |
| Can be overridden | No | No | No |
| Used by | Anyone | Default methods | Static methods |
| Call syntax | Interface.method() | this.method() | method() |
Real-World Example: Logger Interface
interface Logger {
// Private static method - formatting helper
private static String formatMessage(String level, String message) {
return "[" + level + "] " + java.time.LocalTime.now() + " - " + message;
}
// Private method - actual logging implementation
private void writeLog(String formattedMessage) {
System.out.println(formattedMessage);
}
// Default methods using private methods
default void info(String message) {
String formatted = formatMessage("INFO", message);
writeLog(formatted);
}
default void error(String message) {
String formatted = formatMessage("ERROR", message);
writeLog(formatted);
}
default void warning(String message) {
String formatted = formatMessage("WARNING", message);
writeLog(formatted);
}
// Static utility method
static void logSystemInfo() {
System.out.println(formatMessage("SYSTEM", "Java version: " + System.getProperty("java.version")));
}
}
class ApplicationLogger implements Logger { }
public class Main {
public static void main(String[] args) {
Logger logger = new ApplicationLogger();
logger.info("Application started");
logger.warning("Low memory");
logger.error("Connection failed");
Logger.logSystemInfo();
}
}
Benefits
Static Methods:
- Utility methods in interface
- No need for separate utility class
- Related functionality stays together
- Factory methods for creating objects
Private Methods:
- Code reuse in default methods
- Avoid duplication in interface
- Encapsulation of helper logic
- Clean code organization
Static Method Use Cases
interface Shape {
double area();
// Static factory method
static Shape createCircle(double radius) {
return new Circle(radius);
}
static Shape createRectangle(double length, double width) {
return new Rectangle(length, width);
}
// Static utility method
static void printShapeInfo(Shape shape) {
System.out.println("Area: " + shape.area());
}
}
class Circle implements Shape {
private double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class Rectangle implements Shape {
private double length, width;
Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}
public class Main {
public static void main(String[] args) {
// Using static factory methods
Shape circle = Shape.createCircle(5);
Shape rectangle = Shape.createRectangle(4, 6);
// Using static utility method
Shape.printShapeInfo(circle);
Shape.printShapeInfo(rectangle);
}
}
Private Method Use Cases
interface DataProcessor {
// Private validation helper
private boolean isValid(String data) {
return data != null && !data.isEmpty();
}
// Private transformation helper
private String transform(String data) {
return data.trim().toUpperCase();
}
// Default methods using private helpers
default void process(String data) {
if (!isValid(data)) {
System.out.println("Invalid data");
return;
}
String processed = transform(data);
System.out.println("Processed: " + processed);
}
default void processMultiple(String... dataArray) {
for (String data : dataArray) {
if (isValid(data)) {
System.out.println(transform(data));
}
}
}
}
class MyProcessor implements DataProcessor { }
public class Main {
public static void main(String[] args) {
DataProcessor processor = new MyProcessor();
processor.process(" hello "); // HELLO
processor.processMultiple(" java ", " python "); // JAVA \n PYTHON
}
}
Method Access Rules
interface Example {
// Private method - accessible only within this interface
private void privateMethod() {
System.out.println("Private");
}
// Private static method - accessible only within this interface
private static void privateStaticMethod() {
System.out.println("Private static");
}
// Default method - can call private methods
default void defaultMethod() {
privateMethod(); // ✓ OK
privateStaticMethod(); // ✓ OK
}
// Static method - can call only private static methods
static void staticMethod() {
// privateMethod(); // ✗ Error - cannot call instance private
privateStaticMethod(); // ✓ OK
}
}
Common Patterns
1. Factory Pattern:
interface Product {
void create();
static Product getInstance(String type) {
if ("A".equals(type)) {
return new ProductA();
}
return new ProductB();
}
}
2. Validation Pattern:
interface Validator {
private boolean commonValidation(String data) {
return data != null && data.length() > 0;
}
default boolean validate(String data) {
return commonValidation(data);
}
}
3. Utility Pattern:
interface Utils {
static void print(String message) {
System.out.println(message);
}
}
Quick Reference
interface MyInterface {
// Static method (Java 8+)
static void staticMethod() {
System.out.println("Static");
}
// Private method (Java 9+)
private void privateMethod() {
System.out.println("Private");
}
// Private static method (Java 9+)
private static void privateStaticMethod() {
System.out.println("Private static");
}
// Default method using private
default void defaultMethod() {
privateMethod();
}
// Static method using private static
static void anotherStatic() {
privateStaticMethod();
}
}
// Usage
MyInterface.staticMethod(); // Call static
MyInterface obj = new MyClass();
obj.defaultMethod(); // Calls private internally
Common Mistakes
interface Example {
private void privateMethod() { }
static void staticMethod() {
// ✗ Cannot call instance private from static
// privateMethod(); // Error
}
}
class MyClass implements Example {
// ✗ Cannot access private methods from implementing class
void test() {
// privateMethod(); // Error - not visible
}
// ✗ Cannot override static methods
// static void staticMethod() { } // Not overriding!
}
Exam Tips
Remember:
- Static methods since Java 8
- Private methods since Java 9
- Static called with interface name
- Private only inside interface
- Private helps avoid duplication
- Static cannot be overridden
- Private instance from default methods
- Private static from static methods
- Must have method body
- Used for utility and helper methods
Common Questions:
- When were static methods added?
- When were private methods added?
- How to call static interface method?
- Can static methods be overridden?
- Purpose of private methods?
- Difference: private vs private static?
- Can private methods be accessed in implementing class?
- Benefits of static methods in interface?
- Use cases for private methods?
- Can static method call private instance method?