Apex Variable Declaration & Data Types: Complete Guide | SalesforceTutorial

Written by Prasanth Kumar Published on Updated on

Apex variables form the foundation of Salesforce development. This guide covers variable declaration syntax, data type specifications, naming conventions, and practical implementation patterns used in production Salesforce orgs.

What is Apex Variable Declaration?

Apex is a strongly typed language, requiring all variables to be declared with explicit data types before use. Variable declaration follows the pattern: DataType variableName;

Example: Integer i; (Integer = Data Type, i = variable name)

Variable Declaration Syntax

// Basic variable declaration
String accountName;
Integer recordCount;
Boolean isActive;

// Declaration with initialization
String companyName = 'Salesforce';
Integer maxRecords = 50000;
Date todayDate = Date.today();

Apex Variable Naming Rules and Best Practices

Salesforce enforces specific naming conventions for Apex variables:

  • Variable names cannot start with numeric values or symbols
  • Avoid underscore (_) prefixes or suffixes
  • Cannot use Apex reserved words (class, public, static, etc.)
  • Case-insensitive but follow camelCase convention
  • Use descriptive names that indicate purpose

Valid and Invalid Variable Names

// Valid variable names
String firstName;
Integer accountCount;
List<Contact> activeContacts;
Map<Id, Account> accountMap;

// Invalid variable names
// String 1stName;        // starts with number
// Integer _count;        // starts with underscore
// Boolean class;         // reserved word
// String account-name;   // contains hyphen

Complete Apex Data Types Reference

Apex supports primitive data types, collections, and sObject types. Each data type has specific memory allocation and governor limit implications.

Data Type Valid Values Memory Usage
String Unicode characters, null values Variable based on length
Boolean true, false, null 1 bit
Date Date values (YYYY-MM-DD) 8 bytes
DateTime Date and time with timezone 8 bytes
Time Time values (HH:MM:SS.mmm) 4 bytes
Integer -2,147,483,648 to 2,147,483,647 4 bytes
Long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 8 bytes
Decimal Signed numbers with decimal precision Variable
Double 64-bit floating point numbers 8 bytes
Blob Binary data (files, images) Variable
ID 15 or 18 character Salesforce record IDs 18 bytes
Object Any Apex type (generic) Variable

Primitive Data Types with Examples

String Data Type

// String declaration and manipulation
String accountName = 'Acme Corporation';
String description = null; // Strings can be null
String multiLine = 'Line 1\n' + 'Line 2';

// String methods
Integer nameLength = accountName.length();
String upperName = accountName.toUpperCase();
Boolean containsAcme = accountName.contains('Acme');

Numeric Data Types

// Integer for whole numbers
Integer recordCount = 1000;
Integer negativeValue = -500;

// Long for larger whole numbers
Long bigNumber = 9223372036854775807L;

// Decimal for precise calculations
Decimal price = 99.99;
Decimal taxRate = 0.0875;
Decimal totalPrice = price * (1 + taxRate);

// Double for floating point
Double percentage = 85.5;
Double scientificNotation = 1.23e-4;

Date and Time Data Types

// Date operations
Date today = Date.today();
Date futureDate = today.addDays(30);
Date specificDate = Date.newInstance(2024, 12, 25);

// DateTime with timezone handling
DateTime now = DateTime.now();
DateTime utcTime = DateTime.newInstanceGmt(2024, 1, 1, 12, 0, 0);
String formattedDateTime = now.format('yyyy-MM-dd HH:mm:ss');

// Time for time-only values
Time businessHours = Time.newInstance(9, 0, 0, 0); // 9:00 AM

Collection Data Types

Lists (Arrays)

// List declaration and initialization
List<String> cityNames = new List<String>();
List<Integer> numbers = new List<Integer>{1, 2, 3, 4, 5};
List<Account> accounts = [SELECT Id, Name FROM Account LIMIT 10];

// List operations
cityNames.add('San Francisco');
cityNames.add('New York');
Integer listSize = cityNames.size();
String firstCity = cityNames.get(0);

Sets for Unique Values

// Set declaration
Set<String> uniqueIndustries = new Set<String>();
Set<Id> accountIds = new Set<Id>();

// Adding values (duplicates ignored)
uniqueIndustries.add('Technology');
uniqueIndustries.add('Healthcare');
uniqueIndustries.add('Technology'); // Duplicate ignored

Boolean containsTech = uniqueIndustries.contains('Technology');

Maps for Key-Value Pairs

// Map declaration
Map<String, String> stateAbbreviations = new Map<String, String>();
Map<Id, Account> accountMap = new Map<Id, Account>();

// Map operations
stateAbbreviations.put('California', 'CA');
stateAbbreviations.put('New York', 'NY');
String caAbbrev = stateAbbreviations.get('California');
Set<String> allStates = stateAbbreviations.keySet();

