Apex offers two ways to read and write fields on an SObject record:
- Dot notation on the strongly-typed SObject (
a.Name,a.Industry). - Generic
get/puton a baseSObjectreference (r.get('Name'),r.put('Industry', 'Tech')).
The first is the everyday way. The second is how dynamic Apex works.
1. Dot notation — the everyday case
When you have a typed SObject variable, you reference fields the same way as any Apex object property.
Account a = new Account(Name = 'Acme', Industry = 'Tech');
System.debug(a.Name); // 'Acme'
a.Industry = 'Finance'; // re-assign
a.AnnualRevenue = 1000000; // typed: must be Decimal
Dot notation requires the field to be loaded:
- Fields populated in code (e.g., constructor argument).
- Fields included in the SELECT clause of a SOQL query.
Account a = [SELECT Id, Name FROM Account LIMIT 1];
System.debug(a.Name); // OK
System.debug(a.Industry); // System.SObjectException: Industry not selected
This is one of the most common runtime errors in Apex — you forgot to include the field in your SELECT.
2. Dot notation across relationships
Relationship fields are traversed with . as well, but the field syntax differs:
-
Parent (lookup or master-detail) — use the relationship name:
Contact c = [SELECT Id, Account.Name, Account.Industry FROM Contact LIMIT 1]; System.debug(c.Account.Name); // 'Acme' System.debug(c.Account.Industry); // 'Tech' -
Child (one-to-many) — use a subquery; access the inner list via the relationship name:
Account a = [SELECT Id, Name, (SELECT Id, LastName FROM Contacts) FROM Account LIMIT 1]; for (Contact c : a.Contacts) { System.debug(c.LastName); } -
Custom lookups use the relationship name minus
__cplus__r:Order__c o = [SELECT Id, Customer__r.Name FROM Order__c LIMIT 1]; System.debug(o.Customer__r.Name);
3. Generic get and put — for dynamic code
When you don’t know the SObject type at compile time, you use the base SObject interface and its get(String) and put(String, Object) methods.
SObject record = Schema.getGlobalDescribe().get('Account').newSObject();
record.put('Name', 'Acme');
record.put('Industry', 'Tech');
insert record;
String name = (String) record.get('Name');
A few things to call out:
getreturnsObject— you cast to the actual type.putaccepts anObject. Mismatched types throwIllegalArgumentExceptionat runtime.- This is how packaged code, generic utilities, and metadata-driven controllers manipulate fields without hardcoding object names.
4. Setting fields when constructing
The sObject constructor accepts named parameters — the cleanest insert syntax:
Account a = new Account(
Name = 'Acme',
Industry = 'Tech',
AnnualRevenue = 1000000
);
insert a;
Equivalent to:
Account a = new Account();
a.Name = 'Acme';
a.Industry = 'Tech';
a.AnnualRevenue = 1000000;
insert a;
The constructor form is preferred — it scans cleanly and produces fewer lines.
5. Reading fields from a Map<Id, SObject>
Common pattern: SOQL into a Map and look up a parent record by Id.
Map<Id, Account> byId = new Map<Id, Account>(
[SELECT Id, Name, Industry FROM Account WHERE Id IN :accountIds]
);
for (Contact c : contacts) {
Account a = byId.get(c.AccountId);
if (a != null) {
System.debug(c.LastName + ' works at ' + a.Name);
}
}
The Map<Id, SObject> constructor that takes a query result is a daily-use idiom.
6. Polymorphic relationships (Task.WhoId, Task.WhatId)
Fields like Task.WhoId can point to multiple object types (Contact or Lead). Apex represents these with polymorphic dot syntax:
Task t = [SELECT Id, Who.Name, Who.Type FROM Task LIMIT 1];
System.debug(t.Who.Name); // works regardless of whether Who is a Contact or Lead
System.debug(t.Who.Type); // 'Contact' or 'Lead'
TYPEOF in SOQL is the formal way to handle this for typed access.
What interviewers are really looking for
The basic answer is “dot notation.” The senior-level answer covers: (1) the field must be SELECTed in the SOQL or you get a runtime SObjectException, (2) parent traversal uses the relationship name (Account.Name, Customer__r.Name), (3) child access uses subqueries and the relationship list, (4) get/put is how dynamic Apex reaches fields when the type isn’t known at compile time. Mention TYPEOF for polymorphic relationships and you’ve covered the corner cases.
Verified against: Apex Developer Guide — SObject Fields, SOQL Relationship Queries. Last reviewed 2026-05-17.