编写 Apex

Apex 就像 Salesforce 的 Java。它使您能够添加数据并与之交互 Lightning 平台持久性层。它使用类、数据类型、变量和 if-else 语句。您可以根据条件使其执行,也可以执行代码块 反复。

  • 数据类型和变量
    Apex 使用数据类型、变量和相关语言结构,例如枚举、常量、表达式、运算符和赋值语句。
  • 控制流语句
    Apex 提供 if-else 语句、switch 语句和循环来控制代码执行的流程。语句通常按照它们出现的顺序逐行执行。使用控制流语句,您可以根据特定条件执行 Apex 代码,也可以让代码块重复执行。
  • 在 Apex
    中使用数据 您可以在 Lightning 平台持久性层中添加数据并与之交互。sObject 数据类型是保存数据对象的主要数据类型。您将使用数据操作语言 (DML) 来处理数据,并使用查询语言来检索数据,例如 () 等。

数据类型和变量

Apex 使用数据类型、变量和相关语言结构,例如枚举、 常量、表达式、运算符和赋值语句。

  1. 数据类型
    在 Apex 中,所有变量和表达式都具有数据类型,例如 sObject、primitive 或 enum。
  2. 基元数据类型
    Apex 使用与 SOAP API 相同的基元数据类型,但在某些情况下使用更高精度的 Decimal 类型。所有基元数据类型都是按值传递的。
  3. 集合
    Apex 中的集合可以是列表、集合或映射。

  4. 枚举 枚举是一种抽象数据类型,其值每个值都恰好采用您指定的一组有限标识符中的一个。枚举通常用于定义一组可能的值,否则这些值没有数字顺序。典型的例子包括一张牌的花色,或一年中的特定季节。
  5. 变量 局部变量
    使用 Java 样式语法声明。与 Java 一样,可以在单个语句中声明和初始化多个变量。
  6. 常量 顶点常量
    是其值在初始化一次后不会更改的变量。可以使用关键字定义常量。final
  7. 表达式和运算符 表达式是由变量、运算符
    和方法调用组成的构造,其计算结果为单个值。
  8. 赋值语句 赋值语句是将值放入变量的任何语句
  9. 转换
    规则 通常,Apex 要求您显式将一种数据类型转换为另一种数据类型。例如,Integer 数据类型的变量不能隐式转换为 String。您必须使用该方法。但是,可以隐式转换一些数据类型,而无需使用方法。string.format

数据类型

