static关键字

本文深入解析Java中的static关键字,探讨其在属性和方法上的应用,包括如何创建共享属性,实现对象计数,以及static方法的独立性和调用限制。同时,文章提供了多个代码示例,帮助读者理解static在实际编程中的作用。

在所有定义的方法和属性上实际上都可以使用static关键字。

static属性

范例: 定义一个人的类,并设置他的国家

class Person {
	private String name;
	private int age;
	String country = "中国";  //为了后面操作方便,暂时不封装
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getInfo() {
		return "姓名:" + this.name + ", 年龄:" + this.age + ",国家:" + this.country;
	}
}
public class TestDemo {
	public static void main(String[] args) {
		Person p1 = new Person("张飒", 10);
		Person p2 = new Person("李斯", 14);
		Person p3 = new Person("王武", 16);
		System.out.println(p1.getInfo());
		System.out.println(p2.getInfo());
		System.out.println(p3.getInfo());
	}
}

以上的定义模式是以前使用过的,而这个时候三个对象进行的内存分配如下:
在这里插入图片描述

既然现在描述的都是中国人,那么理论上这些country属性都是相同的,所以此时发现每一个对象的country属性被重复保存。如果假设国家的名称都改变了,按照以上的存储模式就会出现一个问题。假设当前Person类产生了10亿个对象,更改他们的国家的话需要一个一个对象地更改。

那么现在就可以发现传统属性所具备的特征就是保存在堆内存之中,并且每一个对象独享此属性。可是同样的概念不适合当前的环境,所以最好的做法是将country属性变为共享属性,只要一次修改就可以影响到所有的对象。那么要如果描述这样的共享属性,则只需要在属性前追加一个static关键字即可。

范例: 定义static属性

class Person {
	private String name;
	private int age;
	static String country = "中国";  //为了后面操作方便,暂时不封装
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getInfo() {
		return "姓名:" + this.name + ", 年龄:" + this.age + ",国家:" + this.country;
	}
}
public class TestDemo {
	public static void main(String[] args) {
		Person p1 = new Person("张飒", 10);
		Person p2 = new Person("李斯", 14);
		Person p3 = new Person("王武", 16);
		p1.country = "China";
		System.out.println(p1.getInfo());
		System.out.println(p2.getInfo());
		System.out.println(p3.getInfo());
	}
}

当程序中使用了static关键字进行定义之后,那么此属性将不会保存在堆内存里面,会保存在一个全部数据区的内存空间之中,并且所有的对象都可以进行该数据区的访问。在这里插入图片描述

既然现在使用的是共享属性了,这个时候代码就会出现一个问题,共享属性可以通过一个对象修改吗?对于static也会将其称为类属性,而所有的类属性都可以利用类名称直接调用。Person.country = "China";

所有的非static属性必须在产生实例化对象之后才可以使用,而所有static的属性不收实例化对象的限制,也就是是否有对象与static属性操作无关。

选择: 关于static属相与非static属性定义的选择?

  • 在定义类99%的情况下不会考虑static属性的
  • 如果需要描述共享属性的概念,或者不希望受到实例化对象控制的时候使用static属性

static方法

static定义的属性可以类名称直接访问,那么同样用static定义的方法也可以直接被类名称进行访问。同样不收到实例化对象的控制。

范例: static定义的方法

class Person {
	private String name;
	private int age;
	static String country = "中国";  //为了后面操作方便,暂时不封装
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public static void setCountry(String c) {
		country = c;
	}
	public String getInfo() {
		return "姓名:" + this.name + ", 年龄:" + this.age + ",国家:" + this.country;
	}
}
public class TestDemo {
	public static void main(String[] args) {
		Person.setCountry("民国"); // 没有实例化对象
		Person p1 = new Person("张飒", 10);
		System.out.println(p1.getInfo());
	}
}

虽然类中已经存在有static方法和非static方法了,那么对于两者的互相调用存在限制

  • 所有的static方法不允许调用非static定义的属性或方法。
  • 所有的非static方法允许访问static属性或方法

因为所有的static方法可以在没有实例化对象的时候访问,而所有的非static方法在有实例化对象产生之后才可以操作。

使用static的属性是共享目的(因为属性需要封装),但是使用statci的方法的目的只有一个:某些方法需希望不受到类的限制,即可以在没有使用实例化对象的时候进行执行。

主方法组成

如果一个方法定义在主类之中,并且由主方法直接调用,那么该方法的定义语法是:public static 返回值类型 方法名称(参数列表) {}

后来写到类结构的时候并没有使用static,其主要原因也是因为static方法的限制。

public class TestDemo {
	// static方法是独立于类之外的使用原则
	public static void main(String[] args) { //static方法
		print();
	}
	public static void print() { //static
		System.out.println("hello world");
	}
}

如果此时print()方法上没有写上static,那么表示的就是一个非static方法,所有的非static方法必须通过类对象才可以使用。但是也可以通过new TestDemo().print()进行调用。

但是反过来看也必须清楚一个问题,Java中给出的主方法名字时最长之一,其组成意义如下:

  • public:表示是公共的,主方法作为起点必须可以访问;
  • static:执行Java程序的时候执行的是一个类名称,所以表示不受实例化限制;
  • void:主方法是一切的起点,既然开始了就走吧;
  • main:是一个系统定义好的方法名称;
  • String args[]表示该类执行时所需的相关参数。

范例: 取得执行参数

public class TestDemo {
	public static void main(String[] args) {
		//所有的参数类型都是String型
		for(int x = 0; x < args.length; x++) {
			System.out.println(args[x]);
		}

	}
}

参数的设置:java TestDemo hello world !

如果现在的参数内容本身有空格,那么需要使用双引号:java TestDemo “hello” “world !”

static应用

static属性最大功能是进行共享的操作,所以在这一基础上可以使用static做一个对象产生的技术统计。新对象一定要使用构造方法完成,所以可以在构造方法中实现。

范例: 对象产生个数统计

class Person {
	private static int count = 0; //保存对象产生个数
	public Person() {
		System.out.println("对象个数:" + ++count);
	}
}

public class TestDemo {
	public static void main(String[] args) {
		new Person();
		new Person();
	}
}

那么也可以在以上的程序基础上做一个更加简答的扩充,假设:Person类中有一个name属性以及两个构造方法,其中一个构造方法可以接受外部传递的name属性内容,而另外一个构造方法是无参构造,一旦使用无参构造就希望可以自动为类中的name属性做一个自动赋值,例如:“NONAME-1”。那么此时就可以继续使用static属性控制。

class Person {
	private String name;
	private static int count = 0; //保存对象产生个数
	public Person() { //需要由程序自己来设置内容
		this("NONAME-" + count++); //调用本类有参构造
	}
	public Person(String name) { //由外部传递属性内容
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
}

public class TestDemo {
	public static void main(String[] args) {
		System.out.println(new Person().getName());
		System.out.println(new Person("Mj").getName());
		System.out.println(new Person().getName());
	}
}

这种自动为属性命名的操作由static属性控制。

总结

  1. static定义的属性和方法并不是进行类设计的首要选择;
  2. static的属性或方法不受到类的实例化对象限制,可以有类名称直接使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值