一文讲清楚static关键字

cnblogs 2024-08-24 08:39:00 阅读 74

static能修饰的地方

  1. 静态变量

    • 静态变量: 又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。
    • 实例变量: 每创建一个实例就会产生一个实例变量,它与该实例同生共死。
  2. 静态方法

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

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

  3. 静态语句块

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

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

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

  5. 静态导包

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

初始化顺序

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

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

  3. 构造方法。

<code>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.seven97.top

公众号:seven97,欢迎关注~



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。