在 Apex 中,所有变量和表达式都有一个数据类型,例如 sObject、primitive、 或枚举。

  • 基元,例如 Integer、Double、Long、Date、Datetime、String、ID 或 布尔值(请参阅原始数据 类型)
  • sObject,可以作为通用 sObject 或特定 sObject,例如 客户、联系人或MyCustomObject__c(请参阅第 4 章中的使用 sObjects。
  • 集合,包括:
    • 基元、sObjects、用户定义对象、对象的列表(或数组) 从 Apex 类或集合创建(请参阅列表)
    • 一组基元(参见 集合)
    • 从基元到基元、sObject 或集合的映射(请参阅映射)
  • 值的类型化列表,也称为举(请参阅枚举)
  • 从用户定义的 Apex 类创建的对象(请参阅类、对象和 接口)
  • 从系统提供的 Apex 类创建的对象
  • Null(对于常量,可以是 分配给任何变量)null

方法可以返回任何列出的类型的值,也可以返回不返回任何值且类型为 无效。

在编译时严格执行类型检查。例如,解析器生成一个 如果为 Integer 类型的对象字段分配了 String 类型的值,则出错。然而 所有编译时异常都作为特定的故障代码返回,并带有行号 和 error 列。有关详细信息,请参阅调试 Apex。

基元数据类型

Apex 使用与 SOAP API 相同的原始数据类型,但精度更高 在某些情况下为十进制类型。所有基元数据类型都是按值传递的。

所有 Apex 变量,无论它们是类成员变量还是方法变量, 初始化为 。确保您 在使用变量之前,请将其初始化为适当的值。例如 将布尔变量初始化为 。nullfalse

Apex 基元数据类型包括:

数据类型描述
斑点存储为单个对象的二进制数据的集合。您可以 分别使用 和 方法将此数据类型转换为 String 或从 String 转换。 Blob 可以作为 Web 服务参数被接受,存储在文档中 (文档的正文是 Blob),或作为附件发送。查看更多 信息,请参阅 Crypto 类。toStringvalueOf
布尔只能赋值 、 或 的值。为 例:truefalsenullBoolean isWinner = true;
日期指示特定日期的值。与 Datetime 值不同,Date 值不包含有关时间的信息。始终使用 系统静态方法。您可以添加或减去 Integer 值 一个 Date 值,返回一个 Date 值。加法和减法 整数值是唯一适用于 Date 的算术函数 值。不能执行包含两个或 更多日期值。请改用 Date 方法。用 方法 获取没有附加时间戳的日期。使用隐式 具有 Date 值的字符串转换将生成带有 附加时间戳。String.valueOf()
日期时间指示特定日期和时间的值,例如 时间戳。始终使用系统静态方法创建日期时间值。您可以在 Datetime 值,返回 Date 值。加法和减法 整数和双精度值是唯一的算术函数 使用 Datetime 值。无法执行算术函数 包含两个或多个 Datetime 值。请改用 Datetime 方法。
十进制包含小数点的数字。十进制是任意的 精度数字。系统会自动为货币字段分配类型 十进制。如果未明确设置 a Decimal,从中创建 Decimal 的项目决定了 小数的刻度。比例是小数位数的计数。 使用该方法 设置小数点的刻度。setScale如果 Decimal 是作为查询的一部分创建的,则小数位数为 基于从 查询。如果 Decimal 是从 String 创建的,则小数位数为 小数点后的小数点后的字符数 字符串。如果 Decimal 是从非十进制数字创建的,则 number 首先转换为 String。然后设置刻度 使用小数点后的字符数。注意两个数值等效的 Decimal 对象 但比例不同(如1.1和1.10)一般没有 相同的哈希码。在以下位置使用此类 Decimal 对象时要小心 设置 或 作为 Map 键。
包含小数点的 64 位数字。双打有最低要求 的值 –263最大值为263-1.为 例:Double pi = 3.14159; Double e = 2.7182818284D;科学记数法 (e) 不支持双打。
编号任何有效的 18 个字符的 Lightning Platform 记录标识符。为 例:ID id='00300000003T2PGAA0';如果 您设置为 15 个字符的值,Apex 将该值转换为其 18 个字符 表示法。运行时将拒绝所有无效值 例外。IDID
整数不包含小数点的 32 位数字。整数有一个 最小值-2,147,483,648和最大值 值2,147,483,647.为 例:Integer i = 1;
不包含小数点的 64 位数字。多头有一个 最小值为 -263最大值为 263-1.当您需要一系列值时,请使用此数据类型 比 Integer 提供的范围更宽。为 例:Long l = 2147483648L;
对象Apex 中支持的任何数据类型。Apex 支持原始数据 类型(如 Integer)、用户定义的自定义类、sObject 泛型类型或特定于 sObject 的类型(如 Account)。都 Apex 数据类型继承自 Object。可以将表示更具体数据类型的对象强制转换为 其基础数据类型。例如:Object obj = 10; // Cast the object to an integer. Integer i = (Integer)obj; System.assertEquals(10, i);下一个示例演示如何将对象强制转换为用户定义的对象 type – 一个自定义 Apex 类,该类在 组织。MyApexClassObject obj = new MyApexClass(); // Cast the object to the MyApexClass custom type. MyApexClass mc = (MyApexClass)obj; // Access a method on the user-defined class. mc.someClassMethod();
字符串用单引号括起来的任何字符集。例如String s = 'The quick brown fox jumped over the lazy dog.';字符串 size:字符串对字符数没有限制 可以包括。相反,堆大小限制用于确保 Apex 计划不会变得太大。空字符串和 尾随空格:sObject String 字段值遵循 与SOAP API中的规则相同:它们永远不能为空(仅),并且永远不能为空 包括前导和尾随空格。这些约定是 数据库存储所必需的。null相反,Apex 中的字符串 可以是 或 空 和 可以包括前导和尾随空格,可用于 构造消息。nullSolution sObject 字段 SolutionNote 作为特殊类型的 String 运行。如果您有 HTML 解决方案 启用后,此字段中使用的任何 HTML 标签都会在 对象已创建或更新。如果输入的 HTML 无效,则会出现错误 被抛出。此字段中使用的任何 JavaScript 都会在 对象已创建或更新。在以下示例中,当 解决方案显示在详细信息页面上,“解决方案注释”字段为 H1 应用于它的 HTML 格式:trigger t on Solution (before insert) { Trigger.new[0].SolutionNote ='<h1>hello</h1>'; }在以下示例中,当解决方案 显示在详细信息页面上,SolutionNote 字段仅包含:HelloGoodbyetrigger t2 on Solution (before insert) { Trigger.new[0].SolutionNote = '<javascript>Hello</javascript>Goodbye'; }有关详细信息,请参阅“HTML” Salesforce 中的“解决方案概述” 帮助。EscapeSequences:Apex 中的所有字符串都使用 与 SOQL 字符串相同的转义序列:(退格)、(制表符)、(换行符)、(换行符)、(回车符)、(双引号)、(单引号)和 (反斜杠)。\b\t \n\f\r\”\’\\比较运算符:与 Java 不同,Apex 字符串 支持使用比较运算符 、 、 、 和 。因为 Apex 使用 SOQL 比较语义,字符串的结果根据 上下文用户的区域设置,不区分大小写。查看更多 信息,请参阅表达式 运算符。==!=<<=>>=字符串方法:与 Java 一样, 可以使用多种标准方法操作字符串。查看更多 信息,请参阅 String 类。顶点 使用 API 版本 15.0 保存(编译)的类和触发器,以及 如果分配的 String 值为 对于这个领域来说太长了。
时间指示特定时间的值。始终创建时间值 使用系统静态方法。请参阅时间类。

此外,两种非标准基元数据类型不能用作变量或方法 类型,但确实出现在系统静态方法中:

  • 任意类型。静态方法转换 将 AnyType 类型的 sObject 字段设置为标准基元。AnyType 在 Lightning Platform 数据库专门用于字段历史记录跟踪中的 sObject 字段 表。valueOf
  • 货币。静态的 方法创建一个 Currency 类型的文本。此方法仅在 SOQL 中使用 和 SOSL 条款进行过滤 sObject 货币字段。您不能在任何其他类型的 顶点。Currency.newInstanceWHERE

有关 AnyType 数据类型的详细信息,请参阅对象中的字段类型 Salesforce 参考。

版本化行为更改

在 API 版本 16 (Summer ’09) 及更高版本中,Apex 使用更高精度的 Decimal 数据 键入某些类型,例如货币。

收集

Apex 中的集合可以是列表、集合或映射。

注意

没有限制 集合可以容纳的项数。但是,有一个一般的限制 堆大小。

  • 列表 列表
    是元素的有序集合,这些元素通过其索引进行区分。列表元素可以是任何数据类型,包括基元类型、集合、sObjects、用户定义类型和内置 Apex 类型。
  • 集合 集合是不包含任何重复项的元素的无序集合
    。Set 元素可以是任何数据类型,包括基元类型、集合、sObjects、用户定义类型和内置 Apex 类型。
  • 映射 映射
    是键值对的集合,其中每个唯一键映射到单个值。键和值可以是任何数据类型,包括基元类型、集合、sObjects、用户定义类型和内置 Apex 类型。
  • 通常,参数化类型化 Apex
    是一种静态类型的编程语言,这意味着用户必须先指定变量的数据类型,然后才能使用该变量。

列表

列表是元素的有序集合,这些元素按其索引进行区分。 列表元素可以是任何数据类型,包括基元类型、集合、sObjects、 用户定义类型和内置 Apex 类型。

下表是字符串列表的可视化表示形式:

索引 0索引 1索引 2索引 3索引 4索引 5
“红色”“橙色”“黄色”“绿色”“蓝色”“紫色”

列表中第一个元素的索引位置始终为 0。

列表可以包含任何集合,并且可以相互嵌套并成为 多面的。例如,您可以有一个整数集列表列表。一个列表 其中最多可以包含七级嵌套集合,即最多八级 整体水平。

若要声明列表,请使用关键字 followed 基元数据、sObject、嵌套列表、映射或集类型在 <> 个字符以内。 例如:List

// Create an empty list of String
List<String> my_list = new List<String>();
// Create a nested list
List<List<Set<Integer>>> my_list_2 = new List<List<Set<Integer>>>();

若要访问列表中的元素,请使用 Apex 提供的方法。例如:List

List<Integer> myList = new List<Integer>(); // Define a new list
myList.add(47);                    // Adds a second element of value 47 to the end 
                                       // of the list
Integer i = myList.get(0);                   // Retrieves the element at index 0
myList.set(0, 1);                           // Adds the integer 1 to the list at index 0
myList.clear();                    // Removes all elements from the list

有关更多信息(包括所有支持的方法的完整列表),请参见 List Class。

使用一维数组表示法 列表

使用基元或对象的一维列表时,可以 还可以使用更传统的数组表示法来声明和引用列表元素。为 例如,可以通过以下方式声明基元或对象的一维列表 在数据类型名称后面加上 [] 字符:

String[] colors = new List<String>();

这两个语句等效于前面的语句:

List<String> colors = new String[1];
String[] colors = new String[1];

自 引用一维列表的一个元素,也可以跟在 在方括号中包含元素索引位置的列表。为 例:

colors[0] = 'Green';

甚至 虽然前一个数组的大小 定义为一个元素(括号中的数字),列表是弹性的,可以增长 根据需要,前提是使用该方法添加新元素。例如 您可以向列表中添加两个或多个元素。但是,如果您使用方括号添加 元素,则该列表的行为类似于数组,并且没有弹性,也就是说, 不允许添加比声明的数组更多的元素 大小。Stringnew String[1]Listaddcolors

所有列表都初始化为 。可以使用文字为列表赋值和分配内存 表示法。例如:null

描述
List<Integer> ints = new Integer[0];定义大小为零且不带元素的整数列表
List<Integer> ints = new Integer[6];定义一个整数列表,其中为六个分配了内存 整数
  • 列表排序
    可以对列表元素进行排序,排序顺序取决于元素的数据类型。

列表排序

您可以对列表元素进行排序,排序顺序取决于 元素。

使用该方法,您可以对 一个列表。对于基元数据类型的元素(如字符串),排序按升序排列。 其他更复杂的数据类型的排序顺序在介绍这些类型的章节中进行了描述 数据类型。List.sort

此示例演示如何对字符串列表进行排序并验证颜色是否在 列表中的升序。

List<String> colors = new List<String>{
    'Yellow',
    'Red',
    'Green'};
colors.sort();
System.assertEquals('Green', colors.get(0));
System.assertEquals('Red', colors.get(1));
System.assertEquals('Yellow', colors.get(2));

对于 Visualforce SelectOption 控件,根据值按升序排序 和标签字段。请参阅下一节,了解用于 选择选项。

的默认排序顺序 选择选项

该方法对 SelectOption 元素进行排序 使用“值”和“标签”字段进行升序排序,并基于此比较序列。

List.sort

  1. 值字段首先用于排序。
  2. 如果两个值字段具有相同的值或都为空,则标签字段为 使用。

请注意,禁用的字段不用于排序。

对于文本字段,排序算法使用 Unicode 排序顺序。此外,空字段在前面 排序顺序中的非空字段。

在此示例中,列表包含三个 SelectOption 元素。Two elements, 美国 和墨西哥,具有相同的值字段(‘A’)。该方法根据 label 字段,并将墨西哥置于美国之前,如输出中所示。最后 排序列表中的元素是 Canada,并按其值字段 ‘C’ 排序, 它位于“A”之后。List.sort

List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('A','United States'));
options.add(new SelectOption('C','Canada'));
options.add(new SelectOption('A','Mexico'));
System.debug('Before sorting: ' + options);
options.sort();
System.debug('After sorting: ' + options);

这是 debug 语句的输出。它显示 排序。

DEBUG|Before sorting: (System.SelectOption[value="A", label="United States", disabled="false"], 
  System.SelectOption[value="C", label="Canada", disabled="false"], 
  System.SelectOption[value="A", label="Mexico", disabled="false"])
DEBUG|After sorting: (System.SelectOption[value="A", label="Mexico", disabled="false"], 
  System.SelectOption[value="A", label="United States", disabled="false"], 
  System.SelectOption[value="C", label="Canada", disabled="false"])

Set

集合是不包含任何重复项的元素的无序集合。设置 元素可以是任何数据类型,包括基元类型、集合、sObjects、用户定义 类型和内置 Apex 类型。

下表表示一组使用城市名称的字符串:

“旧金山”“纽约”“巴黎”“东京”

集合可以包含可以相互嵌套的集合。例如,您可以 有一组整数集的列表。一个集合最多可以包含七个嵌套级别 其中的集合,即总共最多八个级别。若要声明集合,请使用关键字 followed 按 <> 个字符以内的基元数据类型名称。为 例:

Set

Set<String> myStringSet = new Set<String>();

下面的示例演示如何创建具有两个硬编码字符串值的集合。

// Defines a new set with two elements
Set<String> set1 = new Set<String>{'New York', 'Paris'};

