Static关键字详解

Static关键字是什么

static修饰的代码属于类

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

java为什么要设置static关键字?

因为要方便类去使用自己的方法和变量

例如:

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

package Work1;

public class A {
    public  String name="张三";
    public void run(){
        System.out.println("跑得很快");
    }
    public void fly(){
        System.out.println("飞得很高");
    }
    //这些代码以信息的形式存储在内存方法区当中(是二进制的代码),只有创建对象时,这些非静态的方法和变量才会有独立的存储空间,被对象调用
}

这些代码以信息的形式存储在内存方法区当中(是二进制的代码),只有创建对象时,这些非静态的方法和变量才会有独立的存储空间,被对象调用

package Work1;

public class Test {
    public static void main(String[] args) {
    //假设方法和变量上面没有static关键字
        A a=new A();
        a.run();
        a.fly();
        a.name="aaa";//只能由对象调用
        //如果方法和变量属于非静态方法,他们只有在对象当中,才会被分配内存空间,那么也就是只能由对象才能调用
       //如果没有static关键字,那么类是不可以调用自己的属性和方法的,只能用对象去调用

    }
}

如果没有static关键字,方法和变量属于非静态方法,那么类是不可以调用这些属性和方法的,只能用对象去调用

堆栈内存图如下

方法和变量上面有static关键字修饰

public class A {
    public static String name="张三";
    public static void run(){
        System.out.println("跑得很快");
    }
    public static void fly(){
        System.out.println("飞得很高");
    }

}
package Work1;

public class Test {
    public static void main(String[] args) {

        A a=new A();
        a.run();
        a.fly();
        a.name="aaa";
        //对象来源于类,那么对象可以使用类的信息,因此可以通过调用方法和变量
        //可以直接用类调用
        A.name="bbb";
        A.run();
        A.fly();
        //因为在方法区的静态常量池当中由独立的内存空间


    }
}

因为在方法区的静态常量池当中由独立的内存空间,可以直接用类调用。对象来源于类,那么对象可以使用类的信息,因此可以通过调用方法和变量 。

堆栈内存图:

Static关键字如何使用?

staic修饰变量

package Work1;

public class A {
    //static修饰的变量属于类变量,存储在方法区的静态常量池当中,被所有对象所共享
    public static String name="张三";
    public String address="保定";

    @Override
    public String toString() {
        return "A{" +
                "address='" + address + '\'' +
                "name='" + name + '\'' +
                '}';
    }
}
public class Test {
    public static void main(String[] args) {

        A a1=new A();
        A a2=new A();
        a1.address="北京";
        a1.name="aaa";
        a1.address="上海";
        a1.name="bbb";
        System.out.println(a1.toString());
        System.out.println(a2.toString());



    }
}

修饰方法

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

解决方案:

1.在非静态方法上加上static关键字 

2.在main1方法当中创建对象,让对象调用非静态方法

2.在非静态方法可以调用静态方法

原因:非静态方法想要表达,已经创建了对象,那么静态方法一定存在, 有对象一定有类

修饰代码块

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

例1

程序执行流程:

1.首先main方法入栈

2.main方法会调用hhh方法,hhh方法会将静态常量池中的a的值赋给入参

3.a++入参的值变为1

4.然后hhh方法出栈

5.继续执行main函数中的System.out.println(a); 输出静态常量池当中a的值

例2

程序执行流程:

1.首先main方法入栈

2.创建一个A类的对象a1

3.调用及静态常量池当中的hhh()方法入栈

4.将对象a1的私有属性a赋给入参

5.执行hhh()方法当中的return a++:入参加1变为1

6.hhh()出栈

7.继续执行main方法当中的

System.out.println(a);输出对象a1的私有属性a

例3
package Work1;

public class E {
    public E(String a){
        System.out.println("===="+a);
    }
    static {
        System.out.println("11");

    }
    public static E e=new E("+++");
    static{
        System.out.println("22");
    }
}

class T {
    public static void main(String[] args) {
      E e=new E("----");
    }
}

程序执行的流程:

扫描-------->加载(编译)--------->运行

main在哪里先扫描哪个类

1.首先扫描Test类,发现其没有父类,也没有static修饰的代码,那么先编译Test类,并且将main方法入栈

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

3.static {

System.out.println("11");

}先执行该static代码块,输出“11”

4.再执行public static E e=new E("+++");此时会涉及到E类当中的构造方法,输出“====++++”

5.最后执行

static{

System.out.println("22");

}输出“22”

6.编译阶段完毕,回到main方法当中,继续执行new E("----");现在可以创建对象,真正运行

7.通过调用构造器创建对象,输出“====----”

例4
package work2;

public class Test {
    public static void main(String[] args) {
        Person p1=new Person();
        Person p2=new Person();
        p1.name="李四";
        p1.address="北京";
        p2.name="张三";
        p2.address="上海";
        System.out.println(p1.toString());
        System.out.println(p2.toString());

    }
}
package work2;

public class Person {

    public  String name;

    //static修饰符修饰的代码属于类代码,没有static修饰的代码属于对象
    public static String address="保定";

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                "address='" + address + '\'' +
                '}';
    }
}

类信息是存储在方法区当中的

static修饰的代码会存储在方法区的静态常量池当中

程序执行流程

1.main方法入栈

2.创建p1 p2两个对象

3.最开始将p1,p2两个对象的name均为“张三”

4.给p1变量的name赋值,address赋值

5.给p1变量的name赋值,address赋值

如果static修饰方法,方法也是共享的,类似于工具被使用

例5
package work2;

public class Test {
    public static void main(String[] args) {
        Person p1=new Person();
        Person p2=new Person();
        p1.name="李四";
        p1.address="北京";
        p1.run("100");
        p2.name="王五";
        p2.address="上海";
        p2.run("200");
        System.out.println(p1.toString());
        System.out.println(p2.toString());

    }
}

package work2;

public class Person {

    public  String name;

    //static修饰符修饰的代码属于类代码,是被对象所共享的,没有static修饰的代码属于对象
    public static String address="保定";
    public static void run(String num){
        System.out.println("跑了"+num+"米");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                "address='" + address + '\'' +
                '}';
    }
}

run方法入栈执行

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

欢迎点赞,收藏,和关注呦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值