(基础)java中的静态变量与静态函数Static

静态static

静态出现最大的原因:节约内存,只存一份,由对象共享这个属性。

 

 

静态的作用是什么?

场景:

当每个对象都有一个相同的属性,如country="China",那么每个对象所在的堆内存中都会为其分配空间来保存这个属性值country="Chian"。

既然每个对象的country属性值都是一样的,能否只用一个存储空间就行了呢?这样节约堆内存空间。

答案是可以的。

通过static修饰的属性,其值将被所有对象共享使用。

注意:对象特有的属性不能定义为静态的,因为静态即共享。如Person类的name不能是静态的。

如,饮水机是共享的,大家都共同使用同一个饮水机,则静态;

如,杯子是特有的,每个人都有属于自己的水杯,则非静态。 

 

静态的特征: 

静态static修饰的成员,优先于对象存在;

静态static修饰的成员,随着类的加载而进入内存;

静态static修饰的成员,是共享的,而对象中存储的则是特有的;

静态static修饰的成员,不仅可以被对象所使用,还能被类直接使用;

 

静态的优点:

实现共享数据在内存中的唯一存储,节约了内存空间;

每个对象都不用在堆内存中为其单独开辟空间保存,直接使用共享的数据即可。

 

静态的缺点:

 常驻内存,内存释放周期长,只随着类的消失而消失。

 类什么时候消失?

 类其实也是对象,JVM启动时就会加载类路径目录下的类,当内存中加载的类太多太多,JVM的GC会根据某种算法对加载的某些类进行清理,释放空间。

 当JVM关闭时,类消失。

 

类变量与成员变量的区别

类变量不是类的成员变量

 

存储位置不一样

成员变量,在堆内存中,每个对象都有自己的一份不同的成员变量存储区

静态变量,在方法区中,只有唯一的一份,是类变量,每个对象都共享使用这个变量

 

生命周期不一样

成员变量,随着对象的创建而存在,随着对象的回收而释放

静态变量,随着类的加载而存在,随着类的消失而释放

 

调用方式不同

成员变量,只能由对象调用

静态变量,一般直接使用类名进行调用

 

成员变量--->实例变量,对象的特有属性

静态变量--->类变量,该类中的对象都具有相同的一个属性

 

静态修饰属性

静态变量也称为类变量;

静态变量存储在方法区的静态区内存中;

 当每个对象的某个属性的值都相同,则可以考虑使用静态来修饰该属性。

public static String county = "CN";

 

 

方法区

存放方法/函数的地方。

方法区又分为了几个部分:静态数据区,常量区,代码区(存放方法代码的区域)等。

需要说明一点:

类中的代码到底是如何存放的。

类中可以定义的内容:成员变量,类变量,构造方法,一般方法,静态方法。

其中,

成员变量是对象特有的数据,存在于对内存中

构造方法、一般方法,将存放到方法区的非静态区中

类变量、静态方法,将存放到方法区的静态区中

 

=========================================================================

 

 

静态修饰方法

 

静态修饰的方法具有局限性,只能使用静态变量或调用静态方法。

工具方法,工具类,不需要创建对象

方法中只要没有操作对象特有的数据,就可以定义为静态方法;

1.创建对象来调用静态方法,浪费时间、空间,无意义

---私有构造方法,可以防止外部通过对象来调用静态工具方法(单例模式);

2.静态方法中不能处理对象的特有数据,因为静态方法中无法引用对象(静态先于对象存在);

 

由于静态方法先于对象加载到内存,导致:

 静态方法中只能使用静态成员(静态属性,静态方法);

 静态方法中不能使用this/super关键字;

 

 

 

 

=============================================================================

 

 

静态什么时候用?

1.静态变量/类变量(从节约堆内存上考虑)

 

对象中的成员变量的值都是相同的,而且都只需要使用该值,而不做修改,则定义为静态的!

如果其中哪怕只有一个对象将有可能修改这个值,都必须将其定义为成员变量,放到堆内存中存储,此时决定不能将其定义为静态的。

好处:

每个对象都不必在堆内存中为同一份数据分配空间,只需要在方法区存放一份数据即可!

前提:对象只读该数据,不修改该数据,因为大家共享这个数据。

 

 

2.静态方法(从执行代码上考虑,从方法的调用上考虑)

 

方法能否被定义为静态,就看一点:

方法中是否使用到了对象的特有数据或者调用到了普通方法如果没有,则定义为静态方法!

好处:

1.不需要创建对象,因为创建对象耗费时间空间,而且静态方法的执行中没有使用到对象的数据。

(创建对象需要在堆内存开辟空间,调用构造方法进行初始化等操作)

2.调用简单,直接通过类名即可调用方法。

 

注意:不管是静态方法还是非静态方法,都只是一段代码,在方法区中都只存一份,只是存放的区域不同而已!不存在节约内存的说法。

 

 

=========================================================================

 

扩展:主函数main为什么设计成static的

首先,主函数的功能:程序的入口,由JVM调用

主函数专注于:
* 在函数体中创建其它类的对象,指挥这些对象调用它们各自的方法来完成某种功能!
* 代码按功能封装到函数中
* 函数都封装到类中
* 主函数只做一件事:创建那些封装好的类的对象,再调用类的方法!

public class StaticTest {
	
	/**
	 * 对象的特有属性,每个对象的id都不同
	 */
	int id;
	
	/**
	 * 讨论主函数为什么是静态static的
	 * 1.主函数是程序的入口。
	 * 2.主函数中调用其它函数的2种方式:
	 * 		a.静态方法,由类名调用;
	 * 		b.非静态方法,由对象调用
	 * a.静态方法,被主函数调用,由于静态方法中只能使用类变量,使得静态方法的功能具有局限性(对象的特有属性无法在静态方法中使用,因为对象还未创建),不能满足大多数的功能需求;
	 * 这样就只留另一条路,调用非静态方法
	 * b.非静态方法的调用,必须由对象来操作,所以,主函数中必须先创建对象,再通过对象来调用,使得大多数功能的调用都以对象为起点进行
	 * Java面向对象,以对象为核心,将主函数设计为静态的,强制开发人员通过对象来调用方法!
	 * 
	 * 哦也!
	 * @param args
	 */
	public static void main(String[] args) {
		//say(); //静态方法中不能调用非静态方法
		
		//只能通过对象来调用
		StaticTest test = new StaticTest();
		test.say();
		
		//把say()也变为静态的,也能直接调用啊!其后果是,say()要能执行,那么id也必须静态,静态即共享--->id是对象的特有属性,不同对象有不同的id
		//所以,主函数中调用方法,遵从Java的规范,用对象来调用方法!!!
	}
	
	public void say() {
		System.out.println(this.id);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值