2024/8/21记:Java基础--关键字:static关键字


static关键字

2024/8/21记
2024/8/21下午课


1.static关键字

static修饰符修饰的代码属于类代码
(对所有对象共享)
没有用static修饰符修饰的代码属于对象

public class Person {
    private int age;
    private String name;
    private char sex;
    
    public void run(){
        System.out.println("人走路");
    }
    public void fly(){
        System.out.println("人不会飞");
    }
    public static void main(String[] args) {
        
    }
}

你可能会觉得:run(),fly()这样的方法也都是在类里面的,为什么说它是属于对象。
它们也属于类,但严格来说,他们是对象所拥有的。

2.代码举例(好例子,易错,便于理解)——static修饰变量

static修饰变量

Person类

public class Person {
    public String name="张三";
    public static String address="保定";
    public String toString(){
        return "Person{"+"name='"+name+'\''+
                "address='"+address+'\''+
                '}';
    }
}

Test类(测试类,无实际意义,测试用)

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());

    }
}

你可能想到的结果:
Person{name='李四’address=‘北京’}
Person{name='王五’address=‘上海’}

实际上:
Person{name='李四’address=‘上海’}
Person{name='王五’address=‘上海’}

3.画图解释

用代码流程图解释(堆栈图):

类信息存储在方法区里面。
方法区里面有个专门的区域叫:静态常量池。静态常量池里面存储的是static所修饰的代码。

步骤一
画图解释
步骤二
在这里插入图片描述
步骤三
在这里插入图片描述

所以,最后输出结果是:
Person{name='李四’address=‘上海’}
Person{name='王五’address=‘上海’}

由此也可以看出,static修饰的变量被所有类共享的

4.代码举例:加深理解——static修饰方法

static修饰方法

Person类

public class Person {
    public String name="张三";
    public static String address="保定";
    public String toString(){
        return "Person{"+"name='"+name+'\''+
                "address='"+address+'\''+
                '}';
    }
    public static void run(String num){
        System.out.println("跑了"+num+"米");
    }
}

Test类(测试类,无实际意义,测试用)

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());
        p1.run("100");
        p2.run("200");
    }
}

实际上结果:
Person{name='李四’address=‘上海’}
Person{name='王五’address=‘上海’}
跑了100米
跑了200米

5.画图解释

1、p1调用run()方法
2、run()方法入栈
3、 执行函数:跑了100米 (因为传参就是传的100)
4、 run()方法出栈

同理:

1、p2调用run()方法
2、run()方法入栈
3、 执行函数:跑了200米 (因为传参就是传的200)
4、 run()方法出栈

在这里插入图片描述
静态变量是类共享的,静态方法也是类共享的
都是共享的。
但是对于变量来说,它相当于一块内存空间。只要一变,就都变了。
对于方法来说,谁调用就是谁的。相当于工具。会进行入栈出栈的使用。

6.总结

static修饰的代码块是属于类的。
属于类的东西是被所有对象共享的。

为什么是共享的?
因为类是创建对象的模板。
类可以生成很多对象。
类里面的东西是被对象共享的。


1.static修饰变量

static修饰符修饰的变量叫做类变量。
被 所有 该类所产生的对象 所共享。

2. static修饰方法

方法分为静态方法和非静态方法。
static修饰的方法属于静态方法。
静态方法能直接被main方法使用
非静态方法不能直接被静态方法所使用
静态方法只能被静态方法所调用
main方法本身属于静态方法。
static修饰的方法才能调用static修饰的方法

3. static修饰代码块

static修饰的代码块在main方法之前运行。
作用是:优化程序

程序执行第一步:main方法入栈
main方法入栈之前:static修饰的代码块在main方法之前运行,其目的是优化程序。(无论static修饰的代码块放在哪里)


复习一:由此引出复习static修饰代码块相关知识点:static在main方法入栈之前执行的过程

(很全面,知识点+代码+顺一遍流程,不用翻看前面笔记,直接在这里回顾就行)

步骤一

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

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

程序执行先去找main()方法启动程序
先扫描再编译
1.首先 先去扫描Test类,发现Test类有父类Base类,先去扫描父类,发现Base类没有父类
2.将Base.class加载进方法区,此时Base类当中的static代码块执行
3.将Test.class加载进方法区(只有.class文件才能进方法区),此时Test类当中的static代码块执行
(static在main方法入栈之前执行)
4.main方法入栈——》执行new Test();去创建Test类的对象
5.创建子类对象之前先创建父类对象,所以先执行Base()构造器,再执行Test()构造器

步骤二,变形,加深理解。

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

程序执行先去找main()方法启动程序
先扫描再编译
1.首先 先去扫描Base类,发现Base类没有父类
2.将Base.class加载进方法区,此时Base类当中的static代码块执行(输出1)
3.main方法入栈——》执行new Test();去创建Test类的对象
4.扫描Test类时,发现Test类有父类Base。但Base类已经加载过了,不会重复加载。
5.将Test.class加载进方法区,此时Test类当中的static代码块执行(输出二)
6.创建子类对象之前先创建父类对象,所以先执行Base()构造器,再执行Test()构造器
(static在main方法入栈之前执行)

步骤三,复习的时候:自己一边顺一遍,一边大致画一下流程图+看笔记。自己画一遍!然后别放到笔记里了。反复画就行。如图:

在这里插入图片描述

在这里插入图片描述

复习二:方法的重写

用流程图理解大致的流程就行。复习的时候自己画。

步骤一
A类

public class A {
    public void run(){
        System.out.println("跑得快");
    }
    public void fly(){
        System.out.println("飞得高");
    }
}

B类

public class B extends A{
    }
}

测试类1

public class Test {
    public static void main(String[] args) {
        B b=new B();
        b.run();
        b.fly();
    }
}

结果:
跑得快
飞得高

流程图
一、
main方法入栈
创建B对象——》在创建B对象的时候,优先创建父类A的对象

堆用来存储对象
对象是堆里面的一块空间

因为继承关系,所以B可以使用A中的代码
a对象里面有run(),fly()方法。
所以b对象也可以调用run(),fly()方法。
在这里插入图片描述

步骤二
A类

public class A {
    public void run(){
        System.out.println("跑得快");
    }
    public void fly(){
        System.out.println("飞得高");
    }
}

B类2

public class B extends A{
    public void run(){
        System.out.println("B跑得快");
    }
}

测试类2

public class Test {
    public static void main(String[] args) {
        B b=new B();
        b.run();
        b.fly();
    }
}

流程图

二、
当子类重写父类的方法时:
由于继承关系,b可以使用a的代码,
当b有了自己的run()方法后,
父类对象当中的方法被覆盖,
也就是不再能访问到。
在这里插入图片描述

步骤三
A类

public class A {
    public void run(){
        System.out.println("跑得快");
    }
    public void fly(){
        System.out.println("飞得高");
    }
}

B类

public class B extends A{
    public void run(){
        System.out.println("B跑得快");
    }
}

测试类3

public class Test {
    public static void main(String[] args) {
        B b=new B();
        b.run();
        b.fly();
        A a =new A();
        a.run();
    }
}

流程图
三、
此时执行的是A中的run()
new关键字:在堆里面开辟新的内存空间
新的空间里面有A的run(),A的fly()方法。
类是构建对象的方法,类里面有什么,对象里面就有什么。
没有子类,所以没有重写,所以就是自己类里面的方法。
在这里插入图片描述


需要反复强调的知识点(记住)

  • 类:类是创建对象的模板
  • 栈:调用方法时,方法的入栈出栈
  • 堆:new对象和数组时,在堆中开辟空间,分配内存空间
  • 方法区:存储类的信息
  • 构造方法作用:在创建对象时,给对象初始化
  • 构造方法特点:
    1.构造方法名与类名相同
    2.无返回值类型
    3.系统编译器提供一个默认的无参构造器
    4.一旦定义了至少一个构造方法,java编译器不会再提供默认的构造器
    5.在创建对象时,提供new自动调用
    6.可以有参数,参数可以是任何类型
  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值