「静的」キーワードはクラスで何をしますか?
-
03-07-2019 - |
質問
具体的には、このコードを試していました:
package hello;
public class Hello {
Clock clock = new Clock();
public static void main(String args[]) {
clock.sayTime();
}
}
ただし、エラーが発生しました
静的メソッドmainの非静的フィールドにアクセスできません
したがって、 clock
の宣言を次のように変更しました。
static Clock clock = new Clock();
そして、うまくいきました。そのキーワードを宣言の前に置くとはどういう意味ですか?そのオブジェクトに対して何ができるかという点で、正確に何を行うか、または制限しますか?
解決
static
メンバーは、特定のインスタンスではなくクラスに属します。
これは、クラスの100万個のインスタンスを作成した場合でも、 static
フィールドのインスタンスが1つだけ存在することを意味します [1] 作成しないでください。すべてのインスタンスで共有されます。
static
メソッドも特定のインスタンスに属さないため、インスタンスメンバーを参照できません。与えられた例では、 main
は Hello
クラスのどのインスタンス(したがって Clock
クラスのどのインスタンス)を参照すべきかを知りません。 。 static
メンバーは、 static
メンバーのみを参照できます。インスタンスメンバーは、もちろん static
メンバーにアクセスできます。
サイドノート:もちろん、 static
メンバーはオブジェクト参照を介してインスタンスメンバーにアクセスできます。
例:
public class Example {
private static boolean staticField;
private boolean instanceField;
public static void main(String[] args) {
// a static method can access static fields
staticField = true;
// a static method can access instance fields through an object reference
Example instance = new Example();
instance.instanceField = true;
}
[1]:ランタイムの特性に応じて、ClassLoaderまたはAppDomainまたはスレッドごとに1つになりますが、それはポイントの横にあります。
他のヒント
これは、「クロック」のインスタンスが1つしかないことを意味します。 Helloでは、「Hello」の個別のインスタンスごとに1つではありません。クラス、またはそれ以上、一般的に共有される「クロック」が1つ存在することを意味します。 「Hello」のすべてのインスタンス間の参照クラス。
つまり、「新しいHello」を実行する場合は、コードのどこでも: A-最初のシナリオ(「静的」を使用せずに変更する前)では、「新しいHello」が実行されるたびに新しいクロックが作成されます。と呼ばれますが、 B- 2番目のシナリオ(変更後、「静的」を使用)、すべての「新しいHello」インスタンスは引き続き、最初の同じ「クロック」を共有して使用します。最初に作成された参照。
" clock"が必要でない限りメイン以外のどこかで、これも同様に機能します:
package hello;
public class Hello
{
public static void main(String args[])
{
Clock clock=new Clock();
clock.sayTime();
}
}
static
キーワードは、特定のインスタンスではなく type に関連する何か(フィールド、メソッド、またはネストされたクラス)を意味しますタイプ。したがって、たとえば、 Math
クラスのインスタンスなしで Math.sin(...)
を呼び出すと、実際にはできません作成できます Math
クラスのインスタンス。
詳細については、 OracleのJavaチュートリアルの関連ビットを参照してください。
サイドノート
Javaは残念ながら、インスタンスメンバーであるかのように静的メンバーにアクセスすることを許可します。たとえば、
// Bad code!
Thread.currentThread().sleep(5000);
someOtherThread.sleep(5000);
それは、 sleep
がインスタンスメソッドであるかのように見た目にしますが、実際には静的メソッドです-現在のスレッドを常に スリープ状態にします。呼び出し元のコードでこれを明確にすることをお勧めします。
// Clearer
Thread.sleep(5000);
Javaの static
キーワードは、変数または関数が、実際のオブジェクト自体ではなく、 type に属するクラスのすべてのインスタンス間で共有されることを意味します。
変数がある場合: private static int i = 0;
1つのインスタンスでそれをインクリメント( i ++
)すると、変更はすべてのインスタンスに反映されます。 i
はすべてのインスタンスで1になります。
オブジェクトをインスタンス化せずに静的メソッドを使用できます。
静的メンバーの基本的な使用...
public class Hello
{
// value / method
public static String staticValue;
public String nonStaticValue;
}
class A
{
Hello hello = new Hello();
hello.staticValue = "abc";
hello.nonStaticValue = "xyz";
}
class B
{
Hello hello2 = new Hello(); // here staticValue = "abc"
hello2.staticValue; // will have value of "abc"
hello2.nonStaticValue; // will have value of null
}
これにより、クラスインスタンスHelloを他のクラスに送信せずに、すべてのクラスメンバーで値を共有できます。そして、クラスインスタンスを作成する必要がない静的です。
Hello hello = new Hello();
hello.staticValue = "abc";
クラス名で静的な値またはメソッドを呼び出すことができます:
Hello.staticValue = "abc";
Javaの静的:
Staticは非アクセス修飾子です。 staticキーワードは、クラスのインスタンスよりもクラスに属します。 変数またはメソッドをクラスにアタッチするために使用できます。
静的キーワードは以下で使用できます:
方法
変数
別のクラス内にネストされたクラス
初期化ブロック
以下では使用できません
クラス(ネストされていない)
コンストラクター
インターフェース
メソッドのローカル内部クラス(差分とネストされたクラス)
内部クラスメソッド
インスタンス変数
ローカル変数
例:
countという名前のインスタンス変数を持つコンストラクタの次の例を想像してください:
package pkg;
class StaticExample {
int count = 0;// will get memory when instance is created
StaticExample() {
count++;
System.out.println(count);
}
public static void main(String args[]) {
StaticExample c1 = new StaticExample();
StaticExample c2 = new StaticExample();
StaticExample c3 = new StaticExample();
}
}
出力:
1 1 1
インスタンス変数はオブジェクトの作成時にメモリを取得するため、各オブジェクトにはインスタンス変数のコピーがあり、インクリメントされた場合、他のオブジェクトには反映されません。
今、インスタンス変数のカウントを静的に変更する場合、プログラムは異なる出力を生成します:
package pkg;
class StaticExample {
static int count = 0;// will get memory when instance is created
StaticExample() {
count++;
System.out.println(count);
}
public static void main(String args[]) {
StaticExample c1 = new StaticExample();
StaticExample c2 = new StaticExample();
StaticExample c3 = new StaticExample();
}
}
出力:
1 2 3
この場合、静的変数はメモリを1回だけ取得します。オブジェクトが静的変数の値を変更した場合、その値は保持されます。
静的ファイナル:
final and static として宣言されているグローバル変数は、実行全体にわたって変更されません。なぜなら、静的メンバーはクラスメモリに格納され、実行全体で一度だけロードされるからです。これらはクラスのすべてのオブジェクトに共通です。静的変数をfinalとして宣言した場合、どのオブジェクトもfinalであるため値を変更できません。したがって、finalおよびstaticとして宣言された変数は、定数と呼ばれることもあります。インターフェースのすべてのフィールドは、デフォルトで最終および静的であるため、定数と呼ばれます。
画像リソース:最終静的
静的とは、クラスに関連付けられたメソッドまたは変数を使用するために、クラスのインスタンスを作成する必要がないことを意味します。あなたの例では、次のように呼び出すことができます:
Hello.main(new String[]()) //main(...) is declared as a static function in the Hello class
直接ではなく:
Hello h = new Hello();
h.main(new String[]()); //main(...) is a non-static function linked with the "h" variable
静的メソッド(クラスに属する)からは、静的ではないメンバーにアクセスできません。メンバーの値はクラスのインスタンス化に依存するためです。インスタンスメンバーである非静的Clockオブジェクトは、Helloクラスのインスタンスごとに異なる値/参照を持つため、クラスの静的部分からアクセスできません。
この説明では、これまでクラスローダーの考慮事項を無視していました。厳密に言えば、Java静的フィールドは、特定の classloader のクラスのすべてのインスタンス間で共有されます。
フィールドは、クラスまたはクラスのインスタンスに割り当てることができます。デフォルトでは、フィールドはインスタンス変数です。 static
を使用すると、フィールドはクラス変数になるため、 clock
は1つだけです。 1つの場所で変更を加えると、どこにでも表示されます。インスタンス変数は、互いに独立して変更されます。
キーワード static
は、インスタンスではなくクラス自体に属するフィールドまたはメソッドを示すために使用されます。コードを使用して、オブジェクト Clock
が静的である場合、 Hello
クラスのすべてのインスタンスはこの Clock
データメンバー(フィールド)を共有します一般。非静的にすると、 Hello
の個々のインスタンスに一意の Clock
フィールドを含めることができます。
問題は、コードを実行できるように、クラス Hello
に main メソッドを追加したことです。ここでの問題は、 main メソッドが静的であるため、その内部の非静的フィールドまたはメソッドを参照できないことです。これは2つの方法で解決できます。
-
Hello
クラスのすべてのフィールドとメソッドを静的にし、 main メソッド内で参照できるようにします。これは本当に良いことではありません(またはフィールドやメソッドを静的にする間違った理由) - mainメソッド内で
Hello
クラスのインスタンスを作成し、最初に意図した方法ですべてのフィールドとメソッドにアクセスします。
あなたにとって、これはあなたのコードに対する次の変更を意味します:
package hello;
public class Hello {
private Clock clock = new Clock();
public Clock getClock() {
return clock;
}
public static void main(String args[]) {
Hello hello = new Hello();
hello.getClock().sayTime();
}
}
Javaでは、 static
キーワードは単に以下を示すものと見なすことができます。
"特定のインスタンスとは無関係または関係なし"
static
をこのように考えると、遭遇するさまざまなコンテキストでの使用を理解しやすくなります。
-
static
フィールドは、特定のインスタンスではなくクラスに属するフィールドです -
static
メソッドは、this
の概念を持たないメソッドです。クラスで定義されており、参照が渡されない限り、そのクラスの特定のインスタンスを認識しません -
static
メンバクラスは、その外側のクラスのインスタンスの概念や知識を持たないネストされたクラスです(外側のクラスインスタンスへの参照が渡されない限り)
Staticは、クロックメンバーをインスタンスメンバーではなくクラスメンバーにします。 staticキーワードを使用しない場合、Helloクラス(clockメンバー変数を持つ)のインスタンスを作成する必要があります-例:
Hello hello = new Hello();
hello.clock.sayTime();
静的メソッドは、定義されているクラスのインスタンス変数を使用しません。違いの非常に良い説明は、このページ
" helper"で静的メソッドを(可能な場合のみ)好みに開発しました。クラス。
呼び出し元のクラスは、ヘルパークラスの別のメンバー(インスタンス)変数を作成する必要はありません。ヘルパークラスのメソッドを呼び出すだけです。また、コンストラクターが不要になり、メンバー(インスタンス)変数が不要になるため、ヘルパークラスも改善されています。
おそらく他にも利点があります。
また、静的メンバーが" this"を持たないと考えることもできます。ポインター。それらはすべてのインスタンス間で共有されます。
静的な概念を理解する
public class StaticPractise1 {
public static void main(String[] args) {
StaticPractise2 staticPractise2 = new StaticPractise2();
staticPractise2.printUddhav(); //true
StaticPractise2.printUddhav(); /* false, because printUddhav() is although inside StaticPractise2, but it is where exactly depends on PC program counter on runtime. */
StaticPractise2.printUddhavsStatic1(); //true
staticPractise2.printUddhavsStatic1(); /*false, because, when staticPractise2 is blueprinted, it tracks everything other than static things and it organizes in its own heap. So, class static methods, object can't reference */
}
}
第2クラス
public class StaticPractise2 {
public static void printUddhavsStatic1() {
System.out.println("Uddhav");
}
public void printUddhav() {
System.out.println("Uddhav");
}
}
//Here is an example
public class StaticClass
{
static int version;
public void printVersion() {
System.out.println(version);
}
}
public class MainClass
{
public static void main(String args[]) {
StaticClass staticVar1 = new StaticClass();
staticVar1.version = 10;
staticVar1.printVersion() // Output 10
StaticClass staticVar2 = new StaticClass();
staticVar2.printVersion() // Output 10
staticVar2.version = 20;
staticVar2.printVersion() // Output 20
staticVar1.printVersion() // Output 20
}
}
main()
は、2つの基本的な制限がある静的メソッドです。
- 静的メソッドは、非静的データメンバーを使用したり、非静的メソッドを直接呼び出したりすることはできません。
-
this()
およびsuper()
は、静的コンテキストでは使用できません。class A { int a = 40; //non static public static void main(String args[]) { System.out.println(a); } }
出力:コンパイル時間エラー
静的変数は静的メソッドでのみアクセスできるため、静的変数を宣言すると、それらのゲッターメソッドとセッターメソッドは静的メソッドになります
静的メソッドは、クラス名を使用してアクセスできるクラスレベルです
以下は、静的変数GetterおよびSetterの例です。
public class Static
{
private static String owner;
private static int rent;
private String car;
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public static int getRent() {
return rent;
}
public static void setRent(int rent) {
Static.rent = rent;
}
public static String getOwner() {
return owner;
}
public static void setOwner(String owner) {
Static.owner = owner;
}
}
最初にいくつかのプロジェクトを実行すると、静的なもの(変数、メソッド、ブロックなど)が読み込まれます。
このプロジェクトを実行すると、メインメソッドが最初にロードされます。その理由は staticメソッド
です。次に、オブジェクト" a"を探します。オブジェクト
。ただし、オブジェクトはまだ定義されていません。その非静的なため。次に、このエラーのようになります。