はじめに
Apexにはthisキーワードが用意されています。
this
付きで変数にアクセスすることで、その対象変数がクラスのメンバ変数であることを明示できます。(ローカル変数と区別できる)
public class Sample {
//クラスのメンバ変数
String color = '赤';
public void printColor() {
//ローカル変数
String color = '青';
System.debug('ローカル変数color -> ' + color); // 青
System.debug('メンバ変数 this.color -> ' + this.color); // 赤
}
}
上記はプリミティブ型(String)メンバ変数の例となりますが、
一方で、SObject
型メンバ変数へアクセスする際、this
キーワードの有無で異なる動きが観測されたので備忘録として残しておきます。
なにがわかったのか?
簡単に言うと、SObject型メンバ変数がNullの場合でも、thisを付けてアクセスするとNullPointerExceptionが発生しないことがわかりました。
まず、以下のコードはNullPointerExceptionが発生します。
public class Sample {
//クラスのSObjectメンバ変数
public Contact sampleContact;
public void printContactName() {
// sampleContactはNull(非インスタンス)なのでName項目にアクセスできず例外発生
System.debug(sampleContact.Name); // <- System.NullPointerException: Attempt to de-reference a null object
System.debug('finish'); // <- 表示されない
}
}
Sample sample = new Sample();
sample.printContactName();
しかし、以下のようにthis
を付与してメンバ変数にアクセスするとNullPointerExceptionは発生しません。
public class Sample {
//クラスのSObjectメンバ変数
public Contact sampleContact;
public void printContactName() {
// sampleContactをインスタンス化していないが、Name項目を参照可能
System.debug(this.sampleContact.Name); // <- 結果はNullだが、NullPointerExceptionは発生しない
System.debug('finish'); // <- 表示される
}
}
Sample sample = new Sample();
sample.printContactName();
もちろん、thisあり/thisなしの2つは同一データです。
public class Sample {
//クラスのSObjectメンバ変数
public Contact con;
public void printContactName() {
System.debug(this.con === con); // <- true
}
}
Sample sample = new Sample();
sample.printContactName();
以上のようにthis
キーワードの有無で挙動が異なるのですが、原因は不明です。
その他にも色々試してみました。
1.SObjectメンバ変数のリレーション項目へアクセスしてみる
リレーション項目もthis
をつければアクセスできます。もちろん、this
無しはNullPointerExceptionが発生します。
public class Sample {
//クラスのSObjectメンバ変数
public Contact con;
public void printContactName() {
// Contactのリレーション項目Accountの名前にアクセス
System.debug(this.con.account.name); // <- 結果はNullだが、NullPointerExceptionは発生しない
System.debug('finish'); // <- 表示される
}
}
Sample sample = new Sample();
sample.printContactName();
2.メンバ変数をクラス外から直接参照してみる
クラス外からNullのSObjectメンバ変数に直接アクセスした場合、こちらもNullPointerExceptionは発生しないようです。
public class Sample {
public Contact con ;
}
Sample sample = new Sample();
// Sampleクラスのメンバ変数
System.debug(sample.con == null); // <- true
// 項目
System.debug(sample.con.name == null); // <- true
// リレーション
System.debug(sample.con.account == null); // <- true
// リレーション項目
System.debug(sample.con.account.name == null); // <- true
さいごに
以上、this
キーワードの謎についてでした。
クラスをnewした際にSObjectメンバ変数の初期化のような処理が行われるのだろうか・・🤔?と考えましたが、理由はわかりません・・
とりあえず、
クラス内部からSObject型メンバ変数にアクセスする場合、常にthis
キーワードを付与することでNullPointerExceptionが発生しないようになるため、忘れずに付与したいところです。