要访问集合中的元素,请使用 Apex 提供的系统方法。例如:

// Define a new set
Set<Integer> mySet = new Set<Integer>();
// Add two elements to the set
mySet.add(1);
mySet.add(3);
// Assert that the set contains the integer value we added
System.assert(mySet.contains(1)); 
// Remove the integer value from the set
mySet.remove(1);

下面的示例演示如何从另一个集合的元素创建集合。

// Define a new set that contains the
// elements of the set created in the previous example
Set<Integer> mySet2 = new Set<Integer>(mySet);
// Assert that the set size equals 1
// Note: The set from the previous example contains only one value
System.assert(mySet2.size() == 1);

有关更多信息(包括所有受支持的 set 系统方法的完整列表),请参见 Set Class。请注意集合的以下限制:

  • 与 Java 不同,Apex 开发人员不需要引用所使用的算法 在其声明中实现集合(例如,或 )。Apex 对所有集合都使用哈希结构。HashSetTreeSet
  • 集合是无序集合 – 您不能在 具体索引。您只能遍历设置的元素。
  • 集合元素的迭代顺序是确定性的,因此您可以依赖 顺序在每次后续执行相同代码时相同。

Map

映射是键值对的集合,其中每个唯一键映射到单个值。 键和值可以是任何数据类型,包括基元类型、集合、sObjects、用户定义 类型和内置 Apex 类型。

下表显示了国家和货币的地图:

国家/地区 (键)“美国”“日本”“法国”“英格兰”“印度”
货币(值)“美元”“日元”“欧元”“磅”“卢比”

映射键和值可以包含任何集合,并且可以包含嵌套集合。为 例如,您可以将整数映射到映射,而映射又将字符串映射到列表。地图 键最多可以包含七级嵌套集合,即最多八级 整体。

要声明映射,请使用关键字后跟 键的数据类型和字符内的值。例如:Map<>

Map<String, String> country_currencies = new Map<String, String>();
Map<ID, Set<String>> m = new Map<ID, Set<String>>();

可以将泛型或特定 sObject 数据类型用于映射。您还可以创建一个 映射的泛型实例。

与列表一样,在使用 curly 声明映射时,可以填充映射键值对 brace () 语法。在大括号内,指定 首先,然后使用 指定该键的值。例如:{}=>

Map<String, String> MyStrings = new Map<String, String>{'a' => 'b', 'c' => 'd'.toUpperCase()};

在第一个示例中,键的值是 ,键的值是 。abcD

若要访问地图中的元素,请使用 Apex 提供的 Map 方法。此示例创建一个地图 整数键和字符串值。它添加两个条目,检查第一个条目是否存在 key,检索第二个条目的值,最后获取所有键的集合。

Map<Integer, String> m = new Map<Integer, String>(); // Define a new map
m.put(1, 'First entry');                  // Insert a new key-value pair in the map
m.put(2, 'Second entry');                  // Insert a new key-value pair in the map
System.assert(m.containsKey(1));  // Assert that the map contains a key
String value = m.get(2);               // Retrieve a value, given a particular key
System.assertEquals('Second entry', value);
Set<Integer> s = m.keySet();       // Return a set that contains all of the keys in the map

有关详细信息(包括所有受支持的 Map 方法的完整列表),请参阅 Map 类。

Map注意事项

  • 与 Java 不同,Apex 开发人员不需要引用用于 在其声明中实现映射(例如,或 )。Apex 使用哈希 所有地图的结构。HashMapTreeMap
  • 映射元素的迭代顺序是确定性的。您可以信赖订单 在每次后续执行相同的代码时都是一样的。但是,我们建议始终 按键访问地图元素。
  • 映射键可以保存该值。null
  • 添加一个映射条目,其键与映射中的现有键匹配,会覆盖 现有条目,该键具有新条目。
  • String 类型的映射键区分大小写。仅因大小写而异的两个键是 被认为是唯一的,并具有相应的不同映射条目。随后,地图 方法,包括 、 、 和 处理这些键 作为不同的。putgetcontainsKeyremove
  • 用户定义类型的映射键的唯一性由您在你的班级。所有其他非基元类型的键的唯一性,例如 sObject 键, 通过比较对象的字段值来确定。
  • 仅当 Map 对象使用以下数据类型之一时,它才可序列化为 JSON 作为钥匙。
    • 布尔
    • 日期
    • 日期时间
    • 十进制
    • 枚举
    • 同上
    • 整数
    • 字符串
    • 时间

参数化类型化

一般来说,Apex 是一种静态类型的编程语言,这意味着用户必须 在使用变量之前,指定该变量的数据类型。这在 Apex 中是合法的:

Integer x = 1;

如果尚未定义,这是不合法的 早些时候:

x

x = 1;

列表、地图和集合在 Apex 中参数化:它们采用任何数据类型 Apex 支持它们作为论据。该数据类型必须替换为实际数据 在构建列表、地图或集时键入。为 例:

List<String> myList = new List<String>();

使用参数化列表进行子类型化

在 Apex 中,如果 type 是 的子类型,则将是 的子类型。例如,以下是 法律:

TUList<T>List<U>

List<String> slst = new List<String> {'alpha', 'beta'};
List<Object> olst = slst;

枚举

枚举是一种抽象数据类型,其值每个值都恰好采用 您指定的有限标识符集。枚举通常用于定义一组 否则没有数字顺序的可能值。典型的例子包括 一张牌的花色,或一年中的特定季节。

尽管每个值对应于一个不同的整数值,但枚举会隐藏此值 实现。隐藏实现可防止任何可能滥用的值 执行算术等。创建枚举、变量、方法参数和 可以声明该类型的返回类型。

注意

与 Java 不同,枚举类型本身没有构造函数语法。

要定义枚举,请在 声明并使用大括号来划分可能值的列表。例如 以下代码创建一个名为 :enumSeason

public enum Season {WINTER, SPRING, SUMMER, FALL}

通过创建枚举,您还可以 创建了一个名为 的新数据类型。您可以 像使用任何其他数据类型一样使用此新数据类型。例如:SeasonSeason

Season southernHemisphereSeason = Season.WINTER;

public Season getSouthernHemisphereSeason(Season northernHemisphereSeason) {

    if (northernHemisphereSeason == Season.SUMMER) return southernHemisphereSeason;
     //...
}

还可以将类定义为枚举。创建枚举类时,请勿在定义中使用关键字。class

public enum MyEnumClass { X, Y }

您可以在任何可以使用其他数据类型名称的地方使用枚举。如果将 类型为枚举的变量,分配给它的任何对象都必须是该枚举的实例 枚举类。

任何方法都可以使用枚举类型作为一部分 他们的签名。在这种情况下,关联的 WSDL 文件包括 枚举及其值,API 客户端可以使用。webservice

Apex 提供以下系统定义的枚举:

  • System.StatusCode这 枚举对应于 WSDL 文档中公开的 API 错误代码 所有 API 操作。为 例:StatusCode.CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY StatusCode.INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY完整的 状态代码列表在组织的 WSDL 文件中可用。为 有关访问组织的 WSDL 文件的更多信息,请参阅下载 Salesforce WSDL 和客户端身份验证 Salesforce 帮助中的证书。
  • System.XmlTag:此枚举返回用于分析方法的结果 XML 的 XML 标记列表。查看更多 信息,请参见 XmlStreamReader 类。webservice
  • System.ApplicationReadWriteMode: 此枚举指示组织在 Salesforce 升级和停机时间。有关更多信息,请参见 System.getApplicationReadWriteMode()。
  • System.LoggingLevel:此枚举与方法一起使用,以指定所有调用的日志级别。有关更多信息,请参见 System 类。system.debugdebug
  • System.RoundingMode:此枚举由执行数学运算的方法用于指定 操作的舍入行为。典型的例子是 Decimal 方法和 Double 方法。欲了解更多信息, 请参阅舍入模式。divideround
  • System.SoapType:此枚举由字段 describe result 方法返回。欲了解更多信息, 请参阅 SOAPType 枚举。getSoapType
  • System.DisplayType:此枚举由字段 describe result 方法返回。有关更多信息,请参见 DisplayType 枚举。getType
  • System.JSONToken:此枚举用于解析 JSON 内容。有关更多信息,请参见 JsonToken 枚举。
  • ApexPages.Severity:此枚举指定 Visualforce 消息的严重性。查看更多 信息,请参阅 ApexPages.Severity 枚举。
  • Dom.XmlNodeType:此枚举指定 DOM 文档中的节点类型。

注意

系统定义的枚举不能在 Web 服务中使用 方法。

所有枚举值(包括系统枚举)都具有与之关联的通用方法。为 有关详细信息,请参阅枚举方法。

不能将用户定义的方法添加到枚举值。

变量

