static关键字

目录

一.static关键字是什么

二、java为什么设计static关键字

1.假设方法和变量上没有static关键字

 2.假设方法和变量上有static关键字

 3.static关键字怎么用

(1)修饰变量

(2)修饰方法

①static修饰的方法无法调用到非静态方法

②非静态方法可以调用静态方法

(3)修饰代码块

三、和static有关的三道题

1.

2.

3.


一.static关键字是什么

1.static修饰的代码属于类

2.定义的变量存储在方法区的静态常量池中

二、java为什么设计static关键字

方便类直接去使用自己的方法和变量

1.假设方法和变量上没有static关键字

(1)如果方法和变量是非静态的,他们只有在对象当中才会被分配内存空间,也就是只有对象才能调用

(2)A类中的这些代码只是以信息的形式存储在方法区当中,并没有独立的存储空间,

当main方法入栈,执行A a=new A();  的时候,才在堆内存里有了存储空间

A.java

public class A {
    public String name="admin";
    public void run(){

    }
    public void flay(){

    }
}

 Test.java

public class Test {
    public static void main(String[] args) {
        A a=new A();
        a.run();
        a.flay();
        a.name="aa";
    }

}

(3)堆栈内存图: 

 2.假设方法和变量上有static关键字

(1)方法和变量能直接被类调用,因为它们在方法区中已经有了自己独立的存储空间

(2)从上个知识点可以看出:如果没有static关键字,那么类是不可以调用自己的属性和方法的,只能用对象去调用

(3)此时A中的信息直接存储在方法区中的静态常量池中,被所有对象共享,拥有独立的存储空间

A.java

public class A {
    public static String name="admin";
    public static void run(){

    }
    public static void flay(){

    }
}

 Test.java

(4)

A a=new A();
a.run();
a.flay();
a.name="aa";

这些代码没有报错,是因为对象来源于类,那么对象可以使用类的信息

但是推荐使用:

A.name="b";
A.run();
A.flay();

 (5)堆栈内存图: 

 三、static关键字怎么用

static可以修饰变量、方法和代码块

1.修饰变量

stati修饰的变量属于类变量,存储在方法区的静态常量池中,被所有对象共享

比如:

public class A {
    public static String name="admin";
    public String address="张三";
    public void run(int num){
        System.out.println("跑了"+num+"米");
    }
    @Override
    public String toString() {
        return "A{" +
                "name='" + name + '\'' +
                "address='" + address + '\'' +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {
        A a1=new A();
        A a2=new A();
        a1.name="李四";
        a1.address="北京";
        a1.run(10);
        a2.name="王五";
        a2.address="上海";
        a2.run(20);
        System.out.println(a1.toString());
        System.out.println(a2.toString());
    }
}

 输出:

堆栈内存图:
 

static修饰的变量被所有类共享

方法谁调用就是谁的,方法是使用;而这个变量相当于内存空间,共享的是一块空间

2.修饰方法

(1)static修饰的方法无法调用到非静态方法

如果一个方法想要被main方法/静态方法调用,两种方法:

1在非静态方法上加上static
2在main方法中创建对象,让对象调用该非静态方法

(2)非静态方法可以调用静态方法

比如:

原因:

flay()想要表达的时候就已经创建好了对象,有对象就一定有类(类是创建对象的模板),那么静态方法一定是存在的

3.修饰代码块

在main方法之前运行,目的是优化程序运行

例如:

public class Test extends Base{
    public Test(){
        System.out.println("test constructor");
    }

    public static void main(String[] args) {
        new Test();
    }
    static {
        System.out.println("test static");
    }
}
class Base{
    static {
        System.out.println("base static");
    }
    public Base(){
        System.out.println("base constructor");
    }

}

运行结果:

这样输出的原因:

执行过程:扫描----加载/编译----运行

程序执行先去找main()方法启动程序

1.扫描Test类,发现有父类Base类,先去扫描父类,发现Base类没有父类

2.将Base.class加载进方法区,此时Base类中的static代码块执行,所以先输出base static

3.将Test.class加载进方法区,此时Test类中的static代码块执行, 所以然后输出 test static

4,main方法入栈,main执行new Test();去创建Test类的对象

5.创建子类对象之前先创建父类对象,所以先执行Base()构造器,再执行Test()构造器,所以最后输出 base constructor和test constructor

四、和static有关的三道题

1.

public class Test {
    private static int a;
    public static void main(String[] args) {
        modify(a);
        System.out.println(a);
    }
    public static void modify(int a){//这个是局部变量(只在方法内部起作用)
        a++;
    }
}

输出:

 原因:

堆栈内存图:

下一步是modify()这个方法出栈 ,出完栈之后输出的是全局变量a的值,即0

2.

public class Test {
    private int a;
    public static void main(String[] args) {
        Test a1=new Test();
        modify(a1.a);
        System.out.println(a1.a);
    }
    public static void modify(int a){
        a++;
    }
}

输出:

 原因:

堆栈内存图:

 下一步是modify()这个方法出栈 ,出完栈之后输出的是全局变量a的值,即0

3.

public class Demo {
    public Demo(String aa){
        System.out.println("==="+aa);
    }
    static {
        System.out.println("11");
    }
    public static Demo demo=new Demo("+++");
    static {
        System.out.println("22");
    }
}

class Test1{
    public static void main(String[] args) {
        Demo demo=new Demo("----");
    }
}

运行结果:
 

执行过程:扫描----加载/编译----运行

(1).main方法在哪里,就先扫描哪个类,先扫描Test类,发现没有父类,也没有static修饰的代码,那么编译Test类,并且main方法入栈

(2).执行Demo demo=new Demo("----");之前扫描Demo类,发现没有父类,所以编译Demo类,在编译的过程中,static代码块按顺序优先执行

(3).首先输出 11

(4).执行 public static Demo demo=new Demo("+++"); 此时涉及到调用Demo构造方法,输出 ===+++

(5).输出 22

(6).编译完毕,回到main方法中继续执行 new Demo("----"); 现在可以创建对象了,也就是进行到了运行阶段

(7).通过调用构造器创建对象:===----

(8).输出===----

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值