static域
- 如果将域定义为
static
,那么每个类的对象将共享该static
域。并且在加载类的时候对完成对static
变量的内存分配,此时可以通过类型直接方法。 - 对于实例变量,该类的每一个对象都有自己的一份拷贝,它们之间互不影响。
class A{
static int a=1;
int b=0;
public A(){}
public void setA(int a){
this.a=a;
}
public int getA(){
return a;
}
}
public class Test {
public static void main(String[] args)
{
A a=new A();
System.out.println(A.a+" "+a.b);
A.a++;
a.b++;
System.out.println(A.a+" "+a.b);
}
}
输出结果
1 0
2 1
static方法
- 用
static
形容的方法称为静态(static)方法,可以通过类名进行访问。 - 静态方法 不能访问类中的实例域,但是可以访问静态域。
- 在非静态方法中可以访问静态成员方法/变量。
静态导入
import
语句不仅可以导入类,还增加了导入静态方法和静态域的功能。
import static java.lang.System.out; //静态导入域
import static java.lang.Math.sqrt; //静态导入方法
public class Test {
public static void main(String[] args)
{
out.println("hello world");
out.println(sqrt(4.0));
}
}
static块
在一个类的声明中,可以包含多个代码块。只要构造 类 的对象,这些块就会被执行。同时可以将该代码块标记为static
,则称为静态代码块,静态代码块只能对静态域进行初始化。在类第一次加载的时候,将会执行。
public class Test {
public static void main(String[] args)
{
A a=new A();
}
}
class A{
static int n;
public A(){
System.out.println("runing constructor,n is "+n);
}
static{
System.out.println("static n is "+n);
n++;
}
{
System.out.println("not static n is "+n);
n++;
}
}
输出结果
static n is 0
not static n is 1
runing constructor,n is 2
- 当类第一次加载的时候,静态块将会对静态域 进行初始化。与实例域一样,除非将它们显式地设置成其它值,否则默认的初始值是0(整数),false(boolean)和null(应用型)。所有的静态初始化语句以及静态初始化块都将按照类定义的顺序执行。
- 当构造类的对象的时候,非静态化块就会执行。
- 最后执行构造函数。
当类A继承自B类的时候,此时B类中有静态化块,非静态化块,构造函数和初始化语句时,那么情况会复杂一些。此时建立类A的对象的执行顺序为:
对类加载阶段(主要是对静态数据的处理):
- B类所有静态数据域被初始化为默认值。
- 按照在类声明中出现的次序,依次B类执行所有静态域初始化语句。
- 执行B类的静态化块。
- 对A类所有静态数据域被初始化为默认值。
- 按照在类声明中出现的次序,依次A类执行所有静态域初始化语句。
- 执行A类的静态化块。
new A(主要对实例域的处理):
- B类所有实例域被初始化为默认值。
- 按照在类声明中出现的次序,依次B类执行所有实例域初始化语句。
- 执行B类的非静态化块。
- 执行B类构造器。
- 对A类所有实例域被初始化为默认值。
- 按照在类声明中出现的次序,依次A类执行所有实例域初始化语句。
- 执行A类的非静态化块。
- 执行A类构造器。
public class Test {
public static void main(String[] args)
{
A a=new A();
new A();//没有执行静态初始化块,静态初始化块只在类第一次加载的时候执行。
}
}
class A{
static int n;
public A(){
System.out.println("A runing constructor,n is "+n);
}
static{
System.out.println("A static n is "+n);
n++;
}
{
System.out.println("A not static n is "+n);
n++;
}
}
输出结果:
A static n is 0
A not static n is 1
A runing constructor,n is 2
A not static n is 2
A runing constructor,n is 3
public class Test {
public static void main(String[] args)
{
//A a=new A();
B b=new B();
}
}
class A{
static int n;
public A(){
System.out.println("A runing constructor,n is "+n);
}
static{
System.out.println("A static n is "+n);
n++;
}
{
System.out.println("A not static n is "+n);
n++;
}
}
class B extends A{
static int n=1;
public B(){
System.out.println("B runing constructor,n is "+n);
}
static{
System.out.println("B static n is "+n);
n++;
}
{
System.out.println("B not static n is "+n);
n++;
}
}
输出结果:
A static n is 0
B static n is 1
A not static n is 1
A runing constructor,n is 2
B not static n is 2
B runing constructor,n is 3
静态(static)内部类
用static修饰的内部类称为静态内部类。非静态内部类在编译完成后保存着外围类的引用。但是静态内部类却没有。这意味着
- 静态内部类的创建不需要依赖于外围类。
- 静态内部类不能使用外围类的非静态数据域和方法。
这是网上的一个例子:
public class OuterClass {
private String sex;
public static String name = "chenssy";
/**
*静态内部类
*/
static class InnerClass1{
/* 在静态内部类中可以存在静态成员 */
public static String _name1 = "chenssy_static";
public void display(){
/*
* 静态内部类只能访问外围类的静态成员变量和方法
* 不能访问外围类的非静态成员变量和方法
*/
System.out.println("OutClass name :" + name);
}
}
/**
* 非静态内部类
*/
class InnerClass2{
/* 非静态内部类中不能存在静态成员 */
public String _name2 = "chenssy_inner";
/* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
public void display(){
/* 外围类访问静态内部类:内部类. */
System.out.println(InnerClass1._name1);
/* 静态内部类 可以直接创建实例不需要依赖于外围类 */
new InnerClass1().display();
/* 非静态内部的创建需要依赖于外围类 */
OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
/* 方位非静态内部类的成员需要使用非静态内部类的实例 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy
如有错误,欢迎指正!