局部变量是用 Java 样式语法声明的。与 Java 一样,多个变量 可以在单个语句中声明和初始化。

局部变量是用 Java 样式语法声明的。例如:

Integer i = 0;
String str;
List<String> strList;
Set<String> s;
Map<ID, String> m;

与 Java 一样,可以在单个语句中声明和初始化多个变量, 使用逗号分隔。例如:

Integer i, j, k;

Null 变量和初始值

如果您声明一个变量并且不使用值对其进行初始化,则它将是 .从本质上讲,意味着没有值。您还可以分配给使用基元声明的任何变量 类型。例如,这两个语句都会导致变量设置为:

nullnullnullnull

Boolean x = null;
Decimal d;

如果变量为 ,则数据类型上的许多实例方法将失败。在此示例中,第二个语句 生成异常 (

nullNullPointerException)

Date d;
d.addDays(2);

所有变量都初始化为 if 没有为它们分配值。例如,在以下示例中,和 是赋值,而整数变量和布尔变量设置为 ,因为它们未显式初始化。nullikjbnull

Integer i = 0, j, k = 1;
Boolean b;

注意

一个常见的陷阱是假设未初始化的布尔变量是 由系统初始化。这 事实并非如此。与所有其他变量一样,布尔变量如果不是,则为 null 显式分配一个值。false

可变范围

变量可以在块中的任何点定义,并从该点开始 向前。子块无法重新定义已使用的变量名称 在父块中,但并行块可以重用变量名称。例如:

Integer i;
{
   // Integer i;  This declaration is not allowed
}

for (Integer j = 0; j < 10; j++);
for (Integer j = 0; j < 10; j++);

区分大小写

避免与不区分大小写的 SOQL 混淆 和 SOSL 查询,Apex 也不区分大小写。这意味着:

  • 变量和方法名称不区分大小写。为 例:Integer I; //Integer i; This would be an error.
  • 对对象和字段名称的引用不区分大小写。为 例:Account a1; ACCOUNT a2;
  • SOQL 和 SOSL 语句不区分大小写。为 例:Account[] accts = [sELect ID From ACCouNT where nAme = 'fred'];

注意

稍后您将了解有关 sObjects、SOQL 和 SOSL 的更多信息 指导。

另请注意,Apex 使用与 SOQL 相同的过滤语义,即 是 SOAP API 和 Salesforce 用户界面中比较的基础。这 使用这些语义可能会导致一些有趣的行为。例如,如果 最终用户根据筛选器生成报告,以筛选 字母表(即值< ‘m’),结果中返回 null 字段。这 此行为的基本原理是,用户通常会想到没有值的字段 只是一个空格字符,而不是它的实际值。因此,在 Apex 中,以下表达式全部 计算结果为:nulltrue

String s;
System.assert('a' == 'A');
System.assert(s < 'b');
System.assert(!(s > 'b'));

注意

尽管在上面的示例中计算为 ,但会生成错误,因为 您正在尝试将字母与值进行比较。s < ‘b’true‘b.’compareTo(s)null

常数

顶点常量是其值在初始化后不会更改的变量 一次。可以使用关键字定义常量。

final

关键字表示变量可以是 最多分配一次,可以在声明本身中使用,也可以使用静态初始值设定项 方法,如果常量是在类中定义的。此示例声明两个常量。这 首先在声明语句中初始化。第二个在 static 块,通过调用 static 方法。final

public class myCls {
   static final Integer PRIVATE_INT_CONST = 200;
   static final Integer PRIVATE_INT_CONST2; 

   public static Integer calculate() {
       return 2 + 7;
   }

   static {
       PRIVATE_INT_CONST2 = calculate();
   }
}

Apex入门

什么是Apex?

Apex 是一种强类型、面向对象的编程语言,允许开发人员 在 Salesforce 服务器上执行流和事务控制语句,并结合 对 API 的调用。使用看起来像 Java 的语法,并且像存储的数据库一样 过程中,Apex 使开发人员能够将业务逻辑添加到大多数系统事件中,包括 按钮单击、相关记录更新和 Visualforce 页面。Apex 代码可以通过以下方式启动 Web 服务请求和来自对象上的触发器的请求。

作为一种语言,Apex 是:

综合
Apex 提供对常见 Lightning 平台习惯用语的内置支持,包括:
  • 数据操作语言 (DML) 调用,例如 、 和 ,包括内置处理INSERT UPDATE DELETE DmlException
  • 内联 Salesforce 对象查询语言 (SOQL) 和 Salesforce 对象 返回 sObject 记录列表的搜索语言 (SOSL) 查询
  • 允许一次批量处理多条记录的循环
  • 防止记录更新冲突的锁定语法
  • 可从存储的 Apex 方法构建的自定义公共 API 调用
  • 用户尝试编辑或删除自定义项时发出的警告和错误 Apex 引用的对象或字段
简单易用
Apex 基于熟悉的 Java 习语,例如变量和表达式语法, 块和条件语句语法、循环语法、对象和数组表示法。 在 Apex 引入新元素的地方,它使用简单的语法和语义 了解并鼓励有效使用 Lightning 平台。因此 Apex 生成的代码既简洁又易于编写。
以数据为中心
Apex 旨在将多个查询和 DML 语句串联成一个 Salesforce 服务器上的单个工作单元。开发人员使用存储的数据库 将数据库上的多个事务语句串联在一起的过程 服务器以类似的方式。与其他数据库存储过程一样,Apex 不 尝试为在用户中呈现元素提供常规支持 接口。
严格
Apex 是一种强类型语言,它使用对架构对象的直接引用 例如对象和字段名称。如果有的话,它在编译时会很快失败 引用无效。它存储所有自定义字段、对象和类 元数据中的依赖项,以确保它们不会在需要时被删除 活动 Apex 代码。
托管
Apex 完全由闪电解释、执行和控制 平台。
多租户感知
与 Lightning 平台的其他部分一样,Apex 在多租户环境中运行。 因此,Apex 运行时引擎旨在密切防止代码失控, 防止其垄断共享资源。任何违反限制的代码 失败,并显示易于理解的错误消息。
易于测试
Apex 为单元测试的创建和执行提供内置支持。它包括 测试结果,指示覆盖了多少代码,以及 代码可以更有效率。Salesforce 确保所有自定义 Apex 代码都能正常工作 如预期的那样,在任何平台升级之前执行所有单元测试。
版本化
您可以针对不同版本的 API 保存 Apex 代码。这样可以 你保持行为。

了解 Apex 核心概念

Apex 代码通常包含许多您可能熟悉的其他代码 编程语言。
Apex 中的编程元素

本节介绍了 Apex 的基本功能,以及一些核心 概念。

使用版本设置

在 Salesforce 用户界面中,您可以指定 Salesforce API 的版本 保存 Apex 类或触发器的对象。此设置不仅指示 要使用的 SOAP API 版本,以及 Apex 的版本。您可以更改 保存后的版本。每个类或触发器名称都必须是唯一的。你不能 保存相同的类或针对不同版本的触发器。

还可以使用版本设置将类或触发器与特定 组织中安装的托管包的版本 AppExchange。此版本的托管软件包将继续由 类或触发器(如果安装了更高版本的托管包),除非您 手动更新版本设置。要将已安装的托管软件包添加到 设置列表中,从可用包列表中选择一个包。列表是 仅当已安装的托管包尚未安装时显示 与类或触发器相关联。

有关对托管包使用版本设置的更多信息,请参阅 Salesforce 联机帮助中的关于包版本

命名变量、方法和类

在命名变量、方法或 类。这些包括属于 Apex 和 Lightning 平台的单词,例如 作为 、 或 以及保留 关键字。list test account

使用变量和表达式

Apex 是一种强类型语言,也就是说,您必须声明数据 首次引用变量时的类型。Apex 数据类型包括基本类型 例如 Integer、Date 和 Boolean,以及更高级的类型,例如列表、 maps、objects 和 sObjects。

变量使用名称和数据类型进行声明。您可以将值赋给 变量。您也可以稍后分配值。使用以下命令 声明变量时的语法:

datatypevariable_name [ = value];
 

提示

请注意,上述末尾的分号不是可选的。所有语句必须以分号结束。

以下是变量声明的示例:

// The following variable has the data type of Integer with the name Count, 
// and has the value of 0.
Integer Count = 0;
// The following variable has the data type of Decimal with the name Total. Note 
// that no value has been assigned to it.
Decimal Total;
// The following variable is an account, which is also referred to as an sObject.
Account MyAcct = new Account();

在 Apex 中,将传递所有原始数据类型参数,例如 Integer 或 String 按值进入方法。这一事实意味着对参数的任何更改都只存在 在方法的范围内。当该方法返回时,对 参数丢失。

