Java – Naming Conventions
Clear, consistent naming is the single most impactful thing you can do for long-term code readability. Every name in a Java codebase is a communication act — it tells the reader what something is, what it does, and how it should be used.
Quick Reference
| Element | Convention | Example |
|---|---|---|
| Class / Interface / Enum | PascalCase | OrderService, PaymentProcessor, UserStatus |
| Abstract class | PascalCase, prefix Abstract |
AbstractRepository, AbstractValidator |
| Interface | PascalCase, no I prefix |
UserRepository, PaymentGateway |
| Method | camelCase, verb-first | getUserById(), calculateTotal(), isActive() |
| Variable | camelCase | userName, totalAmount, isConfirmed |
| Constant | UPPER_SNAKE_CASE |
MAX_RETRY_COUNT, DEFAULT_TIMEOUT_MS |
| Package | lowercase, dotted reverse-domain | com.cygnus.order.service |
| Enum value | UPPER_SNAKE_CASE |
OrderStatus.PENDING, PaymentMethod.CARD |
| Generic type parameter | Single uppercase letter | T, E, K, V, R |
| Test class | PascalCase, suffix Test |
OrderServiceTest, UserRepositoryTest |
| DTO (request) | PascalCase, suffix Request |
CreateOrderRequest, UpdateUserRequest |
| DTO (response) | PascalCase, suffix Response |
OrderResponse, UserSummaryResponse |
| Exception | PascalCase, suffix Exception |
OrderNotFoundException, PaymentFailedException |
Classes and Interfaces
Classes
Class names must be nouns or noun phrases — never verbs. A class name should answer "what is this thing?"
// ✅ Correct — nouns describing what the class represents
public class OrderService { }
public class PaymentProcessor { }
public class UserRepository { }
public class ShippingAddress { }
// ❌ Incorrect — verbs, vague names, or cryptic abbreviations
public class ProcessOrder { } // verb — should be a method name, not a class
public class Manager { } // too vague — manager of what?
public class OrdSvc { } // abbreviation — adds no clarity
public class Helper { } // meaningless — what does it help with?
public class Util { } // never acceptable as a class name
Interfaces
Interfaces should be named for the capability or contract they represent — never with an I prefix (this is a C# convention, not Java).
// ✅ Correct — describes the contract or capability
public interface UserRepository { }
public interface PaymentGateway { }
public interface Auditable { } // -able suffix for capability interfaces
public interface EventPublisher { }
// ❌ Incorrect — I prefix (C# convention, not Java)
public interface IUserRepository { }
public interface IPaymentGateway { }
Abstract classes
Abstract classes use the Abstract prefix to make their nature explicit.
// ✅ Correct
public abstract class AbstractRepository<T, ID> { }
public abstract class AbstractValidator<T> { }
public abstract class BaseEntity { } // Base prefix also acceptable
// ❌ Incorrect — no indication it is abstract from the name alone
public abstract class Repository<T, ID> { }
Methods
Method names must begin with a verb that describes the action. The verb should be precise — prefer calculate over get when computation is involved, and validate over check when an error may be thrown.
Common verb conventions
| Verb | When to use |
|---|---|
get / find |
Retrieve data. get for required lookups (throws if absent), find for optional lookups (returns Optional) |
create / build |
Construct and return a new object |
save / persist |
Write to a store |
update / patch |
Modify an existing record |
delete / remove |
Remove a record |
calculate / compute |
Perform a computation and return a result |
validate / verify |
Check correctness; throws an exception if invalid |
is / has / can |
Return a boolean |
send / publish / dispatch |
Trigger an external action |
handle / process |
Orchestrate a workflow |
// ✅ Correct — precise verbs
public User getUserById(Long id) { } // throws if not found
public Optional<User> findUserByEmail(String email) { } // returns Optional
public Order createOrder(CreateOrderRequest req) { }
public BigDecimal calculateOrderTotal(List<OrderItem> items) { }
public void validatePaymentMethod(PaymentMethod method) { }
public boolean isEligibleForDiscount(User user) { }
public boolean hasActiveSubscription(Long userId) { }
public void sendOrderConfirmationEmail(Order order) { }
// ❌ Incorrect
public User fetchUser(Long id) { } // fetch is vague — use get or find
public boolean checkDiscount(User u) { } // check is ambiguous — use is/has
public void doPayment(Order o) { } // do conveys nothing
public void handleIt() { } // it — what is it?
Boolean methods
Boolean methods must read as a natural true/false question.
// ✅ Correct — reads naturally as a predicate
boolean isActive()
boolean hasExpired()
boolean canProcessRefund()
boolean isEmpty()
boolean wasDelivered()
// ❌ Incorrect — does not read as a question
boolean active()
boolean expired()
boolean refundable()
Variables
Variables should be descriptive enough that the reader understands the value without tracing its origin. Single-letter variables are only acceptable as loop counters and in very short lambda expressions.
// ✅ Correct
Long orderId = request.getOrderId();
List<OrderItem> eligibleItems = filterEligibleItems(order.getItems());
BigDecimal discountedTotal = applyDiscount(subtotal, discountRate);
boolean isFirstOrder = orderRepository.countByUser(user) == 0;
// ❌ Incorrect — meaningless or abbreviated
Long id = request.getOrderId(); // id of what? There may be many IDs
List<OrderItem> items2 = filterEligibleItems(order.getItems());
BigDecimal dt = applyDiscount(subtotal, discountRate);
boolean flag = orderRepository.countByUser(user) == 0;
Loop variables:
// ✅ Acceptable — i is conventional for numeric loops
for (int i = 0; i < items.size(); i++) { }
// ✅ Preferred — descriptive variable in for-each
for (OrderItem item : order.getItems()) {
inventoryService.reserve(item);
}
// ✅ Lambda — single letter acceptable in short, obvious lambdas
items.stream()
.filter(item -> item.isInStock())
.map(item -> item.getProductId())
.collect(Collectors.toList());
Constants
Constants are declared as static final and named in UPPER_SNAKE_CASE. Every constant that is not self-explanatory must include a comment stating the reason for the value.
// ✅ Correct — name explains the meaning, comment explains the why
public class OrderLimits {
public static final int MAX_ITEMS_PER_ORDER = 100;
public static final int MAX_RETRY_ATTEMPTS = 3;
public static final long SESSION_TIMEOUT_MS = 30 * 60 * 1000L; // 30 minutes — per policy SEC-12
private OrderLimits() { } // prevent instantiation — utility constant class
}
// ❌ Incorrect — magic number with no name, unclear value
if (order.getItems().size() > 100) { }
if (retryCount > 3) { }
Packages
Package names are always lowercase, use the reverse domain convention, and are organised by feature domain (not technical layer).
// ✅ Correct — feature-domain organisation
com.cygnus.order.domain
com.cygnus.order.service
com.cygnus.order.repository
com.cygnus.order.api
com.cygnus.payment.domain
com.cygnus.payment.service
// ❌ Incorrect — layer-first organisation (hard to navigate in large codebases)
com.cygnus.services // all services from all domains mixed together
com.cygnus.repositories
com.cygnus.controllers
// ❌ Incorrect — uppercase or mixed case
com.cygnus.Order.Service
com.Cygnus.payment
Enums
Enum types use PascalCase. Enum values use UPPER_SNAKE_CASE.
// ✅ Correct
public enum OrderStatus {
PENDING,
CONFIRMED,
SHIPPED,
DELIVERED,
CANCELLED
}
public enum PaymentMethod {
CREDIT_CARD,
DEBIT_CARD,
BANK_TRANSFER,
CRYPTO
}
// Usage
if (order.getStatus() == OrderStatus.CANCELLED) {
processRefund(order);
}
// ❌ Incorrect
public enum orderStatus { pending, confirmed } // wrong case on both
public enum OrderStatus { Pending, Confirmed } // Pascal on values — wrong
Generics
Generic type parameters use a single uppercase letter. Follow these conventions:
| Parameter | Meaning |
|---|---|
T |
General type |
E |
Element (collections) |
K |
Key (maps) |
V |
Value (maps) |
R |
Return type |
N |
Number |
// ✅ Correct
public interface Repository<T, ID> {
Optional<T> findById(ID id);
T save(T entity);
List<T> findAll();
}
public <T, R> R transform(T input, Function<T, R> mapper) {
return mapper.apply(input);
}
// ❌ Incorrect — verbose or unclear type names
public interface Repository<Entity, Identifier> { } // too verbose for generic params
public <Input, Output> Output transform(Input i, Function<Input, Output> f) { }
DTOs — Request and Response Objects
DTOs follow strict naming conventions to distinguish them from domain objects:
// ✅ Correct — Request suffix for inbound data
public class CreateOrderRequest {
private Long userId;
private List<OrderItemRequest> items;
private String couponCode;
}
public class UpdateUserRequest {
private String firstName;
private String lastName;
private String phoneNumber;
}
// ✅ Correct — Response suffix for outbound data
public class OrderResponse {
private Long id;
private String status;
private BigDecimal total;
private List<OrderItemResponse> items;
}
public class UserSummaryResponse {
private Long id;
private String fullName;
private String email;
}
// ❌ Incorrect — no suffix, ambiguous whether domain or DTO
public class Order { } // is this the domain entity or the DTO?
public class UserDto { } // Dto suffix is acceptable but less precise than Response/Request
Test Classes and Methods
Test class names mirror the class under test with a Test suffix. Test method names follow the method_whenCondition_shouldBehavior pattern defined in the Testing Standards.
// ✅ Correct — class name
class OrderServiceTest { }
class UserRepositoryTest { }
class PaymentProcessorIntegrationTest { } // Integration suffix for integration tests
// ✅ Correct — method names
@Test
void calculateTotal_whenItemsAreEmpty_shouldReturnZero() { }
@Test
void processPayment_whenCardIsDeclined_shouldThrowPaymentFailedException() { }
@Test
void getOrderById_whenOrderDoesNotExist_shouldThrowOrderNotFoundException() { }
// ❌ Incorrect — vague or unnamed
@Test
void test1() { }
@Test
void testCalculate() { }
@Test
void itWorks() { }
Tooling
Naming conventions are enforced automatically. Configure these tools in every Java project:
| Tool | Purpose | Command |
|---|---|---|
| Checkstyle | Enforces naming rules, import order, Javadoc presence | mvn checkstyle:check |
| Google Java Format | Auto-formats code to Google style (4-space indent, line length) | mvn com.spotify.fmt:fmt-maven-plugin:format |
| SpotBugs | Static analysis — finds bugs including null pointer risks | mvn spotbugs:check |
| PMD | Additional static analysis — unused variables, empty catch blocks | mvn pmd:check |
The Checkstyle configuration file (checkstyle.xml) must be committed to the root of every Java repository. Do not disable rules locally without Tech Lead approval.