static关键字

static关键字

  1. 相关概念:

    • static翻译为:静态的
    • 所有static关键字修饰的都是类相关的,类级别的
    • 所有static关键字修饰的都是采用“类名.”的方式访问
    • static修饰的变量:静态变量
    • static修饰的方法:静态方法

    补充回顾-变量的分类

    • 变量根据声明的位置进行划分:
      • 在方法体当中声明的变量叫做:局部变量
      • 在方法体外声明的变量叫做:成员变量
        • 而成员变量又可以分为:
          • 实例变量
          • 静态变量

    看相关代码总结知识点:

    class VarTest{
        int i; // i为实例变量
        public void m1(){ // m1()为实例方法
            int x = 200;
        }
        /*
        实例-总结:1.以上都是实例的,对象相关的,访问时采用“引用.”的方式访问,需要new对象。
              2.实例相关的,必须先有对象才能访问,可能会出现空指针异常。
        */
        
        static int k; // k为静态变量
        public static void m2(){ // m2()为静态方法
            int m = 100;
        }
        /*
        静态-总结:1.以上都是静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象。
              2.不需要对象的参与 即可访问,不会导致空指针异常。
        */
    }
    
    • 实例相关的都需要new对象,通过“引用.”的方式访问
    • 静态相关的都用“类名.”的方式访问,也可以使用“引用.”的方式,只不过不建议,因为会让程序员产生困惑:这是实例变量还是静态变量?
  2. 思考:什么时候变量声明为实例的,什么时候声明为静态的呢?

    答:如果这个类型的所有对象的某个属性都是一样的,不建议定义为实例变量,因为会浪费内存空间(原因如下内存图)。即:如果一个对象一份的属性,就定义为实例变量;如果所有对象的属性都是一样的则定义为静态变量。

    如以下 程序所示:

    class Chinese{
        // 身份证号
        String idCard; // 每个人的身份证号都不同,即一个对象一份,应定义为实例变量
        // 姓名
        String name;// 姓名也是如此,应定义为实例变量
        // 国籍
        String country;// 而国籍,对于Chinese类来说,每个人的国籍都是“中国”,不会随着对象的改变而改变
                    // 显然,国籍并不是对象级别的特征
                    // 国籍属于整个类的特征,整个族的特征
        // 所以国籍应该定义为静态变量
        static String contry; // *****重点:静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了
                           // 静态变量存储在方法区
    }
    
    • 静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了;静态变量存储在方法区

    • 那么,如果声明为实例变量,内存图是怎样的?而声明为静态变量,内存图又是怎样的?

      如以下内存图所示:


      (声明为实例变量的内存图)

      (声明为静态变量的内存图)
  3. 思考:什么时候声明实例方法,什么时候声明静态方法

    答:(先记着,后面还会讲)当这个方法体中直接访问了实例变量,这个方法一定时实例方法。

在以后开发中,大部分情况下,如果是工具类的话,工具类当中的方法一般都是静态的(静态方法有一个优点,即不需要new对象,直接采用“类名.”方式调用,极其方便。工具类就是为了方便,所以工具类中的方法一般都是static的)

何为工具类? ....以后说 .....

举例:如:张三考试得了90分,李四考试得了100分,

​ 不同的对象参与考试的结果不同,

​ 我们可以认为"考试"这个行为是与对象相关的行为,

​ 所以应将“考试”这个行为定义为实例方法。

  1. 静态代码块.....实例代码块.......(不是很重要,先略过)

  2. 复习JVM内存管理:

    1. Java中一共有三个变量,须掌握哪个变量存储在哪块内存上。
    2. 栈区:方法只要执行,无论是实例方法、静态方法还是构造方法,都会压栈。(栈区存储局部变量
    3. 堆区:new出来的对象都在堆中,垃圾回收器GC主要针对堆区。(堆区存储实例变量
    4. 方法区:方法区存放的是 类的信息字节码信息代码片段。(方法区存储静态变量
    5. 注:方法的代码片段存储在方法区,但是方法执行过程中需要的内存在栈中。
    public class staticTest{
        // 静态变量在什么时候初始化?  类加载时初始化
        // 静态变量存储在哪里?   方法区
        static int i = 100;
        
        // 静态代码块什么时候执行?    类加载时执行
        static{
            System.out.println("i=" + i); // 这里可以访问i吗?   可以
        }
        
        // 定义实例变量
        int k = 111; // k变量是实例变量,在构造方法执行时内存空间才会开辟
        
        static{
            System.out.println("k="+k); //k变量可以访问吗?    不可以
            /*
            static静态代码块是在类加载时执行,并且只执行一次
            类加载时,k变量空间还没有开辟出来
            所以会报错:无法从静态上下文中引用非静态变量k
            */
            
            System.out.println("name=" + name); // 这里可以访问name吗?  不可以
            /*
            报错:非法前向引用
            静态代码块和静态变量都是在类加载的时候执行,时间相同,只能靠代码顺序来决定谁先谁后
            */
        }
        
        static String name = "lihua";
    }
    
  3. 总结:到目前为止,遇到所有的java程序,有顺序要求的是哪些?

    1. 对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行
    2. 静态代码块1 和静态代码块2 是有先后顺序的
    3. 静态代码块和静态变量是有先后顺序的
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。