static关键字

   对于static关键字的用法,主要分为三个部分,分别是静态变量、静态方法和静态类。

1.静态变量

静态变量(静态域)不是类的某个具体对象所有,而是类的所有对象共有的,静态变量既能够被对象调用,也可以用类来调用。

package StaticTest_4_3;

public class StaticTest
{
	public static int count = 3;
	public static void main(String[] args)
	{
		StaticTest test1 = new StaticTest();
		System.out.println(test1.count);
		StaticTest test2 = new StaticTest();
		test2.count++;
		System.out.println(test1.count + " " + test2.count + " " + StaticTest.count);
	}

}

输出结果:

3
4 4 4

  每个类对象都可以对类的静态变量进行修改,这些修改都会被保存,这一点和final关键字修饰的变量不一样。

  注意:静态变量不能引用非静态方法,原因是,加载静态变量的时候,非静态变量、方法都还不存在,所以不能引用。但是非静态方法或类可以正常引用静态变量或方法,因为非静态的总是出现在静态的之后。

2.静态方法

静态方法和静态变量一样,属于类所有,在加载类的时候进行加载,不属于具体的类的对象,所有对象均可以进行引用。

  对于静态类,有几点注意事项:

  ①仅能够调用其他的static方法;

  ②只能访问static数据;

  ③不能以任何方式引用this或super。

package StaticTest_4_3;

public class StaticTest1 
{
	private static String str1 = "static";
	private String str2 = "pro";
	
	public StaticTest1(){}

	public void print1()
	{
		System.out.println(str1);
		System.out.println(str2);
		print2();
	}
	
	public static void print2()
	{
		System.out.println(str1);
		System.out.println(str2);
		print1();
	}
}

  由于print2是独立于对象存在的,可以直接使用类名调用。

假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:

  staticTest1.print2();

  此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以

禁止在静态成员方法中访问非静态成员方法。

非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。

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

  另外记住,即使没有显示地声明为static,类的构造器实际上也是静态方法。

3.静态类

一个普通的类不允许被声明为static,但是在内部类中可以直接将其声明为static,这个时候,外部类可以直接调用内部类,因为static的内部类是在加载外部类的同时加载的,所以并不需要实例化外部类就能直接调用内部类。

BaseStatic.java

public class BaseStatic
{
	static
	{
		System.out.println("Load base static");
	}
	
	public BaseStatic()
	{
		System.out.println("BaseStatic constructor");
	}
	
	static class BaseInnerClass
	{
		static
		{
			System.out.println("Base inner class static");
		}
		
		public BaseInnerClass()
		{
			System.out.println("BaseInnerClass constructor");
		}
	}
}

StaticLoadOrderTest.java

public class StaticLoadOrderTest{

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new BaseStatic.BaseInnerClass();
    }

}

  因为BaseInnerClass是静态的,所以这里并不需要加载外部类和实例化外部类,可以直接加载BaseInnerClass并实例化。

输出结果:

Base inner class static
BaseInnerClass constructor

再看一个例子

BaseStatic.java

package StaticTest_4_3;

public class BaseStatic
{
	static
	{
		System.out.println("Load base static");
	}
	
	public BaseStatic()
	{
		System.out.println("BaseStatic constructor");
	}
	
	static class BaseInnerClass
	{
		static
		{
			System.out.println("Base inner class static");
		}
		
		public BaseInnerClass()
		{
			System.out.println("BaseInnerClass constructor");
		}
	}
}

StaticLoadOrderTest1.java

package StaticTest_4_3;

public class StaticLoadOrderTest1 
{
	static
	{
		System.out.println("Load test");
	}
	
	public StaticLoadOrderTest1()
	{
		System.out.println("Test Constructor");
	}
	
	public static void main(String[] args)
	{
		new BaseStatic();
		new StaticLoadOrderTest1();
		new BaseStatic.BaseInnerClass();
	}

}

输出结果:

Load test
Load base static
BaseStatic constructor
Test Constructor
Base inner class static
BaseInnerClass constructor

  在进入main方法之前,需要加载StaticLoadOrderTest类,这时候发现有static代码块,先加载静态代码块,然后进入main方法内部,new BaseStatic(),这时候需要加载BaseStatic类,同时也要先加载静态代码块,然后调用构造器。注意:这里并没有加载BaseInnerClass,因为它是内部类只有在真正用到的时候才会进行加载,相信聪明的读者看到这个是不是想到了又一种单例设计模式的实现方式?自己研究吧。回到main方法中,接下来该执行new StaticLoadOrderTest()了,因为StaticLoadOrderTest类之前已经被加载过一次了,并且类只加载一次,所以这里就直接构造了;然后是最后一句new BaseStatic.BaseInnerClass()了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏noteless

-1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口 区别 多态

面向对象把功能逻辑封装到类本身,用对象去调用功能 持有数据,结构更加自然,也更符合人们的思维习惯

921
来自专栏weixuqin 的专栏

java 复习总结

类采用首字母大写的方式来命名,如果是多个单词的类名,则每个单词首字母都大写,例如:HelloWorld 。

912
来自专栏编程心路

代码块相关的题,特么再也不会做错了!

代码块包括静态代码块和非静态代码块,另外还有构造函数,它们的执行顺序是面试中经常考的,理解了下面这些基本知识,特么再也不会做错了。

561
来自专栏十月梦想

each()list()while遍历数组

each()函数:需要一个数组作为参考,each函数返回1,0,key,value键值,0,key返回键,1,value对应的值,

971
来自专栏数据结构与算法

29:统计字符数

29:统计字符数 总时间限制: 1000ms 内存限制: 65536kB描述 给定一个由a-z这26个字符组成的字符串,统计其中哪个字符出现的次数最多。 ...

3966
来自专栏土豆专栏

Java面试之comparator与comparable

compareTo(T o),比较此对象与指定对象的顺序。如果该对象小于等于或者大于指定对象,则分别返回负整数、零、正整数

1631
来自专栏calmound

Xtu 1150 Assembly Line

http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1150 题意:任意多个ABC三个数,...

2797
来自专栏TungHsu

这或许是对小白最友好的python入门了吧——14,遍历字典

同列表元组一样,字典也能够遍历,但是和列表元组不一样的是,字典遍历分三个部分:遍历键值对、遍历键、遍历值 首先我们新建一个字典: score = {"engl...

2203
来自专栏desperate633

详解javascript中的即时函数,内部函数,能重写自身的函数即时函数内部函数返回函数的函数能重写自己的函数小结

在上篇谈到匿名函数和回调函数的基础上,我们接着介绍javascript中的即时函数,内部函数,返回函数的函数,能重写自身的函数等几种常见的函数类型及使用方法。只...

831
来自专栏用户2442861的专栏

Java finally语句到底是在return之前还是之后执行?

网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正...

1812

扫码关注云+社区