Apex关键字

Apex 提供了 关键字 finalinstanceofsuperthistransientwith sharing and without sharing

  1. 使用 final 关键字
  2. 使用 instanceof 关键字
  3. 使用 super 关键字
  4. 使用 this 关键字
  5. 使用 transient 关键字
  6. 使用 with sharing、without sharing 和 inherited sharing 关键字 在类上使用 or 关键字
    指定是否必须强制执行共享规则。在类上使用关键字,以在调用该类的类的共享模式下运行该类。with sharing without sharing inherited sharing

使用 final 关键字

您可以使用关键字 修改变量。

final

  • 最终变量只能赋值一次,无论是在声明变量时还是在 构造函数。您必须在以下两个位置之一为其赋值。
  • 静态最终变量可以在静态初始化中更改 代码或定义的位置。
  • 成员最终变量可以在初始化代码块中更改, 构造函数,或使用其他变量声明。
  • 要定义常量,请将变量标记为 和 。staticfinal
  • 非最终静态变量用于在 类级别(例如触发器之间的状态)。然而,事实并非如此 在请求之间共享。
  • 默认情况下,方法和类是最终的。不能在声明中使用关键字 的类或方法。这意味着它们不能被覆盖。如果需要覆盖,请使用关键字 方法或类。finalvirtua

使用 instanceof 关键字

如果需要在运行时验证对象是否实际上是 特定类,请使用关键字。 关键字只能用于 验证关键字右侧表达式中的目标类型是否可行 左侧表达式的声明类型的替代项。instanceofinstanceof您可以将以下检查添加到类中的类中,然后 将项目投射回对象之前的投射示例。

ReportCustomReport

If (Reports.get(0) instanceof CustomReport) {
    // Can safely cast it back to a custom report object
   CustomReport c = (CustomReport) Reports.get(0);
   } Else {
   // Do something with the non-custom-report.
}

注意

在使用 API 版本 32.0 及更高版本保存的 Apex 中,如果左操作数为 null 对象,则返回。为 示例,以下示例返回 。instanceoffalsefalse

Object o = null;
Boolean result = o instanceof Account;
System.assertEquals(false, result);

在 API 版本 31.0 及更早版本中,在本例中返回。instanceoftrue

使用 super 关键字

关键字可以 由从虚拟类或抽象类扩展而来的类使用。 通过使用 ,可以覆盖 父类中的构造函数和方法。supersuper例如,如果您有以下虚拟类:

public virtual class SuperClass {
    public String mySalutation;
    public String myFirstName;
    public String myLastName;

    public SuperClass() {

        mySalutation = 'Mr.';
        myFirstName = 'Carl';
        myLastName = 'Vonderburg';
    }

    public SuperClass(String salutation, String firstName, String lastName) {

        mySalutation = salutation;
        myFirstName = firstName;
        myLastName = lastName;
    }

    public virtual void printName() {

        System.debug('My name is ' + mySalutation + myLastName);
    }

   public virtual String getFirstName() {
       return myFirstName;
   }
}

您可以创建以下类来扩展和重写其方法:

SuperclassprintName

public class Subclass extends Superclass {
  public override void printName() {
        super.printName();
        System.debug('But you can call me ' + super.getFirstName());
    }
}

调用时的预期输出为Subclass.printNameMy name is Mr. Vonderburg. But you can call me Carl.还可以用于调用构造函数。将以下构造函数添加到:

superSubClass

public Subclass() {
    super('Madam', 'Brenda', 'Clapentrap');
}

现在,预期的输出是Subclass.printNameMy name is Madam Clapentrap. But you can call me Brenda.

使用 super 关键字的最佳做法

  • 只有扩展自 或 类的类才能使用 .virtualabstractsuper
  • 只能在用关键字指定的方法中使用。superoverride

使用 this 关键字

有两种不同的使用关键字的方法。this

您可以使用关键字 以点表示法,不带括号,表示当前实例 它出现在哪个类中。使用这种形式的关键字来访问实例变量 和方法。例如:thisthis

public class myTestThis {

string s;
  {
      this.s = 'TestString';
  }
}

在上面的示例中,该类声明了一个实例变量。初始化代码填充 使用 关键字的变量。myTestThissthis

或者你可以使用关键字来做构造函数链接,即在一个构造函数中, 调用另一个构造函数。在此格式中,使用带括号的关键字。为 例:thisthis

public class testThis {

// First constructor for the class. It requires a string parameter.
   public testThis(string s2) {
   }

// Second constructor for the class. It does not require a parameter.
// This constructor calls the first constructor using the this keyword.
   public testThis() {
       this('None');
   }
}

当您使用关键字时 在构造函数中,要执行构造函数链接,它必须是第一个 语句。this

使用 transient 关键字

使用关键字声明实例 无法保存且不应作为视图状态的一部分传输的变量 用于 Visualforce 页面。为 例:

transient

Transient Integer currentTotal;

您还可以在 Apex 中使用关键字 可序列化的类,即在控制器、控制器扩展或类中 实现 or 接口。此外,还可以在定义类型的类中使用 在可序列化类中声明的字段。transientBatchableSchedulabletransient

将变量声明为缩减视图 状态大小。关键字的一个常见用例是 Visualforce 页面上的字段,该字段仅在页面持续时间内需要 请求,但不应是页面视图状态的一部分,并且会使用过多的系统 在请求期间要多次重新计算的资源。transienttransient

