【Java】static修饰符的特点与使用

前言

对象都有name和age两个状态;
也就是说不同对象的name和age是不同的;但是在生活中有些东西不是属于某一个具体对象的,而是属于整个事务的类型。
比如:全世界人的总数,人的毁灭行为。
————————————————————————
状态和行为应该又对象和类型之分。
有的状态和行为应该属于对象,状态和行为可以不一样;
有的状态和行为应该属于类型,不属于对象。
问题:如何表示人类毁灭这个行为(destory)
那么就要用到static修饰符
————————————————————————

static修饰符特点

static修饰符表示静态的,可修饰字段,方法,内部类,其修饰的成员属于类,也就说static修饰的资源属于类,而不是对象。

所以static的真正作用:用来区分字段,方法,内部类,初始化代码块是属于对象还是属于类本身。

(1)static修饰的成员(字段/方法),随着所在类的加载而加载
当JVM把字节码文件加载进JVM的时候,static修饰的成员就已经在内存中存在了。

(2)优先于对象的存在
对象是我们手动通过new关键字创建出来的

(3)static修饰的成员被该类型的所有对象所共享
根据该类创建出来的任何对象,都可以访问static成员(猫天生爱吃鱼)

(4)直接使用类名访问static成员
因为static修饰的成员直接属于类,而不属于对象,所以可以直接使用类名访问static成员。

代码如下:

class Person
{
	String name;
	int age;
	static int totalNum = 5;	
	// 自定义构造器
	Person(String name, int age){
		this.name = name;
		this.age = age;
		totalNum++;		
	}
}
class StaticDemo 
{
	public static void main(String[] args) 
	{		
		// 打印totalNum初始值,优先于对象的存在
		System.out.println(Person.totalNum);
		// 创建一个新的对象
		Person p1 = new Person("Li",16); 
		// 打印当前totalNum值
		System.out.println(Person.totalNum);
	}
}
---------- 运行java ----------
5
6

输出完成 (耗时 0) - 正常终止
class Person
{
	String name;
	int age;
	static int totalNum = 5;
	Person(String name, int age){
		this.name = name;
		this.age = age;
		totalNum++;		
	}
}
class StaticDemo 
{
	public static void main(String[] args) 
	{	
		Person p1 = new Person("Li",16); // 6
		Person p2 = new Person("wang",18); // 7
		System.out.println(Person.totalNum);
		System.out.println(p1.totalNum); // p1.totalNum低层其实就是Person.totalNum
		System.out.println(p2.totalNum); //同样,p2.totalNum低层其实就是Person.totalNum
	}
}
---------- 运行java ----------
7
7
7

输出完成 (耗时 0) - 正常终止

最后两行代码虽然用对象名调用了static修饰的totalNum变量,但是低层依然使用的类名来调用的。假如我们在只能的IDE开发工具中写这样的代码,工具一般会给我们警告的!

但是不能用类名直接调用非static方法!因为,static定义的方法和成员变量属于类,不属于对象,非static定义的方法和变量才属于对象! 如下代码:

class Person
{
	String name;
	int age;
	static int totalNum = 5;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
		totalNum++;		
	}
	void die(){
		totalNum--;
	}
}

class StaticDemo 
{
	public static void main(String[] args) 
	{
		Person.die();// 编译会报错,不能直接用类名调用非static方法!
	}
}

---------- 编译java ----------
StaticDemo.java:30: 错误: 无法从静态上下文中引用非静态 方法 die()
		Person.die();
		      ^
1 个错误

输出完成 (耗时 0) - 正常终止

static成员在JVM中的存储:

totalNum 该成员属于类,而非对象,随着字节码文件的加载就加载到了方法中,而不存在堆中
在这里插入图片描述

类成员和实例成员的访问

类中的成员:字段,方法,内部类;
类成员:使用static修饰的成员;
实例成员:没有使用static修饰符的成员;

1.类成员只能访问类成员,实例成员只能访问实例成员。代码证明如下:

class Person
{
	String name;
	int age;
	
	Person(String name, int age){
		this.name = name;
		this.age = age;
	}
}
class StaticDemo 
{
	public static void main(String[] args) 
	{
		String name = Person.name; //编译报错,不能使用类名访问非static成员,将Person类中的name字段使用static修饰才可以!
	}
}
StaticDemo.java:9: 错误: 找不到符号
		totalNum++;		
		^
  符号:   变量 totalNum
  位置: 类 Person
StaticDemo.java:18: 错误: 无法从静态上下文中引用非静态 变量 name
		String name = Person.name; //编译报错,不能使用类名访问非static成员
		                    ^
2 个错误

输出完成 (耗时 0) - 正常终止

2.类成员直接属于类,可以通过类来访问static字段和static方法;

3.实例成员只属于对象,通过对象来访问非static和非static方法;
(对象其实是可以访问类成员(static修饰的成员),但是低层依然使用类名访问的)

4.在static方法中,只能调用static成员。证明代码如下:

class StaticDemo 
{
	String info = "Hello";
	public static void main(String[] args) 
	{
		System.out.println(info); // 编译报错,static方法不能调用非static成员
	}
}
---------- 编译java ----------
StaticDemo.java:18: 错误: 无法从静态上下文中引用非静态 变量 info
		System.out.println(info);
		                   ^
1 个错误

输出完成 (耗时 0) - 正常终止

5.非static方法,可以访问静态成员(static),也可以访问实例成员(非static);

class Person
{
	String name;
	static int age; // 使用static修饰age

	Person(String name, int age){
		this.name = name;
		this.age = age;
	}

	public void print1(){
		// 非static 修饰的方法可以访问非static字段和static字段
		System.out.println(name);
		System.out.println(age);
	}
	// 定义一个static修饰的方法
	public static void print2(){
		System.out.println(age); //static 修饰的方法只能访问static字段
	}

}

class StaticDemo 
{
	public static void main(String[] args) 
	{
		Person p = new Person("LiMing",18);
		p.print1();
		p.print2();
	}
}

---------- 运行java ----------
LiMing
18
18

输出完成 (耗时 0) - 正常终止

什么时候定义成static的字段和方法?

如果这个状态和行为属于整个事务(类),就直接使用static修饰,它被所有对象所共享。

在开发中,往往把工具方法使用static修饰,如果不使用static修饰,则这些方法属于该类的实例对象,我们得先创建对象再调用方法,在开发工具中,对象只需要一份即可,可能创建N个对象,此时我们往往把该类设计为单例的,但是还是有些麻烦。

因此,在开发中设置工具方法时,为了简单,我们使用static修饰。

类成员的使用:

好处: 对象的共享数据进行单独空间的存储,可以节省空间,直接被类名调用,没有必要每个对象中都存储一份;
弊端: 生命周期过长。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值