Java之static关键字

1 静态成员

配套学习资料【含授课视频、源码】:https://link3.cc/ashao

static修饰类中的数据成员,该成员就成了静态数据成员,也称为类成员;

类成员,是属于类的,为这个类所有对象共享,只占用一块内存空间。

生活中案例:

  • 普通成员变量

    就像教室中,同学们的水杯,每个同学都有一个自己的水杯,和其他人相互不影响

  • 静态数据成员

    就像教室中,角落里的饮水机,它是这个教室中所有同学共享的,张三接一杯水,李四就会看到饮水机中的水少了一些,同样的李四接一杯水,张三也会看到饮水机中的水少了一些

static成员特点:

  • 被类的所有对象共享

  • 随着类的加载而加载,先于对象存在

    对象需要类被加载后,才能被创建出来

  • 可以通过类名调用,也可以通过对象名调用,推荐使用类名调用

    格式:类名.静态数据成员;

  • 方法区中有一块专门的区域:静态区,专门用来存储类的static成员

静态成员访问方式,案例描述:

class Demo {
    public static int num;
}

public static void main(String[] args) {
    //可以使用类名来访问,推荐用法
    Demo.num = 10; 
    
    Demo demo = new Demo();
    //也可以对象来访问,但不推荐
    demo.num = 20; 
}

静态数据成员是属于类的,并且为这个类所有对象共享,案例描述:

class Demo {
    public static int num;
}

public static void main(String[] args) {
	//1.静态数据成员会随着类的加载而加载(开辟内存并进行默认初始化)
    //先于对象存在
    Demo.num = 10; 
    
    //2.实例化两个对象,然后通过对象访问静态成员,输出其值
    Demo demo1 = new Demo();
    Demo demo2 = new Demo();
    
    System.out.println(demo1.num);//输出结果为 10
    System.out.println(demo2.num);//输出结果为 10
    
    //3.通过类名修改静态成员值,再借助对象.static成员,输出其值
    Demo.num = 20; 
    System.out.println(demo1.num);//输出结果为 20
    System.out.println(demo2.num);//输出结果为 20
    
    //4.通过对象名修改静态成员值,再借助类名.static成员,输出其值
    demo1.num = 30;
    System.out.println(Demo.num);//输出结果为 30
    System.out.println(demo2.num);//输出结果为 30
}

可以看出,无论是使用类访问静态属性,还是使用这个类的某个对象访问静态属性,效果是一样的,这个属性对这个类的所有对象都是可见的、共享的。

静态属性存储位置:

在方法区中有一块静态区,专门用来存储各个类静态数据成员。当操作静态数据成员时,不论是通过类名,还是通过对象名操作,都是操作静态区中对应的内存区域。
在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

静态数据成员初始化:

  • 静态数据成员随着类加载而加载(开辟相应内存),并会进行默认的初始化

    其默认初始化值为null(引用类型)、0(整形)、0.0(浮点型)、false(布尔类型)

案例描述:

class Demo {
    public static int num;
    public static String str;
    public static double dNum;
    public static boolean flag;
}

public class Test0102_StaticValue {
	public static void main(String[] args) {
		System.out.println(Demo.num);	//0
		System.out.println(Demo.str);	//null
		System.out.println(Demo.dNum);	//0.0
		System.out.println(Demo.flag);	//false
	}
}
  • 对静态数据成员的初始化,一般采用两种方式

    显式初始化、静态代码块初始化(后面章节介绍)

  • 显式初始化格式:[修饰符] static 数据类型 静态成员名 = 初始值;

    例:public static String library = "栋梁图书馆";

注意:尽量不要在构造方法中对static成员进行初始化,因为只要创建对象,构造方法就会自动被执行,导致static成员值不经意间被修改!

案例描述:

​ 请根据讲解内容,修改上一章节中School类代码,并完成测试。

//学校类
class School {
	private String name; 		//名称
	private int num;			//师生数量
	
	//该类所有对象共享的图书馆,显示初始化
	public static String library = "栋梁图书馆";	
	
	//定义构造器
	public School() {}	
	
	public School(String name, int num) {
		this.name = name;
		this.num = num;
	}
	
	//该构造器不合适,尽量不要在构造方法中 对static成员进行初始化
//	public School(String name, int num, String library) {
//		this.name = name;
//		this.num = num;
//		this.library = library;
//	}
	
	public void show() {
		System.out.println("学校名称: " + this.name);
		System.out.println("师生数量: " + num);
		System.out.println("图书馆: " + School.library);
	}
}

public class Test0102_School {
	public static void main(String[] args) {
		//1.在创建School对象前,输出 static成员值
		//此时程序正常输出,说明static成员的创建与初始化先于对象
		//结论:static成员依赖类,而与该类对象无关
		System.out.println(School.library);
		
		//2.创建类对象
		School s1 = new School("第一中学",3000);
		System.out.println(s1.library);
		s1.show();
		System.out.println("-------------");
		
		School s2 = new School("秀峰中学",2500);
		s2.show();
		System.out.println("-------------");

		School s3 = new School("娄江中学",1800);
		s3.show();
	}
}

运行效果:
在这里插入图片描述
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2 静态方法

在类中,使用static修饰的方法,就是静态方法;

static方法的作用,主要是用来操作static成员;

static方法可以使用类名来调用,也可以使用对象来调用,但推荐使用类名。

案例描述:

public class Demo{
    //定义静态方法
    public static void test() {
        System.out.println("我是static静态方法...");
    }
}

//测试方法
public static void main(String[] args){
    //借助类名调用static方法,推荐方式
	Demo.test();	
    
    Demo demo = new Demo();
    //借助对象调用static方法,可以调用,但不推荐
    demo.test();	
}

static方法和普通成员方法区别:

  • 静态方法只能访问静态的成员

  • 非静态方法可以访问静态的成员,也可以访问非静态的成员

  • 静态方法中没有this关键字 (本质区别)

案例描述:

//学校类
class School {
	private String name; 		//名称
	private int num;			//师生数量
	
	//用private修饰static成员,则该类外无法直接访问该static成员
	private static String library = "栋梁图书馆";	
	
    //定义public修饰的static方法,专门来操作static成员
    public static String getLibrary() {
        //注意1:static方法中没有this
        //return this.library;	//error
        
        //注意2:static方法中不可以访问普通数据成员
        //name = "一高";		  //error
        
        return library;
    }
}

//测试方法
public static void main(String[] args) {
    //1.在创建School对象前,输出 static成员值
    //编译报错,library为private,只能School类内访问
    //System.out.println(School.library);


    //2.借助类名调用static方法,推荐用法
    String lib = School.getLibrary();
    System.out.println(lib);

    //3.借助方法名调用static方法,不推荐
    School s1 = new School("第一中学",3000);
    System.out.println(s1.getLibrary());
}

思考:为什么静态方法中不能访问普通数据成员?

​ 静态方法也称为类方法,该类方法的调用不依赖对象,可以直接通过类名调用。

​ 假设静态成员方法中能够访问普通数据成员,静态方法中有this引用,我们来看下面场景:我们通过类名调用static方法,此时根本不会传递对象的地址值给this引用,static方法内部也无法找到普通数据成员对应的内存空间进行取值,这与我们要实现的功能是矛盾的。

​ 故而,大家记住结论:静态只能访问静态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值