static关键字--main函数、何时使用static

一、主函数
【】主函数是一个固定写法的函数,也是一个一般函数。

【】主函数特殊之处:

1格式是固定的

2被jvm所识别和调用

【】主函数意思:

public:虚拟机需要的权限是最大的,所以函数必须public

static:共享,虚拟机调用主函数的时候不需要创建对象,直接用主函数所属类名就能调用。在dos命令行,运行所写的完整格式java 类名.main

图片

void:主函数没有具体返回值。返回给调用者jvm,虚拟机不需要返回值,主函数只需要把入口做完就好。

main:函数名,不是关键字,只是jvm识别的固定的名字

String[] args:这是主函数的参数列表,是一个数组类型的参数,且元素都是字符串类型

args:主函数名是主函数中唯一可以修改的部件,1.2版本时写作arguments参数,后期简写成了args

图片

 

【】第一个是主函数的格式;第二个是主函数的一种同载函数,只是一种普通函数,不是主函数的固定格式。

 【】参数String[] args

任何函数被调用都需要传入其参数列表对应的参数。

打印这个参数名,得到[Ljava.lang.String;@4eec7777。------------ 数组,包名Ljava.lang.,字符串类型,@右边哈希地址值

图片

 

【】说明虚拟机调用主函数的时候,确实给main方法传递了一个字符串类型的数组实体。

虽然虚拟机产生了一个数组,但是虚拟机没有向里面传元素,所以数组长度为0,是一个空数组,new String[0]。

【】主函数之所以带着这个参数,是因为我们可以在运行程序的同时,指定一些具体的参数值。在程序入口,java留给了一部分自主权,程序员可以把程序运行需要的数据通过这个入口传进去。可以把自定义的东西传进去。

【】为什莫是字符串类型数组?因为字符串类型最通用,它可以转换为其它任意类型的数据。

【】因为允许传入多个数据,所以是数组类型

【】 什么时候传值?虚拟机调用主函数的时候传值。所以在命令行运行时输入   java 类名 值1 值2 值3 

虚拟机看到类名后面有内容的话,就会把这些内容以空格的方式进行分隔,作为数组的元素进行封装,然后把数组传给args,这是数组长度就不是0

图片

 但是实务中不会这么干,而是做一个图形化界面,设置一个文本框让用户往文本框输入信息

 

 总结:

1主函数格式固定,被jvm识别和调用,

2public确保虚拟机需要权限最大化,static共享jvm通过类名调用,void虚拟机不需要返回值,main名称,

3String[] args虚拟机调用主函数会传给一个空元素的字符串类型数组args,程序员可以在运行时写上一些自己需要的数据,

写法:java 类名 值1 值2 值3 

 
 
 二、内存图解

【】java程序执行后,类被加载进内存存到方法区,静态方法如main函数代码存入方法区静态区的该类中,非静态方法存入方法区非静态区的该类中。

【】

图片

【】命令行输入Java StaticDemo2,执行这个主函数所在的类就被加载进入内存。

图片

 这个类加载进来就进行空间的开辟,划分一片空间出来,分成栈、堆、方法区(方法存在方法区)。

这个类叫做StaticDemo2,这个类java一执行就加载进方法区,

就在方法区的非静态区开辟空间,类里面有构造函数StaticDemo2(){},这个默认的构造函数也被加载进来;

StaticDemo2里面有静态的方法static main()方法存储在方法区的静态区,main方法里面代码都在这;

非静态区和静态区的方法,都是被共享的。所有对象都能调用。

只是两者所属不同。非静态区域所有成员都有个this所属,因为非静态区域内容只能被对象调用。静态区成员所属类名。

 

图片

 

 

 image

【】java 类名后,主函数进栈。

【】运行第一句Person.method();

使用到一个类Person,这个类才加载进内存(用到哪个类才把哪个类加载进内存),这时候虚拟机首先找classpath是否有这个类文件,如果没有设置,就在到当前目录找这个类文件。找到,就把这个类文件加载进内存空间的方法区,在方法区分配空间。

Person类进入方法区的非静态区,在StaticDemo类的下面,person里面构造函数和其他非静态方法都也加载进来,

静态区的person类里面加载进静态方法和静态属性。

【】Person.method();,还没建立任何对象就直接用类名调用,属于共享的,需要去共享区的

静态区找method这个方法,这个方法不持有this只有非静态区的方法才持有this

【】然后method()方法进栈,然后运行方法代码

方法区存储方法代码,栈是运行区,栈里面存放局部变量,并不加载引入方法的具体代码

【】共享方法method开始执行代码sop(Person.country)

代码里面是共享变量,可以类名调用在方法区的静态区,就算没有这个class文件里面也有这个变量

【】method()后就是省略的return,执行完毕,method()方法弹栈了

 

image

【】主函数执行第二句Person p= new Person("java",20)

在栈内存main方法内多了一个p变量,堆内存建立Person对象,有了一个内存首地址,

对象内的属性进入空间开始默认初始化,name=null,age=0,对象内没有country,它在方法区的静态区。

默认初始化后,会进行构造函数初始化。构造函数进栈,person-this=0056,构造函数参数name接收java,age接收20.

【】Person构造函数进栈后开始执行方法区的代码,name的值赋给this.name,age的值赋给this.age;所以Person对象内部成员变量name=java,age=20.之后,构造函数Person()弹栈

【】右边堆内存对象初始化完毕后,把对象的内存首地址赋值给左边的栈内存p变量

image

【】主函数执行p.show(),show()进栈,持有this=0056,发现show没有局部变量,只有执行语句,所以执行方法区非静态区的show方法,sop(country+name+age),country从方法去静态区里找,name完整是this.name,age也是。从对象里找name和age

【】输出后,show弹栈

【】主函数代码运行完毕后return语句结束,主函数弹栈,程序结束。

【】没有代码后,jvm结束运行

image

 

总结:

1类执行时被加载进内存的方法区,其中static修饰的成员存到静态区的该类中被类名所属,未被static修饰的方法存到非静态区的该类中并持有this被其所属。其余类执行到时才被加载进内存方法区。

2栈是运行区,有函数有this和临时变量。但是函数里面执行语句不会加载进栈中,而存储在方法区。

3堆内存存储实体,首先会默认初始化,对象还会再进行构造函数初始化。

4执行语句中的成分,可以从栈中、堆中、方法区静态区中找。

 
 
三、开发阶段什么时候写共享static---站在节约堆内存立场考虑,能共享就尽量共享

共享用来修饰类里面的成员,共性修饰后放在方法区被共有,不被共享修饰放在对象里面特有

不共享是普遍的,共享都是有条件的特殊的。共享用以节约内存空间,能共享就共享。

【】属性:各个对象某属性都一样,就可以共享

【】函数:看函数里面是否都是共享成分。里面没有对象特有的成员,就可以共享。换句话说,里面成员都是共享成员,这个函数才能被共享修饰。内部都static外部才能static

【】属性被stattic:所有对象的这个属性都一样,也不会有变化,就可以用static修饰来共享化,避免占用过多堆内存

image

【】函数被static:方法加入共享后,意味着没有对象方法也能执行;

函数是否可以加static:就看函数里面属性是否有static修饰,都有,外面函数能加static,有一个没有,函数外面就不能加static

对象是用来封装特有数据的,没有使用这些数据,就不要创建对象,节约堆内存

image

 

【】什么时候用共享:属性,各个对象这个属性都一样,才能共享;函数,函数内部成员都能共享,这个函数才能采用共享(教室里面每个人都安静,教室才安静)。

能共享尽量共享,节约堆内存空间

 
 
 
 
 
 
 
 
 
 
posted @ 2025-07-28 20:10  ibddindonon  阅读(8)  评论(0)    收藏  举报