JAva基本功16課:(2)オブジェクトとメモリ制御

3601 ワード

前言
前のセクションでは、インスタンス変数とインスタンスオブジェクトの違いについて説明しましたが、このセクションでは、変数とオブジェクトについてさらに詳しく説明します.主な内容:
  • インスタンス変数およびクラス変数
  • 親、サブクラスインスタンス変数およびメモリ割り当てメカニズム
  • finalの注意事項
  • 1.インスタンス変数とクラス変数
    1.1定義
  • インスタンス変数:クラスにstatic修飾を使用しない変数、例えばint i;非静的変数
  • とも呼ばれる.
  • クラス変数:クラスにstatic修飾を使用した変数、例えばstatic int i;静的変数
  • とも呼ばれる.
    1.2違い
  • まず、同じJVM内のクラスごとにClassオブジェクトが対応します.つまり、クラスにメモリ領域が1回しか分割されないため、クラス変数は1回のみ初期化されます.インスタンス変数に対して、オブジェクト(インスタンス)が作成されるたびに、新しいメモリ領域が分割されます.したがって、クラスのインスタンスオブジェクトはすべて、クラス変数を共有します.
  • 1.3初期化
  • まずコード
  • を見てください.
    class test{
        //1.weight         
        double weight=2.3;
        {
            weight=4.3;
        }   
        test(){
            this.weight=4.6;
        }
    
    
        // 2.    (   )
        int num1=num2+2;
        static int num2=4;
        
    
        // 3.   name           
        static{
            name="  java";
        }
        static String name="     ";
    
    
    }
    
    
  • 答えはありますか?質問はありますか?
  • まず、クラスの初期化プロセスを理解しなければならない.ステップ1は、クラスオブジェクトを分割するメモリ空間を確立し、変数を初期化する(まずクラス変数を初期化し、次にインスタンス変数を初期化する).ステップ2は、変数を付与し、付与中にコード順に上から下へ付与する.
  • クラス初期化プロセスを理解した後、最初の問題weight=4.6は明らかである.しかし興味深いことに、コンパイル時には、エディタがweight=2.3と非静的コードブロックを構造方法の中に置いていることがわかります.順番は上から下に並んでいるので、結果は4.6にすぎません.
  • なぜ前に引用できるのでしょうか.それは,クラス初期化の際にクラス変数がインスタンス変数と優先的に初期化されるため,前へ参照できるからである.
  • name=「私に丶励ましを」、なぜですか?ここでは初期化が実は2ステップであることをよく説明しているからです.変数は、intが0などのデフォルト値を初期化してから、変数を割り当てます.だからname=null、そしてname=“javaが好きです”、そしてname=“私に丶励まします”.


  • 2.親、サブクラスインスタンス変数およびメモリ割当てメカニズム
    2.1継承の初期化
  • コード
  • を参照
    class father{
        int age=44;
    
       //    
        father(){
            System.out.println("       "+this.age);
            this.say();
        }
        public void say(){
            System.out.println("   say"+this.age);
        }
    }
    
    class son extends father{
        int age=33;
       //    
        son(){
          System.out.println("      ");
        }
        public void say(){
            System.out.println("   say:"+this.age);
        }
    }
    
    public class second{
        public static void main(String[] ages){
           son myson=new son();
    
        }
    }
    
  • 何を出力すると思いますか?
  • 答えは
  •        44
       say:0
          
    
  • なぜ同じthisなのか.1行目は親の44を出力し、2行目は子のメソッドで、しかも0ですか?これはまず継承の初期化問題と,変数を継承する方法と変数の違いに関する.
  • は,まず初期化の際に親クラスを優先的に初期化する.なぜなら,サブクラス構築関数ではsuper()メソッドを先に呼び出し,親クラスを初期化するからである.初期化プロセス全体がfater->sonですしたがって、まず出力されるのは、親の構造方法出力44である.
  • なぜ2番目の文はサブクラスのsay:0なのか.
  • "    son    say()   ,  ,      ,      say() 。"
    

    うん~実はこれは正しくない.まず、このthisが誰なのか理解する必要があります.実はこれはsonです.信じない?
    System.out.println(this.getClass());
    

    出力結果は:class sonです.だから、これは.say()呼び出しの自然はsonのsay()メソッドである.では、なぜ出力が0なのでしょうか.値は親にしか与えられないので、子のageはまだ与えられていませんか、それとも初期値0ですか.
    2.2継承された変数とメソッドの違いおよびメモリ制御
  • 一言で、変数は書き換えられず、書き換え方法があります.
  • はどんな違いがありますか?まださっきのsonクラスとfaterクラスです:
  •        son myson=new son();
           father myfather=myson;
    
           System.out.println(myson.age);
           myson.say();
           System.out.println(myfather.age);
           myfather.say(); 
          //      
    
    33
       say:33
    44
       say:33
    
  • なぜですか?なぜなら、変数は書き換えられていないので、書き換える方法があるからです.したがって、親クラスは自分の変数を呼び出すことができますが、子クラスを呼び出す方法です.
  • 注意深い学生は、なぜ
  • なのかに気づいた.
    father myfather=myson
    

    new子なのに親のageを出力できるのかな?
  • それは、サブクラスオブジェクトを作成するときに、アドレスを分割するときに、メモリアドレスが親クラスの変数であるためである.サブクラスのsuper()は、親クラスの変数を呼び出すことができる値でもあります.(やってみてもいいよ~)
  • 3.finalの注意事項
    3.1 finalメソッドは書き換えることができず,プログラムによって明示的に1回しか値を付与できない.3.2 finalの最大の役割は「マクロ置換」3.3の内部クラスにおける局所変数であり、finalを使用する必要がある.