美文网首页
Java中的static

Java中的static

作者: 康小曹 | 来源:发表于2021-02-23 15:58 被阅读0次

    一、概念

    在《Java编程思想》P86页有这样一段话:

    “static方法就是没有this的方法。在 static 方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用 static 方法。这实际上正是 static 方法的主要用途。”

    C/C++/OC 中存在全局变量、全局方法的概念,而 Java 中,除了一些特殊的代码,比如 import、enum的声明等,所有的代码都必须写在类中。因此,在 Java 中就不存在全局变量、全局方法这种概念。

    而全局变量就是存储在全局区的变量,直到程序结束时,生命周期才被销毁,Java 中也肯定存在这种需求,所以肯定需要一个替代方案,而 static 就是一种选择。

    静态的概念:

    1. 存储在 data 区(全局区);
    2. 只有一份内存,修改之后影响全局;
    3. Java 中以类为维度,所以会存在一个归属问题,在哪个类中定义,那么这个静态变量/方法就只能通过这个类或者这个类的实例来访问;

    二、场景

    1. static 修饰局部变量

    Java 中的 static 不能修饰局部变量!!!

    其原因可能涉及到:

    1. Java 语言的设计理念问题;
    2. Java 编译器的实现问题,实现一个非必要的功能徒增工作量;
    3. 是否有必要或者已有替代方案(比如类的静态成员变量就可以实现相同的需求);

    2. static 修饰成员变量

    本质上而言,static 修饰成员变量就是和 C 中的 static 一样,将成员变量转移到了 data 区,不改变作用域,改变了生命周期。但是 Java 中代码都写在类中,没有全局变量的概念,所以需要使用类作为承载。

    而 OC 中则不一样。 Java 的设计更加面向对象,就连 main 函数都是对象驱动的,而 OC 中则存在更多面向过程的影子。main 函数的地址是通过 dyld 加载 mach-O 文件时找到并将命令行指向那个位置的。

    因此,OC 中不能使用 static 修饰类成员变量:

    OC是不能使用static修饰成员属性

    究其原因有几点:

    1. 没必要

    OC 中没有以类的维度来划分代码。需要一个全局静态变量直接写在全局代码区(文件的非类、函数区域)即可,需要一个局部静态变量,直接写在栈代码区(函数内部)即可。

    1. 歧义
      如果真这么做了,那么静态变量就和类之间建立了关联,还需要存储和类相关的信息。本质上而言, static 只是改变变量的生命周期,如果和类关联起来,按照 OC 中 ARC 谁持有谁管理的观念,难道类在释放之后,或者在类对象加载时,还要去管理这个静态变量?无意义还引起误会。

    3. static 修饰方法

    static 修饰方法可以用一句话概括:

    • static方法就是没有this的方法。

    其有几个特点:

    1. 不需要对象实例就可以直接调用,作用有点类似于 OC 中的类方法;
    2. 因为没有 this,所以静态方法中不能访问类的非静态成员变量和非静态成员方法;
    3. 静态变量是属于类的,但是也可以通过对象访问(本质还是因为静态意味着data,权限足够而且有办法找到函数地址就可以访问);

    使用示例:

    public class Main {
        public static void main(String[] args) {
            // 不需要对象就可以直接访问
            XKPerson.StaticFunc();
            // 虽然静态方法属于类,但是也可以通过对象访问
            new XKPerson().StaticFunc();
        }
    }
    
    class XKPerson {
        static final String COUNTRY = "CHINA";
        int age;
    
        static public void StaticFunc(){
            System.out.println("StaticFunc");
    
            // static方法中没有this,不能访问非静态成员变量
            System.out.println(age); //compile error
    
            // 可以访问静态成员变量(本质上就是data区的数据)
            System.out.println(COUNTRY);
        }
    }
    

    特殊情况:

    • 对象为 null 时调用静态方法不会出现空指针异常;

    正常情况下,如果一个对象为 null,调用该对象的任何示例方法都将引起空指针异常,但是如果是调用静态方法则可以正常调用:

    对象:

    class XKPerson {
    
        static final String COUNTRY = "CHINA";
    
        static public void StaticFunc(){
            System.out.println("123");
        }
    
        public void InstanceFunc(){
            System.out.println("456");
        }
    }
    

    main函数:

    XKPerson p1 = null;
    p1.StaticFunc();
    p1.InstanceFunc();
    

    结果:

    123
    Exception in thread "main" java.lang.NullPointerException
        at com.company.Main.main(Main.java:15)
    

    四、static 修饰类

    修饰个屁的类哦,你喝多了吧...

    Java 里面 static 一般用来修饰成员变量或函数,但有一种特殊用法是用 static 修饰内部类。

    普通类是不允许声明为静态的,只有内部类才可以。被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类,最常见的使用是解决 AsyncTask 内存泄漏问题:

    public class MainActivity extends AppCompatActivity {
    
        MainAsyncTask asyncTask;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            asyncTask = new MainAsyncTask();
            // 入参会被传递到doInBackground方法中,可以传递多个值
            asyncTask.execute(100);
        }
    
        public static class MainAsyncTask extends AsyncTask<Integer,Integer,String> {
            // asyncTask 逻辑
        }
    }
    

    此时静态内部类 MainAsyncTask 已经不引用 MainActivity 了,所以当 MainActivity 被 destory 打包 MainAsyncTask 还在执行任务时,不会影响 MainActivity 的销毁;

    于此同时

    被 static 修饰的内部类:

    1. 已经不是严格意义上的内部类了;
    2. 不能再使用外部类中的实例方法和属性了(因为相当于和外部类平行,除非传一个外部类的实例对象过来才可以使用);
    3. 内部类不再引用外部类(非静态内部类默认引用外部类);
    4. 因此,使用静态内部类解决 AsyncTask 的内存泄漏问题时,局限性很大,只适用于 AsyncTask 和 外部类 Activity 没有交互时;

    参考:https://blog.csdn.net/vcliy/article/details/85235363

    五、总结

    static 的适用范围,在 C/C++/OC 中:

    1. 修饰局部变量;
    2. 不能修饰成员变量;
    3. 修饰全局变量;
    4. 修饰方法;

    在 Java 中:

    1. 不能修饰局部变量;
    2. 修饰成员变量;
    3. Java 中无全局变量一说;
    4. 修饰方法;

    相关文章

      网友评论

          本文标题:Java中的static

          本文链接:https://www.haomeiwen.com/subject/ewlrfltx.html