李興華Java 8ノート17:staticキーワード詳細

37892 ワード

1.static定義属性


staticを説明する前に、まずコードを観察します.
class Book{
	private String title;
	private Double price;
	String pub = " ";

	public Book(String title,Double price){
		this.title = title;
		this.price = price;
	}

	public String getInfo(){
		return " :"+this.title+"、 :"+this.price+"、 :"+this.pub;
	}
}

public class Hello{
	public static void main(String[] args){
		Book book1 = new Book("Java",12.2);
		Book book2 = new Book("python",132.2);
		Book book3 = new Book("C++",52.2);
      
        // static 
        //  , 
		book1.pub = " ";	

		System.out.println(book1.getInfo());	//  ...
		System.out.println(book2.getInfo());	//  ...
		System.out.println(book3.getInfo());	//  ...
	}
}

メモリ解析
メモリにより,各オブジェクトの出版社情報は同じであることが分かったが,この場合,各オブジェクトが独立して同じ属性情報を占有する必要があるのだろうか.私たちがこの方法で1000 Wの図書の情報を保存したとすれば、出版社はみな同じで、同じ属性を独占している.この1000 W本の出版社情報をさらに変更するには、1000 W回の変更が必要です.
以上のように、属性を通常の方法で定義すると、各オブジェクトは独立してそれぞれの属性情報を保存する.この構造式はメンテナンスが不便です.さらに、各オブジェクトに同じプロパティがある場合は、共有する必要があります.共有する方法はstaticキーワードで修飾することです
class Book{
	private String title;
	private Double price;
	static String pub = " ";

	public Book(String title,Double price){
		this.title = title;
		this.price = price;
	}

	public String getInfo(){
		return " :"+this.title+"、 :"+this.price+"、 :"+this.pub;
	}
}

public class Hello{
	public static void main(String[] args){
		Book book1 = new Book("Java",12.2);
		Book book2 = new Book("python",132.2);
		Book book3 = new Book("C++",52.2);
		
		// static 
        //  , 
		book1.pub = " ";

		//  
		System.out.println(book1.getInfo());
		System.out.println(book2.getInfo());
		System.out.println(book3.getInfo());
	}
}

メモリの割り当て
staticキーワードで修飾されたプロパティは、複数のオブジェクトによって同時に指向されるグローバルデータ領域である独立したメモリに格納されます.また、各オブジェクトには属性情報が個別に格納されません.
staticが共通の属性である以上、前のコードでは、1つのオブジェクトで属性を変更するのは適切ではなく、正しい方法はすべてのオブジェクトの共通の代表によって属性を変更することです.この代表はクラスです.簡単に言えば、staticキーワードによって修飾されたプロパティは、クラスによって直接呼び出されます.したがって、pubプロパティを変更するには、次のコードを使用します.変更後、すべてのオブジェクトに有効になります.
Book.pub = " ";

staticと非static修飾のプロパティには最大の違いがあります.static修飾のプロパティは、オブジェクトをインスタンス化する必要がなく、クラスによって直接呼び出されます.では、いつstaticで修飾しますか.いつ使いませんか.
クラスを作成する過程で、あなたが選択した主な修飾子はstaticではなく、95%の場合staticではありません.共有情報を記述するときにstaticを使用すると、集団で修正したり、スペースを節約したりすることができます.

2.static定義方法


static定義メソッドは、インスタンス化されていないときにクラスによって直接呼び出されることもできます.
class Book{
	private String title;
	private Double price;
	private static String pub = " ";

	public Book(String title,Double price){
		this.title = title;
		this.price = price;
	}

	public String getInfo(){
		return " :"+this.title+"、 :"+this.price+"、 :"+this.pub;
	}

	public static void setPub(String p){
		pub = p;
	}
}

public class Hello{
	public static void main(String[] args){
		//  static , static 
		Book.setPub(" ");

		Book book1 = new Book("Java",12.2);
		Book book2 = new Book("python",132.2);
		Book book3 = new Book("C++",52.2);
			
		//  
		System.out.println(book1.getInfo());
		System.out.println(book2.getInfo());
		System.out.println(book3.getInfo());
	}
}