SObject Data Types

// sObject variable declaration
Account acc = new Account();
Contact con = new Contact();
Opportunity opp = [SELECT Id, Name FROM Opportunity LIMIT 1];

// Generic sObject
sObject genericRecord = new Account();
Account specificAccount = (Account)genericRecord; // Type casting

// Working with sObject fields
acc.Name = 'New Account';
acc.Industry = 'Technology';
acc.AnnualRevenue = 1000000;

Type Casting and Conversion

// Implicit casting (safe)
Integer intValue = 100;
Long longValue = intValue; // Integer to Long
Double doubleValue = intValue; // Integer to Double

// Explicit casting (potential data loss)
Double preciseValue = 99.99;
Integer roundedValue = (Integer)preciseValue; // Results in 99

// String conversions
String numberAsString = String.valueOf(intValue);
Integer stringAsNumber = Integer.valueOf('123');

// sObject casting
sObject genericObj = new Account();
Account specificAcc = (Account)genericObj;

Variable Scope and Lifetime

Local Variables

public void processAccounts() {
    // Local variables - scope limited to method
    Integer processedCount = 0;
    List<Account> accountsToUpdate = new List<Account>();
    
    for (Account acc : [SELECT Id, Name FROM Account]) {
        // Loop variable scope
        String accountName = acc.Name;
        if (accountName != null) {
            processedCount++;
        }
    }
    // accountName not accessible here
}

Instance Variables

public class AccountProcessor {
    // Instance variables - accessible throughout class
    private Integer maxRecords = 10000;
    private String processingStatus;
    
    public void setMaxRecords(Integer max) {
        this.maxRecords = max; // 'this' refers to instance
    }
}

Governor Limits and Memory Considerations

Variable declaration impacts Salesforce governor limits:

  • Heap Size Limit: 6MB synchronous, 12MB asynchronous
  • Collection Limits: Lists and Maps consume memory based on size
  • String Limits: Large strings impact heap usage
  • sObject Limits: Each sObject instance uses memory
// Memory-efficient practices
// Use specific data types
Integer count = 100; // 4 bytes
// Instead of
// String count = '100'; // Variable bytes

// Clear large collections when done
List<Account> largeList = new List<Account>();
// ... process data
largeList.clear(); // Free memory

Common Variable Declaration Patterns

Null Safety Patterns

// Safe null checking
String accountName = acc.Name;
if (String.isNotBlank(accountName)) {
    // Process non-null, non-empty string
}

// Null coalescing pattern
String displayName = String.isBlank(acc.Name) ? 'Unknown' : acc.Name;

// Collection null safety
List<Contact> contacts = acc.Contacts;
if (contacts != null && !contacts.isEmpty()) {
    // Process contacts
}

Constants Declaration

// Class-level constants
public class Constants {
    public static final String DEFAULT_INDUSTRY = 'Technology';
    public static final Integer MAX_RECORDS = 50000;
    public static final Decimal TAX_RATE = 0.0875;
}

Best Practices for Variable Declaration

  1. Use descriptive names: accountCount instead of count
  2. Initialize when possible: Avoid null pointer exceptions
  3. Choose appropriate data types: Use Integer for counts, Decimal for currency
  4. Follow naming conventions: camelCase for variables, PascalCase for classes
  5. Minimize scope: Declare variables in the smallest scope needed
  6. Use final for constants: final String CONSTANT_VALUE = 'value';

Frequently Asked Questions

What happens if I don’t declare a variable before using it in Apex?

Apex will throw a compilation error. Since Apex is strongly typed, all variables must be declared with their data type before use. The error message will indicate “Variable does not exist” at the line where the undeclared variable is referenced.

Can Apex variables be null by default?

Yes, most Apex variables are null by default when declared but not initialized. Primitive types like Integer, Boolean, and String default to null. Collections (List, Set, Map) also default to null and must be initialized before use to avoid null pointer exceptions.

What’s the difference between Integer and Long data types in Apex?

Integer stores 32-bit signed values (-2,147,483,648 to 2,147,483,647) while Long stores 64-bit signed values with a much larger range. Use Integer for typical counting operations and Long when dealing with large numbers like timestamps or record IDs in bulk operations.

How do I handle type casting errors in Apex?

Use try-catch blocks around casting operations and check types before casting. For sObject casting, use instanceof operator: if (obj instanceof Account) { Account acc = (Account)obj; }. For string-to-number conversions, validate the string format first.

What are the memory implications of different Apex data types?

Primitive types have fixed memory footprints (Integer: 4 bytes, Long: 8 bytes). Strings and collections use variable memory based on content size. Large collections and strings can quickly consume the 6MB heap limit in synchronous contexts. Always clear unused collections and avoid storing large datasets in memory.