Salesforce Apex access modifiers define where a class, method, variable, property, constructor, or interface can be used. Apex also supports class-level sharing keywords such as with sharing, without sharing, and inherited sharing, which control whether the class enforces the current user’s record sharing rules. In this Salesforce tutorial, we will learn how Apex access modifiers and sharing modes work, where each keyword is used, and what to check before using system-mode code.
Apex Access Modifiers for Classes, Methods, and Variables
The commonly used Apex access modifiers are private, protected, public, and global. These keywords are about code visibility. They are different from sharing keywords, which are about record-level access.
| Apex keyword | What it controls | Typical use |
|---|---|---|
private | Visible only inside the defining class or block. | Helper variables and methods that should not be called from outside the class. |
protected | Visible in the defining class and in subclasses. | Reusable logic for classes that are designed to be extended. |
public | Visible to other Apex code in the same application or namespace. | Controllers, service classes, helper methods, and normal internal Apex APIs. |
global | Visible outside the application or namespace. | Managed package APIs, web service entry points, and code intentionally exposed externally. |
private Access Modifier in Apex
If you declare a member as private, it can be used only within the Apex class where it is declared. This is the safest default for internal helper logic because it prevents other classes from depending on implementation details.
- Inner classes are private by default if no access modifier is specified.
- Use
privatefor helper methods, temporary state, and calculations that should not be reused directly by other classes. - Top-level Apex classes cannot be declared
private; top-level classes normally usepublicorglobal.
protected Access Modifier in Apex Inheritance
The protected modifier is used when a member should be available to a class and its child classes, but not to unrelated Apex classes. It is useful with virtual or abstract classes where subclasses need controlled access to common logic.
public virtual class BaseDiscountCalculator {
protected Decimal defaultDiscount = 5;
protected Decimal applyDefaultDiscount(Decimal amount) {
return amount - (amount * defaultDiscount / 100);
}
}
public Access Modifier in Apex Application Code
If you declare an Apex class or member as public, it is visible to other Apex code in the same application or namespace. Use public for classes and methods that are meant to be reused by controllers, triggers, batch classes, schedulable classes, and tests inside the same codebase.
A common mistake is to make every method public. Keep helper logic private unless another class has a clear reason to call it.
global Access Modifier for Managed Packages and External Apex APIs
If you declare an Apex class or member as global, it can be referenced from outside the application or namespace. Use it carefully because a global API is harder to change after other code depends on it.
- If a method, property, or inner class is declared as
global, the containing top-level class must also be declared asglobal. - Prefer
publicunless the class must be exposed outside the namespace. - Use clear method signatures because global APIs can become long-term contracts.
Apex Sharing Keywords: with sharing, without sharing, and inherited sharing
Apex sharing keywords are class-level declarations that control whether record sharing rules are enforced. They do not replace object permissions, field-level security checks, validation rules, or explicit security enforcement in SOQL/DML. For current Salesforce behavior, also review the official Apex sharing keyword documentation at Salesforce Developers.
with sharing in Apex Record Access
If you declare a class as with sharing, Apex enforces the current user’s sharing rules for record access. This means the class respects organization-wide defaults, role hierarchy access, manual sharing, teams, territories, and sharing rules that make records visible to the running user.
Use with sharing for controllers, user-facing services, and business logic that should behave according to the records the current user is allowed to see.
public with sharing class AccountViewer {
public static List<Account> getVisibleAccounts() {
return [SELECT Id, Name FROM Account ORDER BY Name LIMIT 50];
}
}
without sharing in Apex System-Mode Record Access
If you declare a class as without sharing, Apex does not enforce the current user’s record sharing rules for that class. This is sometimes required for administrative operations, background processing, or controlled service-layer logic, but it should be used deliberately.
without sharing is about record sharing. It does not mean your code should ignore CRUD permissions or field level security. When user permissions must be respected, check object and field permissions explicitly, use user-mode database operations where appropriate, or use security-enforcing SOQL patterns supported by your Salesforce version.
public without sharing class AccountMaintenanceService {
public static void recalculateAccountScores(Set<Id> accountIds) {
List<Account> accountsToUpdate = [
SELECT Id, Rating
FROM Account
WHERE Id IN :accountIds
];
for (Account accountRecord : accountsToUpdate) {
accountRecord.Rating = 'Warm';
}
update accountsToUpdate;
}
}
inherited sharing in Apex Service Classes
The inherited sharing keyword makes the class run with the sharing mode of its caller. It is useful for service classes that may be called from different contexts but should not silently choose an unclear default. It also makes the security intent easier to read during code review.
public inherited sharing class OpportunityService {
public static List<Opportunity> findOpenOpportunities(Id accountId) {
return [
SELECT Id, Name, StageName
FROM Opportunity
WHERE AccountId = :accountId
AND IsClosed = false
];
}
}
Default Sharing Behavior When No Sharing Keyword Is Declared
If an Apex class does not declare with sharing, without sharing, or inherited sharing, its behavior depends on the execution context and calling class. Because this can be difficult to review, it is better to declare the sharing mode explicitly on classes that run SOQL or DML. A common modern practice is to use with sharing for user-facing classes, without sharing only for carefully controlled system logic, and inherited sharing for service classes whose caller should decide the record-sharing context.
Access Modifiers and Sharing Keywords Are Not the Same Security Control
Do not mix up access modifiers with sharing keywords. private, protected, public, and global control which code can call a class member. with sharing, without sharing, and inherited sharing control whether record sharing is enforced while the class runs.
| Question | Use this Apex feature |
|---|---|
| Can another class call this method? | Access modifier such as private, public, or global. |
| Can the current user see this record through sharing? | Sharing keyword such as with sharing or without sharing. |
| Can the user access this object or field? | CRUD and field-level security checks, not the sharing keyword alone. |
| Should a reusable service follow the caller’s sharing context? | inherited sharing. |
Apex Access Modifier Syntax Examples from the Original Tutorial
The following examples show basic class and sharing declarations. These original examples are kept for syntax reference, followed by notes that clarify how they should be interpreted in real Apex code.
Example 1
public class outterclass {
//statement(s)
Class innerclass {
//statement(s)
}
}
In Apex, an inner class can be declared inside an outer class. Inner classes are private by default unless an access modifier is added.
Example 2
public With Sharing class Sharingclass {
//statement(s)
}
This class is intended to run with the current user’s record sharing rules. In current Apex style, the sharing keyword is usually written as with sharing.
Example 3
public Without Sharing class nonsharing {
//statement(s)
}
This class is intended to run without enforcing the current user’s record sharing rules. Use this mode only when the code has a clear administrative or service-layer reason.
Example 4
public With Sharing Class Outer {
//statement(s)
Without Sharing class inner {
//statement(s)
}
}
In the above example, outer class runs with current user Sharing rules. But inner class runs with System Context.
For review, remember that an inner class can declare its own sharing mode. Do not assume an inner class automatically follows the outer class if it explicitly declares a different sharing keyword.
Example 5
public Without Sharing class outer {
\\outer class code
{
\\inner class code
}
}
In the above example, both inner and outer classes runs with current user’s permissions.
When writing production Apex, declare a real inner class with a class name and a clear sharing mode if it performs record queries or updates. Avoid relying on ambiguous defaults in security-sensitive code.
How Sharing Rules, OWD, and Apex Sharing Keywords Work Together
Organization-wide defaults, often called OWD, set the baseline record access for an object. Sharing rules can open additional record access to users, roles, groups, or territories. A with sharing Apex class respects those record-sharing decisions. A without sharing class bypasses those record-sharing restrictions for the code running inside that class.
Sharing rules do not override OWD by making access more restrictive. They extend access beyond the baseline set by OWD. Apex sharing keywords decide whether the class enforces that record-level sharing model while executing.
Editorial QA Checklist for Apex Access Modifiers and Sharing Mode
- Confirm that each Apex class has the narrowest useful code visibility:
private,protected,public, orglobal. - Check whether every SOQL/DML class declares a clear sharing mode:
with sharing,without sharing, orinherited sharing. - Do not describe
with sharingorwithout sharingas field-level security controls; they are record-sharing controls. - Use
without sharingonly when there is a documented reason to bypass record sharing. - For user-facing code, verify object permissions and field-level security separately from the class sharing keyword.
Apex Access Modifiers and Sharing Keywords FAQs
What is the difference between with sharing and without sharing in Apex?
with sharing enforces the current user’s record sharing rules. without sharing does not enforce those record sharing rules for the class. Both keywords are about record-level access, not about whether a method is public or private.
How can sharing rules be bypassed using an Apex class?
Sharing rules can be bypassed for code in a class declared as without sharing. This should be used carefully because it can allow the class to query or update records that the running user would not normally see through sharing. Object permissions and field-level security should still be considered separately.
What is the default: with sharing or without sharing in Apex?
If no sharing keyword is declared, Apex behavior can depend on the calling context. Because that can be unclear during review, declare the sharing mode explicitly on classes that access Salesforce records. Use inherited sharing when the class should follow its caller’s sharing context.
Does a sharing rule override OWD in Salesforce?
A sharing rule does not make OWD more restrictive. OWD sets the baseline access, and sharing rules open additional access to records. Apex classes declared with sharing respect that record-sharing model.
Does without sharing ignore field-level security in Apex?
without sharing bypasses record sharing, but it should not be treated as a complete security model. Field-level security and object permissions are separate checks. When Apex returns data to users or performs user-driven updates, verify CRUD and field permissions using the security features appropriate for your Salesforce version.
Conclusion: Choosing the Right Apex Access and Sharing Keyword
In this Apex Tutorial, we learned about Apex access modifiers with syntax and examples. Use access modifiers to control code visibility, and use sharing keywords to control record-sharing behavior. For most application code, start with the narrowest access modifier and an explicit sharing mode, then add separate object and field security checks wherever user permissions matter.
TutorialKart.com