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 条评论
登录 后参与评论

相关文章

来自专栏Linux驱动

指针学习(详解)

在指针中*是取内容,&是取地址 (在结构体中时:变量结构体用".",指针结构体用"->") 通常有两种的表示: 1. 通过指针向指向的地址内容赋值 *p=a;...

18850
来自专栏咸鱼不闲

static关键字,面试经常被问到!(一)

static可以理解为全局的。 static可以修饰: 变量,方法,代码块,内部类。

34050
来自专栏用户2442861的专栏

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

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

22320
来自专栏noteless

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

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

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

字符串匹配问题

、字符串匹配问题 【问题描述】        字符串中只含有括号 (),[],<>,{},判断输入的字符串中括号是否匹配。如果括号有互相包含的形式,从内到外必...

40560
来自专栏禁心尽力

Java异常总结

异常就是在程序中可能要发生的未知错误,java机制中异常分为2大类:Exception和Error。 对异常的处理方式有2种,一是将异常通过关键字throws抛...

25370
来自专栏http://www.cnblogs.com

python学习笔记:深浅拷贝的使用和原理

在理解深浅拷贝之前,我们先熟悉下变量对象和数据类型 1.变量和对象 变量-引用-对象(可变对象,不可变对象) 在python中一切都是对象,比如[1,2],'h...

36860
来自专栏desperate633

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

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

9210
来自专栏前端知识分享

第29天:js-数组添加删除、数组和字符串相互转换

一、添加数组 var arr=[1,3,5]; arr.push(7,9);//添加7和9到数组arr后面,得到[1,3,5,7,9] 1、push();可向数...

24910
来自专栏赵俊的Java专栏

equals 和 == 到底有什么区别?

22030

扫码关注云+社区

领取腾讯云代金券