非基元数据类型参数(如 sObjects)通过以下方式传递到方法中 参考。因此,当方法返回时,传入的参数仍然 引用与方法调用之前相同的对象。在方法中, 引用不能更改为指向另一个对象,但 对象的字段可以更改。

using 语句

语句是执行操作的任何编码指令。

在 Apex 中,语句必须以分号结尾,并且可以是以下类型之一:
  • 赋值,例如为变量赋值
  • 条件 (if-else)
  • 循环:
    • 同时做
  • 锁定
  • 数据操作语言 (DML)
  • 交易控制
  • 方法调用
  • 异常处理

是用 curly 组合在一起的一系列语句 大括号,可以在允许单个语句的任何地方使用。为 例:

if (true) {
    System.debug(1);
    System.debug(2);
} else {
    System.debug(3);
    System.debug(4);
}

如果一个块仅包含一个语句,则可以保留大括号 关闭。例如:

if (true) 
    System.debug(1);
else 
    System.debug(2);

使用集合

Apex 具有以下类型的集合:

  • 列表(数组)
  • 地图

列表是元素的集合,例如整数、字符串、对象或 其他集合。当元素的顺序很重要时,使用列表。你可以有 列表中的重复元素。

列表中的第一个索引位置始终为 0。

要创建列表:

  • 使用关键字new
  • 使用关键字后跟 包含在字符中的元素类型。List<>

使用以下语法创建列表:

List <datatype> list_name
   [= new List<datatype>();] |
   [=new List<datatype>{value [, value2. . .]};] |
   ;

下面的示例创建一个 Integer 列表,并将其分配给变量 。请记住,由于 Apex 是强类型的, 您必须将 的数据类型声明为 整数列表。My_ListMy_List

List<Integer> My_List = new List<Integer>();

有关详细信息,请参阅列表

集合是唯一的、无序元素的集合。它可以包含 基元数据类型,如 String、Integer、Date 等。它还可以包含更多 复杂数据类型,例如 sObjects。

要创建集合,请执行以下操作:

  • 使用关键字new
  • 使用关键字后跟 包含在字符中的原始数据类型Set<>

使用以下语法创建集:

Set<datatype> set_name 
   [= new Set<datatype>();] |
   [= new Set<datatype>{value [, value2. . .] };] |
   ;

下面的示例创建一组 String。集合的值是使用 大括号。{}

Set<String> My_String = new Set<String>{'a', 'b', 'c'};

有关详细信息,请参阅

映射是键值对的集合。键可以是任何原始数据 类型。值可以包括基元数据类型,以及对象和其他集合。 按关键事项查找内容时,请使用地图。地图中可以有重复的值, 但每个键必须是唯一的。

要创建地图:

  • 使用关键字new
  • 使用关键字后跟键值对 对,用逗号分隔并用字符括起来。Map<>

使用以下语法创建映射:

Map<key_datatype, value_datatype> map_name
   [=new map<key_datatype, value_datatype>();] | 
   [=new map<key_datatype, value_datatype>
   {key1_value => value1_value 
   [, key2_value => value2_value. . .]};] |
   ;

以下示例创建一个映射,该映射的数据类型为 Integer 的键和 值的字符串。在此示例中,将传入映射的值 在地图所在的大括号之间 创建。{}

Map<Integer, String> My_Map = new Map<Integer, String>{1 => 'a', 2 => 'b', 3 => 'c'};

有关详细信息,请参阅地图。

使用分支

语句是真假测试, 使应用程序能够根据条件执行不同的操作。基本 语法如下:if

if (Condition){
// Do this if the condition is true
} else {
// Do this if the condition is not true
}

有关更多信息,请参见条件 (If-Else) 语句。

使用循环

虽然该语句使你的 应用程序根据条件来做事,循环告诉你的应用程序做 基于条件一次又一次地做同样的事情。Apex 支持以下类型 循环数:if

  • 同时做

Do-while 循环在代码执行后检查条件。

While 循环在代码开始之前检查条件 执行。

For 循环使您能够更精细地控制 循环。此外,Apex 还支持传统的 For 循环,您可以在其中设置 条件,以及使用列表和 SOQL 查询作为 条件。

什么时候应该使用Apex?

Salesforce 预构建应用程序提供强大的 CRM 功能性。此外,Salesforce 还提供了自定义预构建的功能 适合您组织的应用程序。但是,您的组织可能具有复杂的 现有功能不支持的业务流程。在本例中, Lightning Platform 为高级管理员和开发人员提供了多种方式 构建自定义功能。

Apex

如果您想要执行以下操作,请使用 Apex:
  • 创建 Web 服务。
  • 创建电子邮件服务。
  • 对多个对象执行复杂的验证。
  • 创建工作流不支持的复杂业务流程。
  • 创建自定义事务逻辑(在整个 事务,而不仅仅是单个记录或对象)。
  • 将自定义逻辑附加到另一个操作,例如保存记录,以便 每当执行操作时,它都会发生,而不管它是否 源自用户界面、Visualforce 页面或 SOAP API。

闪电组件

开发 Lightning 组件以自定义 Lightning Experience、Salesforce 移动版 应用程序,或构建自己的独立应用程序。您也可以使用开箱即用的 组件以加快开发速度。

从 Spring ’19(API 版本 45.0)开始,您可以使用两个 编程模型:Lightning Web 组件模型和原始 Aura 组件模型。Lightning Web 组件是使用 HTML 构建的自定义 HTML 元素 和现代 JavaScript。Lightning Web 组件和 Aura 组件可以共存,并且 在页面上进行互操作。将 Lightning Web 组件和 Aura 组件配置为 在 Lightning App Builder 和 Experience Builder 中工作。管理员和最终用户不会 了解用于开发组件的编程模型。对他们来说,他们是 简单的闪电组件。

视觉力

Visualforce 由基于标签的标记语言组成 这为开发人员提供了一种更强大的构建应用程序和自定义方式 Salesforce 用户界面。借助 Visualforce,您可以:
  • 生成向导和其他多步骤过程。
  • 通过应用程序创建自己的自定义流控制。
  • 定义导航模式和特定于数据的规则,以实现最佳、高效 应用程序交互。

SOAP API

如果要将功能添加到 一次只处理一种类型的记录的复合应用程序,并且 不需要任何事务控制(例如设置保存点或回滚) 更改)。

Apex 是如何工作的?

所有 Apex 都完全在 Lightning 平台上按需运行。开发人员编写和保存 Apex 代码到平台,最终用户通过用户触发 Apex 代码的执行 接口。
Apex 完全编译、存储和运行 在闪电平台上

当开发人员编写 Apex 代码并将其保存到平台时,平台应用程序 服务器首先将代码编译成一组抽象的指令,这些指令可以 由 Apex 运行时解释器理解,然后将这些指令另存为 元数据。

当最终用户触发 Apex 的执行时,可能通过单击按钮或 访问 Visualforce 页面时,平台应用程序服务器会检索已编译的 来自元数据的指令,并在之前通过运行时解释器发送它们 返回结果。最终用户观察到执行时间与以下方面没有差异 标准平台请求。

在云中开发代码

Apex 编程语言保存并在云中运行,即多租户 平台。Apex 是为平台上的数据访问和数据操作量身定制的,它 使您能够将自定义业务逻辑添加到系统事件中。虽然它提供了许多好处 对于平台上的业务流程自动化,它不是通用编程 语言。
Apex 不能用于:
  • 在用户界面中呈现错误消息以外的元素
  • 更改标准功能 – Apex 只能阻止该功能 ,或添加其他功能
  • 创建临时文件
  • 生成线程

提示

所有 Apex 代码都在 Lightning 平台上运行,该平台是所有人使用的共享资源 其他组织。为了保证一致的性能和可伸缩性, Apex 的执行受调控器限制的约束,这些限制确保没有单个 Apex 执行 影响 Salesforce 的整体服务。这意味着所有 Apex 代码都受到以下限制 它可以在一个操作中执行的操作数(例如 DML 或 SOQL) 过程。

所有 Apex 请求都返回一个包含 1 到 50,000 条记录的集合。你 不能假定您的代码一次只适用于一条记录。因此,你 必须实现考虑批量处理的编程模式。如果你 不要,您可能会遇到调速器限制。

什么是 Apex 开发流程?

要开发 Apex,请获取一个 Developer Edition 帐户,编写并测试您的代码,然后 部署代码。
我们建议采用以程来开发 Apex:
  1. 获取 Developer Edition 帐户。
  2. 学习 更多关于 Apex.apex
  3. 写下你的 apex。
  4. 在编写 Apex 时,您还应该编写测试。
  5. (可选)将 Apex 部署到沙盒组织并执行最终单元 测试。
  6. 部署 您的 Apex 到 Salesforce 生产组织。

除了部署 Apex 之外,一旦编写和测试,您还可以 同时添加您的类和 触发器 AppExchange 应用程序包。

