(ZZ)蔡学饁-staticの意義と実作方式

4362 ワード

「あるclassをinstanceにすると、このclassのすべてのinstance fieldが追加されます.それでは、すべてのinstance methodも追加されますか?」私はよくネット上でこの問題を議論している人を見て、この文章を書いて、説明したいと思っています.
メンバーの種類
カテゴリ(class)の内部構成を総称してメンバー(member)と呼び、メンバーが「資料」か「プログラム」かで区別すると、次のように分けられます.
*資料、fieldと呼ばれています
*プログラム、methodと呼ばれています
static修飾の有無に基づいてさらに細分化すると、メンバーは4つに細分化されます.
*class field:staticで修飾されたfield
*class method:staticで修飾されたmethod
*instance field:staticで修飾されていないfield
*instance method:staticで修飾されていないmethod
名前の通り、class field/methodとclass自体は密接な関係があり、instance field/methodはinstance(すなわち物件)と密接な関係がある.次の例のプログラムを見てください.
public class Class1 {
  public static int classField;
  public static void classMethod1() {
  // ...
  }
  public static void classMethod2() {
  // ...
  }
  public int instanceField;
  public void instanceMethod1() {
  // ...
  }
  public void instanceMethod2() {
  // ...
  }
}
public class Class2 {
  public static void classMethod () {
  // ...
  }
  public void instanceMethod() {
  // ...
  }
}

Field
フィールドを宣言するとき、staticの修飾字を前に付けると、このフィールドはclassフィールドになります.1つのclass fieldは、常に1つのメモリのみを占有し、このメモリ空間は、classがメモリにロードされるとすぐに構成され、classのinstanceに関連するのではなく、このfieldがclass自体に関連しているように感じられる.class fieldは、同じclassのclass method内部で直接使用することができ、例えば、上述したclassMethod 1()内部にclassFieldが現れることができる.Class 1のclass methodまたはinstance methodをClass 2のclass fieldに使用する場合は、前にClass 2を付ける必要があります.たとえば、Class 2.classField.
フィールドを宣言するとき、前の「いいえ」にstaticの修飾字を付けると、このフィールドはinstance fieldになります.Instance fieldでは、1つのinstance(物件)が生成されるたびに1つのinstance fieldの記憶体が多くなり、1つのinstanceが少なくなるごとに1つのinstance fieldの記憶体が少なくなる.instance fieldは、同じinstanceのinstance method内部で直接使用することができ、例えば、上述したinstance Method 1()内部にinstance Fieldが現れることができる.あるclassのclass methodまたはinstance methodがあるinstanceのinstance fieldに使用する場合は、前冠にinstance名、例えばobj.classField.
Method
methodを宣言するとき、staticの修飾字を前に付けると、このmethodはclass methodになります.class methodでは、常に1つのメモリのみが占有され、このメモリ空間は、classがメモリにロードされるとすぐに構成され、このmethodがclass自体に関連し、classのinstanceに関連するのではなく、class自体に関連している.class methodは、同じclassの任意のclass method内部で直接使用することができ、例えば、上述したclassMethod 1()内部にclassMethod 2()が現れることができる.Class 1のclass methodまたはinstance methodをClass 2のclassMethod()に使用するには、前にClass 2、つまりClass 2を冠す必要があります.classMethod().
methodを宣言するとき、前の「いいえ」にstaticの修飾字を付けると、このmethodはinstance methodになります.instance methodでは、instanceが1つ生成されるたびに、instance methodの記憶体が1つ増えることはありません.同じmethodが何度呼び出されても、呼び出されたときのinstanceが何であるかにかかわらず、毎回のプログラムコードは全く同じで、違いは実行するたびに資料が異なり、資料はcall stackに格納されるので混同されません.instance methodでは、資料のソースにはパラメータとinstance fieldが含まれています.パラメータはcall stack内のentryに伝達されるので混同されないのは分かりやすいが、instance fieldがどのように区切られているのか(前述したように、instance fieldはinstance数の増加に伴って増加する)、これは隠匿(implicit)のthisパラメータによって達成され、後で説明する.instance methodは、同じinstanceのinstance method内部で直接使用することができ、例えば、上述したinstance Method 1()内部にinstance Method 2()が現れることができる.あるclassのclass methodまたはinstance methodがあるinstanceのあるinstance methodに使用する場合は、前にこのinstance名を冠す必要があります.例えば、obj.classMethod().
隠しthisパラメータ
以上の記述を総合すると、
*class field:メモリを共有
*class method:メモリを共有
*instance field:instanceごとにメモリが1つずつあります
*instance method:メモリーを共有
instance methodはなぜinstanceごとに記憶体を占有するのではなく、逆に記憶体を共有するのですか?実際には、instance methodごとにinstance fieldのように、instanceごとに記憶体を占有させることはもちろんできますが、JavaコンパイラもJVMもそうしません.記憶体の空間がもったいないからです.1つのfieldが少なければ1つのbyteを占有し、多くは数百Byteを占有するが、methodが少なければ数byteを占有し、多くは数百Kilo Byteを占有する.Mehtodが消費するメモリはfieldの数百倍、さらに数千倍であり、もちろん共用できるだけ共用し、比較的メモリを消費しない.JVMが1つのclassのすべてのinstanceに同じinstance methodを共有させる以上、次の2行のプログラムコードがinstance Method()内部にある場合、instance 1またはinstance 2をどのように区別しますか?
instance1.instanceMethod();
instance2.instanceMethod();
コンパイラはinstance 1とinstance 2をinstanceMethod()に個別に転送する最初のパラメータとして役立つからです.つまり、どのinstance methodパラメータの実際の個数も表面より1つ多く、この多くのパラメータはJavaコンパイラが追加してくれて、対応するinstanceを表すために使われています.このパラメータの変数名はthisであり、Javaのキーワードでもあります.
あるinstance methodを呼び出したり、あるinstance fieldを使用したりする場合は、そのinstanceの名前を前に付けなければなりません.instance method/fieldに関連するinstanceと、その時点のプログラムコードが存在するinstance methodのinstanceが同じinstanceを指す場合は、そのinstanceの名前がthisである場合は、前に「this.」を付けないこともできます.
しかし、ある状況では、前に「this.」を付けなければならない.いけません.たとえば、methodのパラメータや領域変数がinstance field名と完全に同じである場合、前の冠に「this.」を付けないと、パラメータまたは領域変数を指します.前に「this.」を冠すると、それはinstance fieldを指します.