酸狗带你了解static关键字
说到了static关键字,相信大家都不陌生,这是相对比较难以理解的一个关键字,酸狗就带着大家深入了解下static关键字。
前言
在《Java编程思想》P86页有这样一段话:
“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”
这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:
方便在没有创建对象的情况下来进行调用(方法/变量)。
很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
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 ;
}
//setter、 getter略
public String getInfo(){
return "姓名:" +this.name + "、年龄: " + this.age+"、国家:"+this.country;
}
}
public class JavaDemo {
public static void main(String args []) {
Person perA = new Person("张三",10);
Person perB = new Person("李四",10);
Person perC = new Person("王五",11);
system.out.println(perA.getInfo());
system.out.println(perB.getInfo()) ;
system.out.println(perc.getInfo()) ;
}
}
传统操作
为了更好的观察出程序的问题,下面对此操作做一个内存的分析。
在正常开发过程之中每一个对象要保存有各自的属性,所以此时的程序没有任何问题,但是如果突然有一天,国家变成了中华人民共和国。并且你已经产生了5000W个对象,那么此时面对你的将是场噩梦。因为每一个对象都拥有各自的country属性,所以这个时候就会发现从整体的设计上就出现了问题(重复保存数据并且修改不方便)。
public class JavaDemo {
public static void main(String args []) {
Person perA = new Person("张三",10);
Person perB = new Person("李四",10);
Person perC = new Person("王五",11);
perA.country ="中华人民共和国";
system.out.println(perA.getInfo());
system.out.println(perB.getInfo()) ;
system.out.println(perc.getInfo()) ;
}
}
那么这个时候最好的解决方案就是将country修改为公共属性,而这种情况下就必须使用static进行标注。
举例:
修改Person类定义,使用static定义公共属性
//定义一个程序类
class Person{ //创建所有同一个国家的类
private String name;
private int age;
static String country = "中华民国";//国家,暂时不封装
public Person(String name ,int age) {
this.name = name ;
this.age = age ;
}
//setter、 getter略
public String getInfo(){
return "姓名:" +this.name + "、年龄: " + this.age+"、国家:"+this.country;
}
}
public class JavaDemo {
public static void main(String args []) {
Person perA = new Person("张三",10);
Person perB = new Person("李四",10);
Person perC = new Person("王五",11);
perA.country ="中华人民共和国";
system.out.println(perA.getInfo());
system.out.println(perB.getInfo()) ;
system.out.println(perc.getInfo()) ;
}
}
只是在country 加了个static关键字,此时会发现所有对象中的country属性的内容都发生了改变,所以这是一个公共属性。
而此时的内存关系图如下:
但是对于static属性的访问需要注意一点:由于其本身是一个公共的属性,虽然可以通过对象进行访问,但是最好的做法应该是通过所以对象的最高代表(类)来进行访问,所以static属性可以由类名称直接调用
。
所以可以用类名称调用如下;
Person.country ="中华人民共和国";
static属性虽然定义在类之中,但是其并不受到类实例化对象的控制,所以static属性可以在没有实例化对象的时候使用。
实例:
public class JavaDemo {
public static void main(String args []) {
system.out.println(Person.country);
Person.country ="中华人民共和国";
Person per =new Person("张三",10);
system.out.println(per.getInfo()) ;
}
}
在以后进行类设计的时候首选的一定是非static属性,而考虑到公共信息存储的时候才会使用到static属性。非static属性必须在实例化对象产生之后才可以使用,而static属性可以在没有实例化对象产生的情况下直接通过类名称进行调用。
static定义方法
static关键字也可以进行方法的定义,static方法的主要特点在于,其可以直接由类名称在没有实例化对象的情况下进行调用。
举例:
//定义一个程序类
class Person{ //创建所有同一个国家的类
private String name;
private int age;
private static String country = "中华民国";//封装国家
public Person(String name ,int age) {
this.name = name ;
this.age = age ;
}
//setter、 getter略
public static void setCountry(String c){ //static方法
country =c;
}
public String getInfo(){
return "姓名:" +this.name + "、年龄: " + this.age+"、国家:"+this.country;
}
}
public class JavaDemo {
public static void main(String args []) {
Person.setCountry("中华人民共和国");
Person per =new Person("张三",10);
system.out.println(per.getInfo()) ;
}
}
这个时候对于程序而言方法就有了两种: static方法、非 static方法,这两个方法之间在调用上就有了限制:
- static方法只允许调用static属性或static方法;
- 非static方法允许调用static属性或static方法;
所有的static定义的属性和方法都可以在没有实例化对象的前提下使用,而所有的非static定义的属性和方法必须要有实例化对象的情况下才可以使用。
如果说现在可以理解这个限制,那么对于之前的方法定义就可以得出新的结论:
方法定义的时候强调过,“当前的方法都是在主类中定义的,并且由主方法调用的”
举例
public class JavaDemo {
public static void main(String args []) {//static方法
new JavaDemo().print();//通过对象调用
}
public void print(){//非static方法
system.out.println('酸狗') ;
}
}
static定义的方法或者是属性都不是你代码编写之初所需要考虑的内容,只有在回避实例化对象调用并且描述公共属性的情况下才会考虑使用static定义的方法或者是属性。
static应用
为了加强理解,下面做两个简单的程序来进行static应用的提示。
范例:
编写一个程序类,这个类可以实现实例化对象个数的统计,每一次创建新的实例化对象都可以实现一个统计操作。
- 此时可以单独创建一个static属性,因为所有对象都共享同一个static属性,那么在构造方法中可以实现数据的统计处理。
class Book{
private String title;
private static int count =0;
public Book(string title){
this.title = title;
count++;
system.out.println("第" + count +"本图书创建出来。");
}
}
public class JavaDemo{
public static void main(string args []){
new Book("Java");
new Book("JSP");
new Book("Spring");
}
}
范例:
实现属性的自动命名处理
- 如果现在传递了title属性,而如果没有传递title属性,则自动采用“NOTITLE-编号”的形式进行该属性内容的定义。
class Book{
private String title;
private static int count =0;
public Book(){
this("NOTITLE - "+count++ )
}
public Book(string title){
this.title = title;
}
private String getTitle() {
return this.title;
}
}
public class JavaDemo{
public static void main(string args []){
system.out.println(new Book("Java").getTitle()) ;
system.out.println(new Book("JSP").getTitle()) ;
system.out.println(new Book("Spring").getTitle()) ;
}
}
这样处理的好处是可以避免在没有设置title属性时内容为null的重复问题。
变量
静态变量:
静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。
实例变量:
每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
注意:
在C/C++中static是可以作用域局部变量的,但是在Java中切记:static是不允许用来修饰局部变量。不要问为什么,这是Java语法的规定。
结语
ok,文章就先到这里了,希望这篇文章能够帮助到你对static的认识,若有不足或者不正之处,希望谅解并欢迎批评指正酸狗!
如果本文章对你有帮助,哪怕是一点点,那就请点一个赞给酸狗,谢谢大家~
end~