创建开发人员或沙盒组织

您可以在生产组织、开发人员组织或沙盒组织中运行 Apex。您可以 在开发人员组织或沙盒组织中开发 Apex,但不在生产组织中开发。
  • 生产组织 – 有实时用户访问您的 数据
  • 开发人员组织 – 使用 Developer Edition 创建的组织 帐户
  • 沙盒组织 – 在生产组织上创建的组织,它是 生产组织的副本
 

注意

Apex 触发器在 Salesforce 试用版中可用。但是,它们是 转换为任何其他版本时禁用。如果您新注册的组织包括 Apex,使用其中一种部署方法将代码部署到您的组织。

您无法在 Salesforce 中开发 Apex 生产组织。在开发过程中访问系统的实时用户可以 破坏数据稳定性或损坏应用程序。相反,做你所有的 在沙盒或 Developer Edition 组织中进行开发工作。

如果您还不是开发者社区的成员,请转到 https://developer.salesforce.com/signup 和 按照说明注册 Developer Edition 帐户。开发人员 通过 Edition 帐户,您可以访问免费的 Developer Edition 组织。即使你 已拥有 Professional、Enterprise、Unlimited 或 Performance Edition 组织,以及 用于创建 Apex 的沙盒,我们强烈建议您利用 开发人员社区中提供的资源。

 

注意

您无法使用 Salesforce 用户界面在 Salesforce 生产组织。

