Java static关键字与静态块 - Go语言中文社区

Java static关键字与静态块


一.static修饰符

static 修饰符能够与属性、方法和内部类一起使用,表示是“静态”的。

类中的静态变量和静态方法能够与“类名”一起使用,不需要创建一个类的对象来访问该类的静态成员。所以static修饰的变量又称作“类变量”。这与实例变量不同。实例变量总是用对象来访问,因为它们的值在对象和对象之间有所不同。

下列示例展示了如何访问一个类的静态变量:
class StaticModifier {
    static int i = 10;
    int j;
    StaticModifier() {
        j = 20;
    }
}
public class Test {
    public static void main(String args[]) {
        System.out.println("类变量 i=" + StaticModifier.i);
        StaticModifier s = new StaticModifier();
        System.out.println("实例变量 j=" + s.j);
    }
}
上述程序的输出是:
类变量 i=10
实例变量 j=20

二.static属性的内存分配

在上面的例子中,无需创建类的对象即可访问静态变量 i。之所以会产生这样的结果,是因为编译器只为整个类创建了一个静态变量的副本,因此它能够用类名进行访问。也就是说:一个类中,一个 static 变量只会有一个内存空间,虽然有多个类实例,但这些类实例中的这个static 变量会共享同一个内存空间。示例如下:
public class Test {
    public static void main(String[] args) {
        UserModel um1 = new UserModel();
        um.userName = "张三";
        um.country = "china";
        UserModel um2 = new UserModel();
        um2.userName = "李四";
        um2.country = "中国";
        System.out.println("um1.userName==" + um1.userName +" um1.country==" + um1.country );
        System.out.println("um2.userName==" + um2.userName +" um2.country==" + um2.country );
    }
}
class UserModel {
    public static String country
    public String userName;
}
运行结果:
um1.userName==张三 um1.country==中国
um2.userName==李四 um2.country==中国

为什么会是一样的值呢?就是因为多个UserModel 实例中的静态变量country 是共享同一内存空间,um1.country 和 um2.country 其实指向的都是同一个内存空间,所以就得到上面的结果了。

在对象um2创建前的运行后内存分配示意图如下:


在对象um2创建后的运行后内存分配示意图如下:


要想看看是不是 static 导致这样的结果,你可以尝试去掉country前面的 static,然后再试一试,看看结果,应该如下:
    um1.userName==张三 um1.country==china
    um2.userName==李四 um2.country==中国
还有一点也很重要:static 的变量是在类装载的时候就会被初始化。也就是说,只要类被装载,不管你是否使用了这个static 变量,它都会被初始化。

小结一下:类变量(class variables)用关键字 static 修饰,在类加载的时候,分配类变量的内存,以后再生成类的实例对象时,将共享这块内存(类变量),任何一个对象对类变量的修改,都会影响其它对象。外部有两种访问方式:通过对象来访问或通过类名来访问。

三.static的基本规则

有关静态变量或方法的一些要点如下:

  • 一个类的静态方法只能访问静态属性;
  • 一个类的静态方法不能够直接调用非静态方法;
  • 如访问控制权限允许,static 属性和方法可以使用对象名加“.”方式调用;当然也可以使用实例加“.”方式调用;
  • 静态方法中不存在当前对象,因而不能使用“this”,当然也不能使用”super”;
  • 静态方法不能被非静态方法覆盖;
  • 构造方法不允许声明为 static 的;
  • 局部变量不能使用static修饰。

static 方法可以用类名来访问,如:
public class GeneralFunction {
    public static int addUp(int x, int y) {
        return x + y;
    }
}
public class UseGeneral {
    public void method() {
        int a = 9;
        int b = 10;
        int c = GeneralFunction.addUp(a, b);
        System.out.println("addUp() gives " + c);
    }
}
因为 static 方法不需它所属的类的任何实例就会被调用,因此没有 this 值。结果是,static方法不能访问与它本身的参数以及 static 变量之外的任何变量,访问非静态变量的尝试会引起编译错误。

注:非静态变量只限于实例,并只能通过实例引用被访问。

四.静态初始器——静态块

静态初始器(Static Initializer)是一个存在与类中方法外面的静态块。静态初始器仅仅在类装载的时候(第一次使用类的时候)执行一次。静态初始器的功能是:往往用来初始化静态的类属性。

示例:
class Count {
    public static int counter;
    static {// 只运行一次
        counter = 123;
        System.out.println("Now in static block.");
    }
    public void test() {
        System.out.println("test method==" + counter);
    }
}
public class Test {
    public static void main(String args[]) {
        System.out.println("counter=" + Count.counter);
        new Count().test();
    }
}
运行结果是:
Now in static block. counter=123
test method==123

五.静态import

当我们要获取一个随机数时,写法是:
public class Test {
    public static void main(String[] args) {
        double randomNum = Math.random();
        System.out.println("the randomNum==" + randomNum);
    }
}
从 JDK5.0 开始可以写为:
import static java.lang.Math.random;
public class Test {
    public static void main(String[] args) {
        double randomNum = random();
        System.out.println("the randomNum==" + randomNum);
    }
}
静态引用使我们可以象调用本地方法一样调用一个引入的方法,当我们需要引入同一个类的多个方法时,只需写为“import static java.lang.Math.*”即可。这样的引用方式对于枚举也同样有效。

转载于:https://www.cnblogs.com/chateldon/archive/2013/05/01/3053296.html

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_30348519/article/details/95695157
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-07 19:48:40
  • 阅读 ( 641 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