写点什么

一文讲清楚 static 关键字

作者:EquatorCoco
  • 2024-08-24
    福建
  • 本文字数:2378 字

    阅读完需:约 8 分钟

static 能修饰的地方


  1. 静态变量

  • 静态变量: 又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。

  • 实例变量: 每创建一个实例就会产生一个实例变量,它与该实例同生共死。


  1. 静态方法

  • 静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。

  • 只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字。


  1. 静态语句块

  • 静态语句块在类初始化时运行一次。


  1. 静态内部类

  • 非静态内部类依赖于外部类的实例,而静态内部类不需要。

  • 静态内部类不能访问外部类的非静态的变量和方法。


  1. 静态导包

  • 在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。


初始化顺序


  1. 静态属性,静态代码块。

  2. 普通属性,普通代码块。

  3. 构造方法。


public class InitOrder {
// 静态属性 private static String staticField = getStaticField();
// 静态代码块 static { System.out.println(staticField); System.out.println("静态代码块初始化"); }
// 普通属性 private String field = getField();
// 普通代码块 { System.out.println(field); System.out.println("普通代码块初始化"); }
// 构造方法 public InitOrder() { System.out.println("构造方法初始化"); }
// 静态方法 public static String getStaticField() { String staticFiled = "静态属性初始化"; return staticFiled; }
// 普通方法 public String getField() { String filed = "普通属性初始化"; return filed; }
public static void main(String[] argc) { new InitOrder(); }
/** * 静态属性初始化 * 静态代码块初始化 * 普通属性初始化 * 普通代码块初始化 * 构造方法初始化 */}
复制代码


静态方法和变量能否被继承


先说结论:能


父类 A:


public class A {    public static String staticStr = "A静态属性";    public String nonStaticStr = "A非静态属性";    public static void staticMethod(){        System.out.println("A静态方法");    }    public void nonStaticMethod(){        System.out.println("A非静态方法");    }}
复制代码


子类 B:

public class B extends A{
public static String staticStr = "B改写后的静态属性"; public String nonStaticStr = "B改写后的非静态属性";
public static void staticMethod(){ System.out.println("B改写后的静态方法"); }
@Override public void nonStaticMethod() { System.out.println("B改写后的非静态方法"); }}
复制代码


子类 C:


public class C extends A{}
复制代码


测试:


public class Demo {    public static void main(String[] args) {        C c = new C();//C的引用指向C的对象        System.out.println(c.nonStaticStr);//A非静态属性        System.out.println(c.staticStr);//A静态属性        c.nonStaticMethod();//A非静态方法        c.staticMethod();//A静态方法        //推出静态属性和静态方法可以被继承
System.out.println("-------------------------------");
A c1 = new C();//A的引用指向C的对象 System.out.println(c1.nonStaticStr);//A非静态属性 System.out.println(c1.staticStr);//A静态属性 c1.nonStaticMethod();//A非静态方法 c1.staticMethod();//A静态方法 //推出静态属性和静态方法可以被继承
System.out.println("-------------------------------"); B b = new B();//B的引用指向B的对象 System.out.println(b.nonStaticStr);//B改写后的非静态属性 System.out.println(b.staticStr);//B改写后的静态属性 b.nonStaticMethod();//B改写后的非静态方法 b.staticMethod();//B改写后的静态方法
System.out.println("-------------------------------"); A b1 = new B();//A的引用指向B的对象 System.out.println(b1.nonStaticStr);//A非静态属性 System.out.println(b1.staticStr);//A静态属性 b1.nonStaticMethod();//B改写后的非静态方法 b1.staticMethod();//A静态方法 //结果都是父类的静态方法,说明静态方法不可以被重写,不能实现多态 }}
复制代码


注意


静态变量尤其要注意并发问题。因为静态变量在 Java 中是类级别的变量,它们被所有类的实例共享。由于静态变量是共享资源,当多个线程同时访问和修改静态变量时,就会引发并发问题。


总结


  • 子类会继承父类的静态方法和静态变量,但是无法对静态方法进行重写


  • 子类中可以直接调用父类的静态方法和静态变量


  • 子类可以直接修改(如果父类中没有将静态变量设为 private)静态变量,但这是子类自己的静态变量。


  • 子类可以拥有和父类同名的,同参数的静态方法,但是这并不是对父类静态方法的重写,是子类自己的静态方法,子类只是把父类的静态方法隐藏了。


  • 当父类的引用指向子类时,使用对象调用静态方法或者静态变量,是调用的父类中的静态方法或者变量(这比较好理解,因为静态方法或变量是属于类的,而引用指向的是一个对象,对象中并不会包含静态的方法和属性)。也就是说,失去了多态。


  • 当子类的引用指向子类时,使用对象调用静态方法或者静态变量,就是调用的子类中自己的的静态方法或者变量了。


文章转载自:Seven

原文链接:https://www.cnblogs.com/seven97-top/p/18377083

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

EquatorCoco

关注

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
一文讲清楚static关键字_Java_EquatorCoco_InfoQ写作社区