要创建沙盒组织,请执行以下操作:

  1. 在“设置”中,在“快速”中输入沙盒 查找框,然后选择沙盒
  2. 单击新建沙盒
  3. 输入沙盒的名称(不超过 10 个字符)和描述。

    我们建议您选择一个符合以下条件的名称:

    • 反映此沙盒的用途,例如 QA。
    • 只有几个字符,因为 Salesforce 将沙盒名称附加到 沙盒环境中用户记录的用户名。字符较少的名称使 沙盒登录更易于键入。
  4. 选择所需的沙盒类型。

    如果您没有看到沙盒选项或需要许可证以获取更多许可证,请联系 Salesforce 为您的组织订购沙盒。

    如果您减少了购买的沙盒数量,则需要匹配该数量 的沙盒数量为购买的数量。例如,如果有两个 Full 沙盒但只购买了一个,则无法创建完整沙盒。相反,将 将完整沙盒更改为较小的沙盒,例如 Developer Pro 或 Developer 沙盒,具体取决于 您有可用的类型。

  5. 选择要包含在“部分副本”或“完整”沙盒中的数据。
    • 对于“部分复制”沙盒,单击“下一步”,然后选择 您创建的模板,用于指定沙盒的数据。如果您尚未创建 模板,请参阅创建或编辑沙盒模板。
    • 对于“完整沙盒”,单击“下一步”,然后确定数据量 包括。
      • 要为完整沙盒包含基于模板的数据,请选择现有沙盒 模板。有关更多信息,请参阅创建或编辑沙盒模板
      • 要将所有数据包含在完整沙盒中,请选择是否字段以及字段大小 跟踪要包含的历史数据,以及是否复制 Chatter 数据。Chatter 数据 包括源、消息和主题,并用于影响 您的沙盒副本。减少复制的数据量可以显著加快速度 沙盒复制时间。
  6. 若要在每次创建和刷新此沙盒后运行脚本,请指定 Apex 类 您之前从 SandboxPostCopy 接口创建。
  7. 对于“沙盒访问”,选择“用户组”以选择公共用户 包含需要访问沙盒的用户的组,或选择“全部” 活跃用户
  8. 单击创建
     

    学习 Apex

    拥有开发者帐户后,有许多资源可供您使用 了解 Apex
    Apex Trailhead 内容
    初级和中级程序员
    多个 Trailhead 模块提供了有关学习 Apex 的教程。使用这些模块 了解 Apex 的基础知识以及如何在 Lightning 上使用它 平台。使用 Apex 通过触发器、单元测试、 异步 Apex、REST Web 服务和 Visualforce 控制器。
    快速入门:Apex
    Apex 基础知识 &数据库
    Apex 触发器
    Apex 集成 服务业
    Apex 测试
    异步 Apex
    Salesforce 开发人员 Apex 页面
    初级和高级程序员
    Salesforce Developers 上的 Apex 页面包含指向多个 资源,包括有关 Apex 编程语言的文章。这些 资源提供了对 Apex 的快速介绍,并包括 Apex开发。
    Lightning 平台代码示例和 SDK
    初级和高级程序员
    开源代码示例和 SDK、参考代码和最佳实践可以是 在代码示例和 软件开发工具包。一个简明、有意义的 Apex 代码示例库,用于 遵循最佳实践的常见用例可以在 Apex-recipes 中找到。
    开发生命周期:Lightning平台上的企业开发
    架构师和高级程序员
    应用程序生命周期和开发 Trailhead 上的模型模块可帮助您了解如何使用该应用程序 闪电平台上的生命周期和开发模型。
    培训课程
    Salesforce Trailhead Academy 还提供培训课程。发展和验证您的 具有 Salesforce 凭据的技能。
    在本书中 (Apex 开发人员指南)
    初级程序员可以查看以下内容:
    • 介绍 Apex,并在 特定:
      • 文档 约定
      • 核心概念
      • 快速上手 教程
    • 类、对象和接口
    • 测试 Apex
    • 执行调控器和限制
    此外,高级程序员可以查看:
    • 触发器和批量请求最佳实践
    • 高级 Apex 编程 例
    • 了解 Apex Describe 信息
    • 异步执行(@future注释)
    • Batch Apex 和 Apex 调度程序

    使用开发环境编写 Apex

    有几种开发环境可用于开发 Apex 代码。开发商 控制台和 Visual Studio Code 的 Salesforce 扩展允许您编写、测试和 调试您的 Apex 代码。用户界面中的代码编辑器仅允许编写代码和 不支持调试。

    开发者控制台

    Developer Console 是一个集成开发环境,其中包含 可用于在 Salesforce 中创建、调试和测试应用程序的工具 组织。

    Developer Console 支持以下任务:
    • 编写代码 – 您可以使用源代码编辑器添加代码。另外,你 可以浏览组织中的包。
    • 编译代码 – 保存触发器或类时,代码为 自动编译。任何编译错误都会被报告。
    • 调试 – 您可以查看调试日志并设置有助于 调试。
    • 测试 – 可以执行特定测试类或所有测试的测试 ,您可以查看测试结果。此外,您可以检查 代码覆盖率。
    • 检查性能 – 您可以检查调试日志以查找性能 瓶颈。
    • SOQL 查询 – 您可以查询组织中的数据并查看 使用查询编辑器的结果。
    • 颜色编码和自动完成 – 源代码编辑器使用颜色 方案,使代码元素更容易阅读,并提供自动完成功能 用于类和方法名称。

    适用于 Visual Studio Code 的 Salesforce 扩展

    适用于 Visual Studio Code 的 Salesforce 扩展包包括用于在 Salesforce 平台上以轻量级、 可扩展的 VS Code 编辑器。这些工具提供了用于开发的功能 orgs(临时组织、沙盒和 DE 组织)、Apex、Aura 组件和 视觉力。

    有关安装和使用的信息,请参阅 web网站。

     

    提示

    如果您想开发自己的 Apex IDE,SOAP API 包括 编译触发器和类以及执行测试方法的方法,而 元数据 API 包括用于将代码部署到生产环境的方法。为 有关更多信息,请参阅部署 Apex 和使用 SOAP API 部署 Apex。

    Salesforce 用户界面中的代码编辑器

    Salesforce 用户 接口。所有类和触发器在保存时都会被编译,任何语法 错误被标记。在代码编译完毕且没有错误之前,无法保存代码。这 Salesforce 用户界面还会对代码中的行进行编号,并使用颜色编码来 区分不同的元素,例如注释、关键字、文本字符串等。
    • 对于对象上的触发器,请从对象的管理设置中转到 触发器,单击“新建”,然后在“正文”文本框中输入代码。
    • 对于课程,请从“设置”中输入“快速查找”框,然后选择“Apex” 类。单击“新建”,然后输入你的 正文文本框中的代码。Apex Classes
     

    注意

    您无法使用 Salesforce 用户界面在 Salesforce 生产组织。

    或者,您可以使用任何文本编辑器(如记事本)来编写 Apex 代码。然后 将代码复制并粘贴到应用程序中,或使用 API 调用之一 部署它。

    编写测试

    测试是成功长期发展的关键,也是 开发过程。我们强烈建议您使用测试驱动的 开发过程,即与 代码开发。

    为了促进健壮、无错误的代码的开发,Apex 支持创建和 执行单元测试。单元测试是验证 特定代码段工作正常。单元测试方法不带任何参数, 不向数据库提交任何数据,也不发送电子邮件。此类方法在方法定义中使用注释进行标记。 单元测试方法必须在测试类中定义,即用 批注的类。@IsTest@IsTest

     

    注意

    上的注释 methods 等同于关键字。如 最佳做法,Salesforce 建议您使用 而不是 .关键字可以在 未来版本。@IsTesttestMethod@IsTesttestMethodtestMethod

    此外,在部署 Apex 或将其打包之前 AppExchange,则必须满足以下条件。

    • 单元测试必须至少覆盖 75% 的 Apex 代码,并且所有这些测试都必须 成功完成。

      请注意以下事项。

      • 将 Apex 部署到生产组织时,每个单元测试 默认情况下,将执行 Organization 命名空间。
      • 调用不计入 Apex 代码的一部分 覆盖。System.debug
      • 测试方法和测试类不计为 Apex 代码的一部分 覆盖。
      • 虽然只有 75% 的 Apex 代码必须被测试覆盖,但不要专注于 所覆盖代码的百分比。相反,请确保每次使用 涵盖您的申请案例,包括正面和负面案例, 以及批量和单条记录。这种方法可确保 75% 或更多 的代码包含在单元测试中。
    • 每个触发器都必须具有一定的测试覆盖率。
    • 所有类和触发器都必须成功编译。

    有关编写测试的详细信息,请参阅测试 Apex。

    将 Apex 部署到沙盒组织

    沙盒在单独的环境中创建 Salesforce 组织的副本。将它们用于 开发、测试和训练,而不会影响 生产组织。沙盒与您的生产组织隔离,因此您的 在沙盒中执行不会影响生产组织。

    将 Apex 从适用于 Visual Studio Code 的 Salesforce 扩展中的本地项目部署到 Salesforce 组织,请参阅 Salesforce Extensions for Visual Studio 代码。

    您还可以使用元数据 API 调用来 将 Apex 从开发人员组织部署到沙盒组织。deploy()

    一个有用的 API 调用是 。在开发中或 沙盒组织,可以对特定类运行单元测试,列表 类或命名空间。runTests()

    您还可以使用 Salesforce CLI。有关详细信息,请参阅针对任何组织进行开发。

    有关更多信息,请参阅部署 Apex。

    将 Apex 部署到 Salesforce 生产组织

    完成所有单元测试并验证 Apex 代码 正确执行,最后一步是将 Apex 部署到您的 Salesforce 生产中 组织。

    在 Visual Studio Code 编辑器中将 Apex 从本地项目部署到 Salesforce 组织,请参阅适用于 Visual Studio 的 Salesforce 扩展 代码。

    此外,您还可以通过 Salesforce 用户界面中的更改集来部署 Apex。

    有关更多信息和其他部署选项,请参阅部署 Apex 和构建和发布您的应用程序。

    将 Apex 代码添加到 AppExchange 应用程序

    您可以在为其创建的应用中包含 Apex 类或触发器 AppExchange。

    作为包的一部分包含的任何 Apex 必须至少具有 75% 的累积测试覆盖率。每个触发器还必须具有一定的测试覆盖率。当你 将您的软件包上传到 AppExchange,将运行所有测试以确保它们在没有 错误。此外,当包安装在 安装程序的组织。您可以指定在打包期间应运行哪些测试 通过用 注释它们来安装。包必须通过此测试子集 安装成功。@isTest(OnInstall=true)@isTest(OnInstall=true)

    创建自定义对象

    在此步骤中,您将创建一个名为 Book 的自定义对象,其中包含一个名为 价格。
    先决条件:

    沙盒 Professional 中的 Salesforce 帐户, Enterprise、Performance 或 Unlimited Edition 组织,或开发人员中的帐户 组织。

    有关创建沙盒组织的更多信息,请参阅 Salesforce 帮助中的“沙盒类型和模板”。要注册 免费的开发者组织,请参阅 Developer Edition 环境注册页面。

    1. 登录到您的沙盒或开发人员组织。
    2. 从自定义对象的管理设置中(如果您使用的是 Salesforce) “经典”,请单击“新建自定义对象”,或者如果您使用的是 Lightning Experience,选择“创建”|”自定义对象
    3. 输入“书籍”作为标签。
    4. 输入 Books 作为复数标签。
    5. 点击保存
      哒哒!现在,您已经创建了第一个自定义对象。现在让我们创建一个 自定义字段。
    6. “自定义字段和关系”部分中 图书详情页面,点击新建
    7. 选择“数字”作为数据类型,然后单击“下一步”。
    8. 输入字段标签的价格
    9. 在长度文本框中输入 16。
    10. 在小数位文本框中输入 2,然后单击下一步
    11. 单击“下一步”接受字段级的默认值 安全。
    12. 点击保存
    您刚刚创建了一个名为 Book 的自定义对象,并将自定义字段添加到 该自定义对象。自定义对象已经有一些标准字段,例如 Name 和 CreatedBy,并允许您添加更特定于 实现。在本教程中,Price 字段是 Book 对象的一部分,它是 由您将在下一步中编写的 Apex 类访问。

     

    添加 Apex 类

    在此步骤中,您将添加一个 Apex 类,该类包含用于更新书籍的方法 价格。此方法由将在下一个中添加的触发器调用 步。
    先决条件:
    • 沙盒中的 Salesforce 帐户 Professional、Enterprise、Performance 或 Unlimited Edition 组织,或开发人员组织中的帐户。
    • 这本书 自定义对象。
    1. 在“设置”中,在“快速查找”框中输入“Apex Classes”, 然后选择 Apex 类并单击新建
    2. 在类编辑器中,输入以下类定义:
      public class MyHelloWorld {
      
      }
      前面的代码是要向其添加一个的类定义 方法。Apex 代码通常包含在类中。此类定义为 ,其中 表示该类可供其他 Apex 类和触发器使用。查看更多 信息,请参阅类、对象和 接口。public
    3. 在类开始和结束之间添加此方法定义 括弧。
      public static void applyDiscount(Book__c[] books) {
         for (Book__c b :books){
            b.Price__c *= 0.9;
         }
      }

      此方法称为 , 它既是公共的,也是静态的。因为它是一个静态方法,所以你不需要 需要创建类的实例才能访问该方法,您可以 只需使用类的名称后跟点 (.) 和 方法。有关更多信息,请参见静态方法和实例方法。 变量和初始化代码。applyDiscount

      此方法采用一个参数,即 Book 记录列表,该参数分配给 变量 。请注意对象名称中的 。这表示它是您创建的自定义对象。标准对象 在 Salesforce 应用程序中提供的内容(例如帐户)不会以 this 结尾 后缀。books__cBook__c

      代码的下一部分包含方法定义的其余部分:

      for (Book__c b :books){
         b.Price__c *= 0.9;
      }

      请注意字段名称 后面的 。这表明它是 您创建的自定义字段。标准字段 默认情况下,Salesforce 中提供的点使用相同类型的点进行访问 符号,但没有 , for 示例,不以 .该语句采用旧值 的 ,乘以 0.9, 这意味着它的价值将打折 10%,然后存储新的 值添加到字段中。运算符是快捷方式。 写此语句的另一种方法是 。请参阅表达式运算符。__cPrice__c__cName__cBook__c.Nameb.Price__c *= 0.9;b.Price__cb.Price__c*=b.Price__c = b.Price__c * 0.9;

    4. 单击保存”以保存新类。你现在应该有 这个完整的类定义。
       
      public class MyHelloWorld {
         public static void applyDiscount(Book__c[] books) {
            for (Book__c b :books){
               b.Price__c *= 0.9;
            }
         }
      }
    现在,您有一个类,其中包含一些代码,这些代码遍历书籍列表和 更新每本书的“价格”字段。此代码是触发器调用的静态方法的一部分 您将在下一步中创建。applyDiscount

     

    添加 Apex 触发器

    在此步骤中,您将为自定义对象创建一个触发器,该对象调用您在上一步中创建的类的方法。Book__capplyDiscountMyHelloWorld
    先决条件:
    • 沙盒中的 Salesforce 帐户 Professional、Enterprise、Performance 或 Unlimited Edition 组织,或开发人员组织中的帐户。
    • MyHelloWorld(我的你好世界酒店) Apex类。

    触发器是在记录之前或之后执行的一段代码 从 Lightning 平台插入、更新或删除特定类型 数据库。每个触发器都使用一组上下文变量运行,这些变量提供 访问导致触发器触发的记录。所有触发器都批量运行; 也就是说,它们一次处理多条记录。

    1. 从书籍的对象管理设置中,转到“触发器”,然后单击“新建”。
    2. 在触发器编辑器中,删除默认模板代码并输入此触发器 定义:
       
      trigger HelloWorldTrigger on Book__c (before insert) {
      
         Book__c[] books = Trigger.new;
      
         MyHelloWorld.applyDiscount(books);
      }

      第一行代码定义触发器:

      trigger HelloWorldTrigger on Book__c (before insert) {

      它为触发器指定一个名称,指定其操作的对象,以及 定义导致它触发的事件。例如,此触发器是 称为 HelloWorldTrigger,它对对象进行操作,并在将新书籍插入到 数据库。Book__c

      触发器中的下一行将创建一个名为 触发名为 的上下文变量。触发上下文变量,例如在 所有触发器,并提供对导致触发器的记录的访问 火灾。在本例中,包含将要插入的所有新书。booksTrigger.newTrigger.newTrigger.new

       
      Book__c[] books = Trigger.new;

      代码中的下一行调用类中的方法。它传入了一系列新书。applyDiscountMyHelloWorld

      MyHelloWorld.applyDiscount(books);
    现在,您拥有了更新所有书籍价格所需的所有代码。 插入。然而,仍然缺少一块拼图。单元测试是一个 编写代码的重要部分,并且是必需的。在下一步中,您将看到为什么会这样 就是这样,您将能够添加一个测试类。

    添加测试类

    在此步骤中,您将添加一个具有一个测试方法的测试类。您还运行测试并 验证代码覆盖率。测试方法练习并验证触发器中的代码,以及 类。此外,它还使您能够达到触发器的 100% 代码覆盖率,并且 类。
    先决条件:
    • 沙盒中的 Salesforce 帐户 Professional、Enterprise、Performance 或 Unlimited Edition 组织,或开发人员组织中的帐户。
    • 这 HelloWorldTrigger Apex 触发器。
     

    注意

    测试是开发过程的重要组成部分。部署之前 Apex 或将其打包为 AppExchange,则必须满足以下条件。

    • 单元测试必须至少覆盖 75% 的 Apex 代码,并且所有这些测试 必须成功完成。
    • 每个触发器都必须具有一定的测试覆盖率。
    • 所有类和触发器都必须成功编译。

    请注意以下事项。

    • 将 Apex 部署到生产组织时,每个单元测试 默认情况下,将执行组织命名空间。
    • 调用不计算在内 作为 Apex 代码覆盖率的一部分。System.debug
    • 测试方法和测试类不计为 Apex 代码的一部分 覆盖。
    • 虽然只有 75% 的 Apex 代码必须被测试覆盖,但不要 重点关注所覆盖代码的百分比。相反,请确保 涵盖应用程序的每个用例,包括 阳性和阴性病例,以及批量和单条记录。 此方法可确保 75% 或更多的代码被 单元测试。
    1. 在“设置”中,在“快速”中输入 Apex 类 “查找”框,然后选择“Apex 类”和 单击“新建”。
    2. 在类编辑器中,添加此测试类定义,然后单击“保存”。
       
      @IsTest 
      private class HelloWorldTestClass {
          @IsTest
          static void validateHelloWorld() {
             Book__c b = new Book__c(Name='Behind the Cloud', Price__c=100);
             System.debug('Price before inserting new book: ' + b.Price__c);
      
             // Insert book
             insert b;
          
             // Retrieve the new book
             b = [SELECT Price__c FROM Book__c WHERE Id =:b.Id];
             System.debug('Price after trigger fired: ' + b.Price__c);
      
             // Test that the trigger correctly updated the price
             System.assertEquals(90, b.Price__c);
          }
      }

      此类是使用注释定义的。以这种方式定义的类应该只 包含测试方法以及支持这些测试方法所需的任何方法。 为测试创建单独的类的一个优点是类 使用 Don’t Count 定义 违反组织 6 MB 的 Apex 代码限制。您也可以将注释添加到单个 方法。有关更多信息,请参见@IsTest注释和执行 调速器和限制。@IsTest@IsTest@IsTest

      该方法是使用注释定义的。这 注解意味着如果对数据库进行了更改,则会滚动这些更改 执行完成后返回。您不必删除任何测试数据 在测试方法中创建。validateHelloWorld@IsTest

      注意

      上的注释 methods 等同于关键字。如 最佳做法,Salesforce 建议您使用 而不是 .关键字可以在 未来版本。@IsTesttestMethod@IsTesttestMethodtestMethod

      首先,测试方法创建一本书并将其插入数据库 暂时。该语句在调试中写入价格值 日志。System.debug

      Book__c b = new Book__c(Name='Behind the Cloud', Price__c=100);
      System.debug('Price before inserting new book: ' + b.Price__c);
      
      // Insert book
      insert b;

      插入书籍后,代码将检索新 插入的书籍,使用最初分配给书籍的 ID,当它 已插入。然后,该语句记录触发的新价格 改 性。System.debug

      // Retrieve the new book
      b = [SELECT Price__c FROM Book__c WHERE Id =:b.Id];
      System.debug('Price after trigger fired: ' + b.Price__c);

      当类运行时,它会更新字段并将其值减少 10%.以下测试验证该方法是否运行并生成了 预期 结果。MyHelloWorldPrice__capplyDiscount

      // Test that the trigger correctly updated the price
      System.assertEquals(90, b.Price__c);
    3. 若要运行此测试并查看代码覆盖率信息,请切换到“开发人员” 安慰。
    4. 在开发者控制台中,点击测试 |新运行
    5. 若要选择测试类,请单击“HelloWorldTestClass”。
    6. 若要将 HelloWorldTestClass 类中的所有方法添加到测试运行中,请单击“添加” 已选择
    7. 单击运行
      测试结果将显示在“测试”选项卡中。或者,您可以展开 “测试”选项卡中的测试类,用于查看运行了哪些方法。在本例中, 该类仅包含一个测试方法。
    8. “总体代码覆盖率”窗格显示此测试类的代码覆盖率。自 查看此测试涵盖的触发器中代码行的百分比,其中 为 100%,则双击 HelloWorldTrigger 的代码覆盖率行。因为触发器调用一个方法 来自 MyHelloWorld 类,此类 也有覆盖率(100%)。若要查看类覆盖率,请双击 MyHelloWorld
    9. 若要打开日志文件,请在“日志”选项卡中双击 日志列表。将显示执行日志,包括日志记录信息 关于触发器事件、对 applyDiscount 方法的调用以及 触发。
    到目前为止,您已经完成了使用 在开发环境中运行的测试。在现实世界中,在你 测试了您的代码并对此感到满意,您想要部署代码和任何 生产组织的必备组件。下一步将演示如何执行此操作 部署已创建的代码和自定义对象。

     

    将组件部署到生产环境

    在此步骤中,您将部署 Apex 代码和之前创建的自定义对象 使用更改集添加到您的生产组织。
    先决条件:
    • 沙盒 PerformanceUnlimited 或 Enterprise Edition 组织中的 Salesforce 帐户。
    • 这 HelloWorldTestClass Apex 测试类。
    • 沙盒与生产组织之间的部署连接,该连接 允许生产组织接收入站更改集。看 Salesforce 联机帮助中的“更改集”。
    • “创建和上传变更集”用户创建、编辑、 或上传出站更改集。

    此过程不适用于开发人员组织,因为更改集是 仅在 PerformanceUnlimitedEnterprise 或 Database.com Edition 组织。如果您拥有 Developer Edition 帐户,则可以 使用其他部署方法。有关更多信息,请参阅部署 Apex。

    1. 在“设置”中,在“快速查找”框中输入“出站变更集”,然后选择“出站 变更集
    2. 如果出现启动页面,请单击“继续”。
    3. 在“更改集”列表中,单击“新建”。
    4. 输入更改集的名称(例如 HelloWorldChangeSet)和描述(可选)。 点击保存
    5. 在“更改集组件”部分中,单击“添加”。
    6. 从组件类型下拉列表中选择 Apex Class,然后选择 MyHelloWorld 和列表中的 HelloWorldTestClass 类,然后单击添加到更改集
    7. 单击“查看/添加依赖项”以添加依赖项 组件。
    8. 选中顶部复选框以选择所有组件。单击“添加到” 更改集
    9. 在更改集页面的“更改集详细信息”部分中,单击“上传”。
    10. 选择目标组织(在本例中为生产),然后单击上传
    11. 更改集上传完成后,将其部署到生产环境中 组织。
      1. 登录到您的生产组织。
      2. 在“设置”中,在“快速查找”框中输入“入站更改集”,然后选择“入站” 更改集
      3. 如果出现启动页面,请单击“继续”。
      4. 在等待部署的更改集列表中,单击更改集的 名字。
      5. 单击 Deploy
    在本教程中,您学习了如何创建自定义对象,如何添加 Apex 触发器、类和测试类。最后,您还学习了如何测试代码,以及如何 以使用更改集上传代码和自定义对象。