Skip to content

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.