Java中static修饰符用于属性与方法的简单用法

Java中static修饰符对属性与方法的用法
Java中的static修饰符十分常见,先谈谈关于修饰属性时需要注意的。
先来观察一段关于修饰属性的例子:

class Fruit {
	private String name;    //水果类型
	private double value;   //水果价格
	String area = "产地A";  //水果产地
	public Fruit(String name,double value) {          //定义构造方法
		this.name=name;
		this.value=value;
	}
	public String getData() {
		return"水果名:"+this.name+",价格:"+this.value+"元/斤"+",产地:"+this.area;
	}
}
		
public class StaticDemo {
	public static void main(String[] args) {
		Fruit fruit1 = new Fruit("苹果",5);
		Fruit fruit2 = new Fruit("香蕉",6);
		Fruit fruit3 = new Fruit("梨子",7);
		fruit1.area="产地B";
		System.out.println(fruit1.getData());
		System.out.println(fruit2.getData());
		System.out.println(fruit3.getData());
	}
}

运行结果:
水果名:苹果,价格:5.0元/斤,产地:产地B
水果名:香蕉,价格:6.0元/斤,产地:产地A
水果名:梨子,价格:7.0元/斤,产地:产地A

以上仅仅是个修改其中单一对象的属性值,若把其中area属性定义为static private String area;

static private String area = "产地A";  //水果产地
fruit1.area="产地B";//水果产地

会出现以下结果:
水果名:苹果,价格:5.0元/斤,产地:产地B
水果名:香蕉,价格:6.0元/斤,产地:产地B
水果名:梨子,价格:7.0元/斤,产地:产地B

所以在这里可以发现,用static修饰过的属性,属性会变成“共有”的,不仅fruit1对象可以更改该属性,fruit2同样也可以更改,但是我们不建议在这里使用对象名.属性的方式对有static修饰符修饰过的属性进行修改,原因将在后文叙述。
当一个属性被static修饰符修饰后,这个属性将成为“类属性”,同理,当一个方法被static修饰后,也将称为“类方法”,意味这个属性或者方法将同class文件一同被加载入方法区,下面来张内存图方便理解:

简单的叙述一下整个流程:
首先先是Class文件StaticDemo.class最先进入方法区,然后读入main()方法,由于main()方法是一个静态方法,所以进入静态区。
其次读入Fruit类,Fruit.class文件进入方法区,Fruit类中name属性和value属性进入非静态区,area属性进入静态区,构造方法与getInfo()方法进入栈内存,作为读入与取出数据的方法,而area属性被显式初始化为:产地A,在图中表示为由Null改变为产地A
随着主方法中创建fruit1、fruit2、fruit3三个Fruit类对象,堆内存中出现三块区域,并且每个区域有一个自己的内存地址,并且栈内存中的fruit1、fruit2、fruit3分别指向这三个地址,这三块内存中分别存储着三个对象各自的成员属性,在这里就是name与value,而area属性是静态成员属性,它并不在堆内存中,而是在方法区对应的静态区中,由于尚未初始化值,所以成员属性的初始值就是对应数据类型的默认值,name是String类型数据,对应默认值是Null,value是double类型数据,对应默认值是0.0。
随着构造方法实例化对象后,name、value值会相应改变为对应的实例化数据。在图中可以看出,三个对象的area属性是公共的,它被存放在Fruit.class的静态区中,随着类一同出现,而当Fruit类对象fruit1修改了area属性时,三个对象的area属性同时发生了变化。

所以我们可以得知,static修饰过的属性不进入堆内存,而是跟随class文件一同产生,因此也叫类变量,它并不受到类的实例化对象影响,因此,它的产生顺序是优先于对象的,我们不建议使用对象.属性来修改属性值,若要这样做,建议使用类名.属性名来操作。

下面再说说static修饰方法
先举个例子:

public class StaticDemo {
    public static void main(String[] args) {
        a();
    }
    public void a(){
        System.out.println("Hello World");
    }
}

这样程序是没法通过编译的,提示Error:(3, 9) java: 无法从静态上下文中引用非静态 方法 a()
main()方法是一个static修饰过的方法,而它没法调用非static修饰的方法a()(如果一定要用主方法来调用非static方法,可以使用new StaticDemo().a()) 从对属性的分析也可以拿到这里来,因为static修饰过的方法是同时与类进入方法区的,而此时非static方法还尚未加载进入栈内存,因此这就形成了一个先来后到的次序,main()来的太早,没法调用尚未加载的方法a(),从而报错。那么反过来呢?

public class StaticDemo {
    public static void main(String[] args) {}
    public void a(){
        b();
    }
    public static void b(){
        System.out.println("Hello World");
    }
}

这样程序是不会报错并且顺利执行的,因为后来的肯定能调用先前已经在方法区的方法,因此可以得知,非static方法可以调用static方法,也可以调用非static方法,而static方法只能调用static方法不能调用非static方法

那么问题来了,我们什么时候使用static来定义方法??
当一个类没有属性成员,而只有方法时,使用static来定义方法,好比Java.lang.math类,这是个工具类,只需要用户拿来使用它其中的各种数学方法,而不需要去实例化成员,这时候就需要将类中的方法用static修饰,省去了构造方法实例化对象的繁琐步骤。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值