你不可不知的static(1)-引入及特点

在《Java编程思想》中有这样一段话:“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:方便在没有创建对象的情况下来进行调用(方法/变量)。

下面我们开始探索我们不可不知的static。

首先,为什么引入static,请看这一段代码:

首先我们定义一个人(类):

class Person{
	private String name;
	private int age;
	private String country;
//	private static String country;
	
	static int num = 100;
	
	public Person() {
		super();
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person(String name, int age, String country) {
		super();
		this.name = name;
		this.age = age;
		this.country = country;
	}
	
	@Override
	public String toString() {
		return "人 [姓名=" + name + ", 年龄=" + age + ", 国籍=" + country
				+ "]";
	}
	
//	public static String getCountry() {
//		return country;
//	}
//	public static void setCountry(String country) {
//		Person.country = country;
//	}
	
}


然后我们跑一下代码:

public class StaticTest {

	/**
	 * 权兴权意-2016.10.8
	 * static关键字的引入、特点
	 */
	public static void main(String[] args) {
		Person p1 = new Person("甲",18,"中国");
		Person p2 = new Person("乙",18,"中国");
		Person p3 = new Person("丙",18,"中国");
//		Person p2 = new Person("乙",18);
//		Person p3 = new Person("丙",18);
		
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);
		
//		p3.setCountry("德国");
//		System.out.println("p3.setCountry('德国')");
//		
//		System.out.println(p1);
//		System.out.println(p2);
//		System.out.println(p3);
//		
//		System.out.println("Num:");
//		System.out.println(p3.num);
//		System.out.println(Person.num);
//		
//		new Test();
		
	}

}


输出结果:

人 [姓名=甲, 年龄=18, 国籍=中国]
人 [姓名=乙, 年龄=18, 国籍=中国]
人 [姓名=丙, 年龄=18, 国籍=中国]


对于一个人,姓名、年龄一般都不同,但如果都是中国人,国籍一样。

每次创建对象都在堆内存开辟这样的空间,这是一种浪费。

此时,当多个对象有共同的成员变量值-我们用static关键字修饰。(可以修饰成员变量和成员方法
我们修改代码:

//	private String country;
	private static String country;


		Person p1 = new Person("甲",18,"中国");
//		Person p2 = new Person("乙",18,"中国");
//		Person p3 = new Person("丙",18,"中国");
		Person p2 = new Person("乙",18);
		Person p3 = new Person("丙",18);
		
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);

通过static共用国籍变量。

输出结果如下:

人 [姓名=甲, 年龄=18, 国籍=中国]
人 [姓名=乙, 年龄=18, 国籍=中国]
人 [姓名=丙, 年龄=18, 国籍=中国]

为static(Java面向对象)点赞。

下面我们看一下static关键字特点

核心: 随着类的加载而加载
1.优先于对象存在
2.被类的所有对象共享( 这也是我们判断是否使用静态关键字的条件, 举例:饮水机和水杯的问题思考
3.可以通过类名调用, 既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。

正因为static修饰的东东被其他所有对象共享,因此也会有一些问题,比如说丙突然移民德国:

	public static String getCountry() {
		return country;
	}
	public static void setCountry(String country) {
		Person.country = country;
	}


		p3.setCountry("德国");
		System.out.println("p3.setCountry('德国')");
		
		System.out.println(p1);
		System.out.println(p2);
		System.out.println(p3);


输出结果:

p3.setCountry('德国')
人 [姓名=甲, 年龄=18, 国籍=德国]
人 [姓名=乙, 年龄=18, 国籍=德国]
人 [姓名=丙, 年龄=18, 国籍=德国]

因此,务必三思static的使用场景。


我们试试通过类名和对象名调用:

		System.out.println("Num:");
		System.out.println(p3.num);
		System.out.println(Person.num);

输出结果ok:

Num:
100
100


最后,我们看一道关于static的面试题:

class Test extends Base{
	 
    static{
        System.out.println("test static");
    }
     
    public Test(){
        System.out.println("test constructor");
    }
     
}
 
class Base{
     
    static{
        System.out.println("base static");
    }
     
    public Base(){
        System.out.println("base constructor");
    }
}

		new Test();


你能猜出输出结果吗?

base static
test static
base constructor
test constructor

至于为什么是这个结果,我们先不讨论,先来想一下这段代码具体的执行过程,
在执行开始,先要寻找到main方法,因为main方法是程序的入口,
但是在执行main方法之前,必须先加载Test类,
而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,
在加载Base类的时候,发现有static块,便执行了static块。
在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。
在加载完所需的类之后,便开始执行main方法。
在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。
因此,便出现了上面的输出结果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值