LearnFrenzy
Sign in Take a free test

Control Flow and Collections · Lesson 8 of 41

If-Else and Switch Statements in Apex

5 min read Updated Nov 8, 2026 Saurabh Samir

Business rules are decisions: discount only for Gold customers, escalate only high-priority cases, route leads by country. Apex gives you two tools – if/else for conditions and switch for choosing between many values – and a third, often-forgotten trick: switching on the type of a record.

In this lesson

  • if, else if, else
  • Guard clauses that keep code flat
  • switch on values, with when null and when else
  • switch on sObject types

if, else if, else

Decimal annualRevenue = 4500000;
String rating;

if (annualRevenue == null) {
    rating = 'Unknown';
} else if (annualRevenue >= 10000000) {
    rating = 'Hot';
} else if (annualRevenue >= 1000000) {
    rating = 'Warm';
} else {
    rating = 'Cold';
}
System.debug('Rating: ' + rating);

Debug log

Rating: Warm

Conditions are checked top to bottom and only the first true branch runs, so order matters: put the most specific checks first. Conditions must be real Booleans – Apex has no "truthy" values, so if (name) doesn't compile; write if (String.isNotBlank(name)).

Guard clauses keep code flat

Deeply nested if blocks are hard to read. Return early for the cases you don't handle, and the main logic stays at the left margin:

// DiscountCalculator.cls
public with sharing class DiscountCalculator {
    public static Decimal discountFor(Opportunity opp, String customerTier) {
        if (opp == null || opp.Amount == null) return 0;           // guard clauses
        if (opp.StageName == 'Closed Lost') return 0;

        Decimal rate = customerTier == 'Gold' ? 0.10 : customerTier == 'Silver' ? 0.05 : 0;
        if (opp.Amount > 1000000) rate += 0.02;                    // volume bonus
        return (opp.Amount * rate).setScale(2);
    }
}
Opportunity big = new Opportunity(Amount = 2000000, StageName = 'Negotiation');
Opportunity lost = new Opportunity(Amount = 500000, StageName = 'Closed Lost');

System.debug('Gold, big deal: ' + DiscountCalculator.discountFor(big, 'Gold'));
System.debug('Silver, big deal: ' + DiscountCalculator.discountFor(big, 'Silver'));
System.debug('Lost deal: ' + DiscountCalculator.discountFor(lost, 'Gold'));
System.debug('No opportunity: ' + DiscountCalculator.discountFor(null, 'Gold'));

Debug log

Gold, big deal: 240000.00
Silver, big deal: 140000.00
Lost deal: 0
No opportunity: 0

switch on values

switch compares one expression against several when values. It works with Integer, Long, String (case-sensitive here!), enums and sObjects:

List<String> priorities = new List<String>{ 'High', 'Critical', 'Low', null, 'high' };

for (String priority : priorities) {
    String sla;
    switch on priority {
        when 'Critical', 'High' {          // several values in one branch
            sla = '4 hours';
        }
        when 'Medium' {
            sla = '1 day';
        }
        when null {                        // switch handles null explicitly
            sla = 'not set';
        }
        when else {                        // everything else (like default)
            sla = '3 days';
        }
    }
    System.debug(priority + ' → ' + sla);
}

Debug log

High → 4 hours
Critical → 4 hours
Low → 3 days
null → not set
high → 3 days

Notice the last line: 'high' fell through to when else. Unlike ==, switch on String is case-sensitive. Normalise input first if case shouldn't matter. There's no fall-through between branches and no break – exactly one branch runs.

switch on enums

// CaseChannel.cls
public enum CaseChannel { EMAIL, PHONE, CHAT, PORTAL }
for (CaseChannel ch : CaseChannel.values()) {
    switch on ch {
        when EMAIL, PORTAL {
            System.debug(ch + ': respond in writing');
        }
        when PHONE, CHAT {
            System.debug(ch + ': live response');
        }
    }
}

Debug log

EMAIL: respond in writing
PHONE: live response
CHAT: live response
PORTAL: respond in writing

switch on sObject type

When code receives a generic SObject – a polymorphic lookup like Task.WhatId, or a utility that handles several objects – switch can branch on its type and give you a typed variable in one step:

List<SObject> records = new List<SObject>{
    new Account(Name = 'Acme', Industry = 'Energy'),
    new Contact(FirstName = 'Neha', LastName = 'Rao'),
    new Opportunity(Name = 'Acme renewal', Amount = 75000),
    new Lead(LastName = 'Shah', Company = 'Globex')
};

for (SObject rec : records) {
    switch on rec {
        when Account a {
            System.debug('Account ' + a.Name + ' in ' + a.Industry);
        }
        when Contact c {
            System.debug('Contact ' + c.FirstName + ' ' + c.LastName);
        }
        when Opportunity o {
            System.debug('Opportunity worth ' + o.Amount);
        }
        when else {
            System.debug('Something else: ' + rec.getSObjectType());
        }
    }
}

Debug log

Account Acme in Energy
Contact Neha Rao
Opportunity worth 75000
Something else: Lead

if or switch?

Use if/else when…Use switch when…
conditions are ranges or combinations (amount > 1000 && isActive)you compare one value with a list of exact values
each branch checks something differentyou branch on an enum or a record's type
you need case-insensitive String checksyou want explicit when null handling

Practice

Try it yourself

  1. Write a switch that maps a Lead's LeadSource ('Web', 'Phone Inquiry', 'Partner Referral', anything else) to a queue name.

    Show answer

    switch on lead.LeadSource { when 'Web' { queue = 'Digital_Leads'; } when 'Phone Inquiry' { queue = 'Inside_Sales'; } when 'Partner Referral' { queue = 'Partner_Team'; } when else { queue = 'General'; } } – remember it's case-sensitive, so picklist API values must match exactly.

  2. Why doesn't if (opp.IsWon) throw for a queried Opportunity, while if (myFlag) might?

    Show answer

    Checkbox fields on records are never null, but a Boolean variable that was never assigned is null, and a null Boolean in a condition throws a NullPointerException.

Quick check

Is switch on String case-sensitive?

Yes – unlike ==.

What is the switch equivalent of default?

when else.

Can switch branch on a record's object type?

Yes – when Account a { … } gives you a typed variable.

Summary

  • if/else for ranges and combined conditions; order branches from specific to general.
  • Use guard clauses to keep logic flat.
  • switch for exact values and enums, with when null and when else; it's case-sensitive for Strings.
  • switch on SObject gives typed variables for polymorphic records.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Search LearnFrenzy

Esc

Quick links