staticによって修飾されたメソッドと属性は、インスタンス化されたクラスによって制限されず、クラスによって直接呼び出されることがわかります.しかし、このとき特に面倒な問題が発生し、クラスのメソッドは2つのグループになります.1つはstaticメソッドで、1つは非staticです.2つのグループのメソッド間の相互アクセスも制限されます.
  • staticメソッドは、static修飾以外のプロパティまたはメソッドにアクセスできず、staticプロパティおよびメソッド
  • のみを呼び出すことができます.
    class Book{
    	private String title;
    	private Double price;
    	private static String pub = " ";
    
    	public Book(String title,Double price){
    		this.title = title;
    		this.price = price;
    	}
    
    	//  static static 
    	public static String getInfo(){
    		return " :"+this.title+"、 :"+this.price+"、 :"+this.pub;
    	}
    
    }
    
    public class Hello{
    	public static void main(String[] args){
    		Book.getInfo();	// 
    	}
    }
    
  • 非staticメソッドは、非static修飾の属性またはメソッドにアクセスすることができ、
  • は何ら制限されない.
    class Book{
    	private String title;
    	private Double price;
    	private static String pub = " ";
    
    	public Book(String title,Double price){
    		this.title = title;
    		this.price = price;
    	}
    
    	public static String getInfo(){
    		return " :"+pub;
    	}
    
    	//  static static 
    	public String getPub(){
    		return this.getInfo();
    	}
    }
    
    public class Hello{
    	public static void main(String[] args){
    		Book.getInfo();	//  
    	}
    }
    

    どうしてこんなことになったの?
  • すべての非static修飾の属性と方法は、オブジェクトをインスタンス化した後にのみ空間が割り当てられ、アクセスされます.
  • すべてのstatic修飾の方法は、インスタンス化オブジェクトがないときにすでにスペースがあり、
  • にアクセスできます.
    主クラスでのメソッドは、staticメソッドを付けて修飾されるのが一般的ですが、付けないとエラーが表示されます.以下のようにします.
    public class Hello{
    	public static void main(String[] args){
    		fun();// 
    	}
    
    	public void fun(){
    		System.out.println("hello");
    	}
    }
    

    プライマリクラスをインスタンス化してfunメソッドを呼び出すと、エラーは発生しません.
    public class Hello{
    	public static void main(String[] args){
    		new Hello().fun();// 
    	}
    
    	public void fun(){
    		System.out.println("hello");
    	}
    }
    

    では、いつstaticで修飾するのでしょうか.
  • クラスを定義するときは、まず非staticメソッド
  • を考慮する.
  • あるクラスのメソッドが、本クラスの非static属性を使用する必要がある場合は、static定義メソッド
  • を使用しないでください.
    class Book{
    	private boolean flag;
    
    	public Book(boolean falg){
    		this.flag = flag;
    	}
    
    	public void fun(){
    		if(this.flag){
    			System.out.println(" ");
    		}else{
    			System.out.println(" ");
    		}
    	}
    }
    
    public class Hello{
    	public static void main(String[] args){
    		Book b1 = new Book(true);
    		Book b2 = new Book(false);
    
    		b1.fun();
    		b2.fun();
    	}
    
    }
    
  • クラスにメソッドのみがあり、属性がない場合はstaticメソッドを完全に定義できるため、クラスを生成することなくメソッドを呼び出すことができます.
  • class Book{
    	public static int sum(int x, int y){
    		return x + y;
    	}
    }
    
    public class Hello{
    	public static void main(String[] args){
    		System.out.println(Book.sum(5,6));
    	}
    }
    

    3.主な方法


    メソッドの構成は次のとおりです.
  • public:主な方法はプログラムの開始であるため、必ずいかなる操作に対しても可視であるため、publicで共通の概念を記述しなければならない.
  • static:このメソッドがクラス名によって呼び出されたことを証明します.クラスを実行するときに実行されるからです.java+クラス名
  • です.
  • void:戻り値がない
  • main:システムが指定したメソッド名は、変更できません.
  • String[]args:プログラム実行時に渡されるパラメータ.

  • コンパイルファイルを実行するときに、主クラス名の後ろにスペースで区切られたパラメータを付けることができます.パラメータ自体にスペースがある場合は、二重引用符で囲むことができます.
    public class Hello{
    	public static void main(String[] args){
    		for(int i = 0; i<args.length; i++){
    			System.out.println(args[i]);
    		}
    	}
    }
    //  
    java Hello "hello world" hello word
    
    // 
    hello world
    hello
    word
    

    3.staticの実用化

  • オブジェクトの数にかかわらず、同じクラスでstaticで定義された属性
  • です.
  • staticメソッドを使用すると、インスタンス化オブジェクト呼び出しメソッドの制限
  • を回避することができる.

    3.1クラスインスタンス化対象個数の統計を実現する


    オブジェクトをインスタンス化するたびに、x番目のインスタンス化オブジェクトを生成する情報を印刷することが望ましい.
    新しいインスタンス化オブジェクトが生成されると、コンストラクションメソッドが呼び出されるので、コンストラクションメソッドでインスタンス化オブジェクトの回数を1回加算することができます.
    class Book{
    	private String title;
    	private static int num = 0;
    	public Book(String title){
    		this.title = title;
    		this.num = ++this.num;
    		System.out.println(" "+this.num+" ");
    	}
    }
    
    public class Hello{
    	public static void main(String[] args){
    		Book boo1 = new Book("java");
    		Book boo2 = new Book("java");
    		Book boo3 = new Book("java");
    		Book boo4 = new Book("java");
    	}
    }
    
    // 
     1 
     2 
     3 
     4 
    

    4.まとめ

  • 開発における優先属性はstatic属性ではなく、方法はstatic方法ではない
  • staticプロパティおよびメソッドは、インスタンス化されずにクラスによって直接呼び出され得る.
  • staticプロパティは、グローバルデータ領域
  • に保存されます.
  • メモリには、スタックメモリ、スタックメモリ、グローバルデータ領域、グローバルコード領域
  • の4つの領域があります.