解析static关键字

一,static关键字的用途

方便在没有创建对象的情况下来进行调用(方法/变量)。

被static关键字修饰的方法或者变量,不需要依赖于对象来进行访问,只要类被加载了。
可以通过类名去访问。

可以修饰 类的成员方法,成员变量,static 代码块


1.static方法

static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类
的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

package com.xiaoqiang.test;

public class BaseTest {

	private static String str = "www.baidu.com";
	private String str2 = "www.qidian.com";
	
	
	public static void print() {
		System.out.println(str);
		System.out.println(str2);
	}
}

禁止在静态成员方法中访问非静态成员方法。
因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何
对象,因此只有通过类名来访问。


2.static变量

static变量也称作静态变量,静态变量和非静态变量的区别:
静态变量被所有的对象共享,在内存中只有一个副本,
它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
 

3.static块

可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
所以用来优化程序。

package com.xiaoqiang.test;

import java.sql.Date;

public class Women {
	private Date birthDate;

	public Women(Date birthDate) {
		this.birthDate = birthDate;
	}

	boolean isBornBoomer() {
		Date startDate = Date.valueOf("1946-12-11");
		Date endDate = Date.valueOf("1946-11-11");
		return birthDate.compareTo(startDate) >= 0 && birthDate.compareTo(endDate) < 0;
	}
}

  isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好:

  

package com.xiaoqiang.test;

import java.sql.Date;

public class Car {
	private Date birthDate;
	private static Date startDate, endDate;

	public Car(Date birthDate) {
		this.birthDate = birthDate;
	}

	static {
		startDate = Date.valueOf("1946-12-11");
		endDate = Date.valueOf("1946-11-11");
	}

	boolean isBornBoomer() {
		return birthDate.compareTo(startDate) >= 0 && birthDate.compareTo(endDate) < 0;
	}
}

 这样一改,第一次初始化就处理了.

4.static关键词修饰类

static修饰内部类,普通类是不允许声明为静态的,
只有内部类才可以。

被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类

需要注意的是当一个内部类没有使用static修饰的时候,是不能直接使用内部类创建对象,须要先使用外部类对象点new内部类对象及(外部类对象.new 内部类())
 

package com.xiaoqiang.test;

public class OutXxq {

	public static void main(String[] args) {

		OutXxq outXxq = new OutXxq();
		InnerXxq innerXxq = outXxq.new InnerXxq();

	}

	class InnerXxq {
		public InnerXxq() {
			System.out.println("我是内部类");
		}
	}
}

  这是不用静态类 初始化方式

  只是用静态类初始化:

package com.xiaoqiang.test;

import com.xiaoqiang.test.OutXxq.InnerXxq;

public class OutXxq {

	public static void main(String[] args) {
		OutXxq.InnerXxqs  b =  new OutXxq.InnerXxqs();
	}

	class InnerXxq {
		public InnerXxq() {
			System.out.println("我是内部类");
		}
	}

	static class InnerXxqs {
		public InnerXxqs() {
			System.out.println("我静态内部类");
	}
	}
}

 二.static关键字的误区

1.static关键字会改变类中成员的访问权限吗?
 不会
2.能通过this访问静态成员变量吗?

package com.xiaoqiang.test;

public class BaseTest {

	private static String str = "www.baidu.com";
	private String str2 = "www.qidian.com";
	static int a = 44;
	
	public static void print() {
		System.out.println(str);
	}
	
	private void testA() {
		int a = 5;
		System.out.println(this.a);
	}
	
	public static void main(String[] args) {
		new BaseTest().testA();
	}
}

  

打印:44

this代表什么?this是当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。

而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是44。

在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是44。

静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

3.static能作用于局部变量么?
static是不允许用来修饰局部变量


三.常见的笔试面试题


package com.xiaoqiang.test;

public class Dog extends Animal {
	static {
		System.out.println("test static");
	}
	public Dog() {
		System.out.println("test constructor");
	}
	public static void main(String[] args) {
		new Dog();
	}
}

class Animal {
	static {
		System.out.println("base static");
	}
	public Animal() {
		System.out.println("base constructor");
	}
}

  

输出的结果是:
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()的时候会先调用父类的构造器,然后
再调用自身的构造器。
 

public class Test {
     
    static{
        System.out.println("test static 1");
    }
    public static void main(String[] args) {
         
    }
     
    static{
        System.out.println("test static 2");
    }
}

  

test static 1
test static 2

虽然在main方法中没有任何语句,但是还是会输出,原因上面已经讲述过了。另外,static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。
 

参考资料:
https://www.cnblogs.com/dolphin0520/p/3799052.html

猜你喜欢

转载自blog.csdn.net/qq_32363305/article/details/81083306