某些 Apex 对象会自动被视为瞬态对象,也就是说,它们的值不会 保存为页面视图状态的一部分。这些对象包括:

  • 页面引用
  • XmlStream 类
  • 集合自动标记为暂时性,仅当它们的对象类型 保留会自动标记为暂时性保留,例如保存点的集合
  • 大多数对象由系统方法生成,例如 .Schema.getGlobalDescribe
  • JSONParser类实例。

静态变量也不会得到 通过视图状态传输。

以下示例包含一个 Visualforce 页面和一个自定义控制器。点击 页面上的“刷新”按钮使瞬态日期为 已更新,因为每次刷新页面时都会重新创建它。非瞬态 date 继续具有其原始值,该值已从视图中反序列化 状态,所以它保持不变。

<apex:page controller="ExampleController">
  T1: {!t1} <br/>
  T2: {!t2} <br/>
  <apex:form>
    <apex:commandLink value="refresh"/>
  </apex:form>
</apex:page>
public class ExampleController {

    DateTime t1;
    transient DateTime t2;

    public String getT1() {
        if (t1 == null) t1 = System.now();
        return '' + t1;
    }

    public String getT2() {
        if (t2 == null) t2 = System.now();
        return '' + t2;
    }
}

使用有共享、无共享和继承共享关键字

在类上使用 or 关键字来指定是否 必须强制执行共享规则。在类上使用关键字以在类的共享模式下运行该类 称其为。

with sharingwithout sharinginherited sharing

与共享

在声明 类来强制执行当前用户的共享规则。显式设置此关键字可确保 Apex 代码在当前用户上下文中运行。通过调用执行的 Apex 代码和 Apex 中的 Connect 始终执行 使用当前用户的共享规则。有关 的详细信息,请参阅匿名块。with sharingexecuteAnonymousexecuteAnonymous

在声明 类来强制执行适用于当前用户的共享规则。例如:with sharing

public with sharing class sharingClass {

   // Code here

}

无共享

在声明 类来确保不强制执行当前用户的共享规则。例如 当一个类从另一个类调用时,您可以显式关闭共享规则强制执行 使用 声明的类。without sharingwith sharing

public without sharing class noSharing {

   // Code here

}

继承共享

在声明 类来强制执行调用它的类的共享规则。使用是一种先进的技术来确定 运行时的共享模式,并设计可以在任一模式下运行的 Apex 类。inherited sharinginherited sharingwith sharingwithout sharing

警告

由于共享模式是在运行时确定的,因此必须采取极端措施 注意确保您的 Apex 代码可以安全地在两种模式下运行。with sharingwithout sharing将 一起使用 和其他 适当的安全检查,有助于通过 AppExchange 安全审查并确保 您的特权 Apex 代码不会以意外或不安全的方式使用。一个 Apex 类,其运行方式为:

inherited sharinginherited sharingwith sharing

  • Aura 组件控制器
  • Visualforce 控制器
  • Apex REST 服务
  • Apex 事务的任何其他入口点

标有 Apex 类和省略共享的类之间有明显的区别 声明。如果该类用作 Apex 事务的入口点,则省略 共享声明以 . 但是,确保默认 是以 .声明为 的类仅在从 已经建立的上下文。inherited sharingwithout sharinginherited sharingwith sharinginherited sharingwithout sharingwithout sharing

此示例声明一个 Apex 类,其中包含该 Apex 代码的 Visualforce 调用。由于声明,只有联系人 显示正在运行的用户具有共享访问权限。如果省略声明,请联系 由于不安全的默认值,用户没有查看权限 行为。

inherited sharinginherited sharing

public inherited sharing class InheritedSharingClass {
    public List<Contact> getAllTheSecrets() {
        return [SELECT Name FROM Contact];
    }
}
<apex:page controller="InheritedSharingClass">
    <apex:repeat value="{!allTheSecrets}" var="record">
        {!record.Name}
    </apex:repeat>
</apex:page>

实施细节

  • 应用定义方法的类的共享设置,而不是 从中调用方法的类。例如,如果在类中定义了方法 声明为由类调用 声明为 ,方法 在强制执行共享规则的情况下执行。with sharingwithout sharing
  • 如果类未显式声明为 either 或 , 当前共享规则仍然有效。因此,该类不强制执行共享 规则,除非它从另一个类获取共享规则。例如,如果 类由另一个强制执行共享的类调用,然后强制执行共享 被调用的类。with sharingwithout sharing
  • 内部类和外部类都可以声明为 。内部类不继承 共享容器类中的设置。否则,共享设置将应用于 类中包含的所有代码,包括初始化代码、构造函数和 方法。with sharing
  • 当一个类扩展或 实现另一个。
  • Apex 触发器不能具有显式共享声明,不能以 .without sharing

最佳实践

默认情况下,没有显式共享声明的 Apex 是不安全的。我们强烈建议 您始终为类指定共享声明。

无论采用何种共享模式,对象级访问和字段级安全性都不是 由 Apex 强制执行。您必须在 您的 SOQL 查询或代码。例如,机制不强制用户访问查看报表和 仪表 板。您必须显式强制执行正在运行的用户的 CRUD(创建、读取、更新、 Delete) 和代码中的字段级安全性。请参阅强制执行对象和字段权限。with sharing

共享模式何时使用
with sharing使用此模式作为默认模式,除非您的用例另有要求。
without sharing请谨慎使用此模式。确保您不会无意中暴露敏感内容 通常由共享模型隐藏的数据。这种共享机制是 最适合用于向当前授予有针对性地提升共享权限 用户。例如,使用 允许社区用户读取他们原本不会拥有的记录 访问。without sharing
inherited sharing对于必须灵活且支持使用的服务类,请使用此模式 具有不同共享模式的情况,同时也默认为更安全的模式。with sharing