Apex has four built-in categories of data types — Primitives, Collections, sObjects, and Enums — plus the user-defined types you create yourself (classes and interfaces). Knowing the categories helps you answer everything from “how do I store a list?” to “what’s the difference between Account and SObject?“
1. Primitives
The atomic types. Each one represents a single value, not a collection.
| Type | Purpose | Example |
|---|---|---|
Boolean | true/false | Boolean done = true; |
Integer | 32-bit whole number | Integer count = 42; |
Long | 64-bit whole number | Long big = 9_000_000_000L; |
Decimal | High-precision number for currency, percent | Decimal price = 19.95; |
Double | 64-bit floating point | Double pi = 3.14159; |
String | UTF-16 text, immutable | String name = 'Acme'; |
Date | Calendar date, no time | Date today = Date.today(); |
Time | Time of day, no date | Time t = Time.newInstance(9, 0, 0, 0); |
Datetime | Date + time, in UTC by default | Datetime now = Datetime.now(); |
Id | Salesforce 15- or 18-char record ID | Id accId = '001...'; |
Blob | Binary data (PDFs, images, callout payloads) | Blob b = Blob.valueOf('hi'); |
Object | The base type for everything | Object o = 'anything'; |
Id is technically a strongly-typed String — same wire format, but the compiler validates length and shape.
2. Collections
Containers for multiple values. Three flavors:
List
Ordered, allows duplicates, integer-indexed.
List<String> names = new List<String>{ 'Acme', 'Beta', 'Gamma' };
List<Account> accs = [SELECT Id FROM Account]; // SOQL returns a List
Set
Unordered, no duplicates, fast membership check.
Set<Id> ids = new Set<Id>{ a.Id, b.Id, c.Id };
if (ids.contains(someId)) { ... }
Map
Key-value pairs, no duplicate keys.
Map<Id, Account> byId = new Map<Id, Account>([SELECT Id, Name FROM Account]);
Account a = byId.get(someId);
All three are generic — you specify the element type in <...>.
3. sObjects
Every Salesforce record has an Apex type corresponding to its object: Account, Contact, Opportunity, MyCustomObject__c. They share a common base type, SObject, which lets you write code generic across objects.
Account a = new Account(Name = 'Acme');
SObject anything = a; // upcast to the generic
String name = (String) anything.get('Name');
The generic SObject is how dynamic Apex works.
4. Enums
Named, finite sets of values.
public enum Season { Winter, Spring, Summer, Fall }
Season current = Season.Spring;
if (current == Season.Spring) { ... }
Apex provides several built-in enums you’ll encounter: System.AccessLevel, TriggerOperation, Schema.DisplayType, LoggingLevel. Enums are not interchangeable with Integers — they’re their own type.
5. User-defined classes and interfaces
When the built-in types aren’t enough, you define your own. A wrapper class to bundle related fields for an LWC. A service class to encapsulate business logic. An interface to enforce a contract.
public class OrderDTO {
@AuraEnabled public String orderNumber;
@AuraEnabled public Decimal total;
@AuraEnabled public List<Contact> contacts;
}
A side note on Object
Object is the root of the Apex type hierarchy — every type inherits from it. It’s used when truly anything could be the value (generic deserialization, untyped maps from JSON). Casting Object back to a specific type is your responsibility.
Map<String, Object> payload = (Map<String, Object>) JSON.deserializeUntyped(body);
String customer = (String) payload.get('customer');
What interviewers are really looking for
The naming check is “four categories — primitives, collections, sObjects, enums.” Distinguishing Decimal vs Double (Decimal is precise for currency; Double is binary floating-point and can introduce rounding errors) shows fundamentals. Calling out SObject as the dynamic-Apex base type and user-defined classes as the fifth category that everything else builds on shows architecture-level understanding.
Verified against: Apex Developer Guide — Data Types. Last reviewed 2026-05-17.