java的static关键字使用


导读:文章内容选自尚硅谷,JDK8,采用eclipse环境。

static关键字修饰属性

  • static关键字可以修饰属性、方法、代码块和内部类,修饰属性时,该属性一般为此类创建的多个对象所共有的一个属性。
  • static修饰的属性叫做静态属性,也叫做类属性,属性会随着类被加载到方法区的时候一同被加载到方法区。其创建时间要早于此类对象所创建的时间。
  • 由于static属性是至于方法区中,且为多个对象所共有,当静态属性被修改后,所有此类对象的该属性也被修改了。
  • 静态属性与非静态属性(实例变量)不同,实例变量就是类中的普通属性,一个类中创建的多个对象的同一种实例变量,彼此之间是相互独立的,可以为不同的值,而静态属性由于共享同一个内存空间,属性内容是一样的。

代码演示如下

package com.atguigu.java1;

public class StatiaTest {
   public static void main(String[] args) {
   	Chinese c1 = new Chinese();
   	c1.name = "姚明";
   	c1.age = 40;
   	Chinese c2 = new Chinese();
   	c2.name = "malong";
   	c2.age = 30;
   	c1.nation = "CHN";
   	System.out.println(c2.nation);
   }
}

class Chinese{
   String name ;
   int age;
   static String nation;
}

运行结果为 CHN

这儿是通过对象来修改静态属性,我们没有对c2的nation属性赋值过,但是却能打印出c2的nation属性,而且和c1的nation属性一样,可见,nation作为静态属性,被该类多个对象所共享。

当通过其中一个对象修改静态属性后,其他对象的这个静态属性的内容也会发生改变。

package com.atguigu.java1;

public class StatiaTest {
	public static void main(String[] args) {
		Chinese c1 = new Chinese();
		c1.name = "姚明";
		c1.age = 40;
		c1.nation = "CHN";
		
		Chinese c2 = new Chinese();
		c2.name = "malong";
		c2.age = 30;
		c2.nation = "China";
		System.out.println(c1.nation);
	}
}

class Chinese{
	String name ;
	int age;
	static String nation;
}

输出结果为 China ,这是因为c2.nation对之前c1.nation赋值的内容做出了修改。输出c1.nation,由于共享同一块内存空间,输出结果肯定为修改后的值。
ps:介绍一下java中变量的分类
在这里插入图片描述
图片内容选自尚硅谷PPT

通过类名来调用静态变量

java的静态属性也叫做类变量,是因为java的静态属性是可以通过类名来直接调用的。
在之前的代码中

		Chinese.nation = "中国";

通过类名的方法调用类变量是完全合法的。

在java中,通过类名来调用静态变量其实非常常见,比如System.out,比如Math.PI,其实都是通过类名来调用静态属性,System和Math首字母都是大写,他们其实都是类名。
比如System.out,其实定义为

    public final static PrintStream out = null;

比如Math.PI,定义为

    public static final double PI = 3.14159265358979323846;
  • 类的对象可以创建多个,但是得先加载类到方法区,然后再创建类的对象。
  • 类一般只加载一次,静态变量随着类的加载而加载,静态变量在内存中也只存在一份,存在于方法区中的静态域中。
  • 类变量既可以通过对象调用,也可以通过类名调用,而实例变量只能通过对象调用。

静态变量的内存解析

在这里插入图片描述
图片选自尚硅谷PPT

图片右侧是执行的代码,这儿代码画在了堆空间内部,但其实代码存放位置不在堆空间中。
代码的执行过程为

  • 1.第一行代码 Chinese.nation=”中国“; 首先在方法区中直接加载了类信息,同时在方法区中的静态域中创建了一个静态属性,属性值默认为null,然后再赋值”中国“。
  • 2.先后创建了两个对象,并赋初值。这两个对象中的name属性为实例变量,存在于堆空间中,但是name变量中存放的内容并不是字符串的值,而是字符串的地址,因为name属性是String类型的,String类型的内容存放在字符串常量池中,存在于方法区内部,name变量中存放指向常量池的地址。(有分析说java1.8中字符串常量池在堆空间内部)
  • 3.先后通过变量名,对静态变量的值进行修改。

static关键字修饰方法

与静态属性类似,static关键字修饰的方法也叫做静态方法和类方法,其使用和静态属性类似。

  • 静态方法既可以通过对象调用,也可以通过类名调用。
  • 静态方法内只能调用静态属性和静态方法,不能够调用非静态属性和非静态方法。而非静态方法可以调用静态属性和方法。
  • 静态方法中不能使用this和super关键字,因为this和super关键字的使用,前提是必须要有对象,而静态方法的加载要早于对象的创建。

静态方法内不能调用非静态属性或方法,当调用非静态属性时,默认非静态属性前加上了this关键字,造成了生命周期冲突的问题。

演示代码如下

package com.atguigu.java1;

public class StatiaTest {
	public static void main(String[] args) {
		Chinese c1 = new Chinese();
		c1.name = "姚明";
		c1.age = 40;
		c1.nation = "CHN";

		Chinese c2 = new Chinese();
		c2.name = "malong";
		c2.age = 30;
		c2.nation = "China";
		Chinese.nation = "中国";
		
		Chinese.show();
		System.out.println("****** ****");
		c1.eat();
	}
}

class Chinese {
	String name;
	int age;
	static String nation;
	
	public void eat(){
		System.out.println("人吃饭");
		info();
		walk();
		System.out.println(nation);
	}
	
	public static void show(){
		System.out.println("我是中国人");
//		eat(); //编译器报错,静态方法内不能调用非静态属性和方法
//		name = "tom";
		System.out.println(nation);
		walk();
	}
	
	public void info(){
		System.out.println("name = "+name+",age = "+age);
	}
	
	public static void walk(){
		System.out.println("walk");
	}
}

ps:nation和walk都是静态的,他们在被静态方法和非静态方法调用的时候,默认省略掉了前缀Chinese.。
他们实际上是Chinese.nation和Chinese.walk。在静态方法内部,他们若把Chinese改为this会报错,这是因为前面讲的生命周期的问题,在非静态方法内,他们若把Chinese改为this不会报错,可以正常使用,这是因为此时是通过对象调用静态方法和属性。

  • 开发中,操纵静态属性的方法,一般为静态方法,这是因为生命周期是一致的,若采用非静态方法,还得先造一个对象,才能调用非静态方法。
  • 工具类中的方法,习惯上声明为静态方法。比如Math,Arrays、Collections,直接拿类去调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值