java-static修饰符

什么是静态?

概念:

  静态可以修饰属性和方法。

  称为静态属性(类属性)、静态方法(类方法)。

  静态成员是全类所有对象共享的成员。对象而产生

  在全类中只有一份(是全类对象共享的),不因创建多个对象而产生多份。

静态属性代码:

package day11;

public class TestStatic {

	public static void main(String[] args) {
		ClassA a1=new ClassA();
		ClassA a2=new ClassA();		
		a1.m++;
		a1.n++;
		System.out.println(a2.m);//11
		System.out.println(a2.n);//21
	}
}
class ClassA{
	int m=10;
	static int n=20;
	public static void print() {
		//System.out.println(m);error
		System.out.println(n);
		//ma();这个会报红,因为在静态方法中调用了非静态方法
		//mb();这个正确
	}
	public void ma() {}
	public static void mb() {}
	
}

static:

 属性:静态属性(静态属性不是在创建对象时有的)全类共有,可以直接拿类名访问。如ClassA.n

  静态变量跟对象没有关系,初始化是先于成员变量的。

 静态方法:静态能修饰属性,也能修饰方法。在静态方法中,不能访问非静态成员(方法和属性)。

  静态方法可以用类名引用。例子见如下图12行。

 在print()方法中,是不能直接调用ma()方法的,但是却可以通过对象的创建来引用:

public static void print() {
		//System.out.println(m);error
		System.out.println(n);
		//ma();这个会报红,因为在静态方法中调用了非静态方法 ma指的默认是this.ma() this:当前对象
		ClassA a=new ClassA();
         a.ma();//运行结果:21
         问题:在静态方法中能有this吗? 不能 因为this指的是当前对象,而静态方法没有对象
	}
静态方法与静态方法之间的覆盖:
package day11;

public class TestStatic {

	public static void main(String[] args) {
		Super s=new Sub();
		s.m();
	}
}

class Super{
	public static void m() {
		System.out.println("Super");
	}
}
class Sub extends Super{
	public static void m() {
		System.out.println("Sub");
	}
}

  运行结果:

   分析一下运行结果:按照之前的多态的思想(子类与父类有一样的方法,子类方法覆盖父类的方法),运行结果应该是Sub。思考:为什么会出现这样的结果呢?在静态方法中,是例外。静态方法的覆盖的情况下,编译器对引用类型去调用一个静态方法,结果输出引用类型的静态方法。结果为Super就不奇怪了。

  非静态方法不能覆盖父类的静态方法。因为会报错。静态方法自能被子类的静态方法覆盖,而且没有多态(只根据引用类型,调用相应的静态方法)。

  注:带有静态二字的都和对象没有什么关系。

代码:

package day11;

public class TestDynamicBlock {

	public static void main(String[] args) {
		new MyClass();
	}

}
class MyClass{
	String field="实例属性";
	{
		System.out.println(field);
		System.out.println("动态代码块");
	}
	public  MyClass(){
		System.out.println("构造方法");
	}
}

  运行结果:

  初始代码块:静态初始代码块在类加载的时候执行。静态修饰静态初始代码块。

类加载:

    当JVM第一次使用一个类时,读入这个类所对应的.class文件,并保存起来。  

  加载时机:

    创建对象。

    创建子类对象。(加载子类之前,先加载父类)

    访问静态属性。

    调用静态方法。

    Class.forName(“全限定名”)指名道姓的我要加载某个类

    将.class文件中对类的描述信息加载到内存中,进行保存。

      如:包名、类名、父类、属性、方法、构造方法...

    如果只是声明一个类的引用,不需要类加载。如A a;   A a=null;变量的本身不需要存对象,存的是对象的地址。

  类加载的步骤:

    1)如果需要,先加载父类。

    2)按顺序初始化静态属性,或执行静态初始代码块。按顺序执行。

静态代码块例子1:

package day11;

public class TestDynamicBlock {

	public static void main(String[] args) {
//		new MyClass();
//		new A();
		System.out.println(A.m);
//		new A();
	}

}
class MyClass{
	static String field="实例属性";
	static {
		System.out.println(field);
		System.out.println("动态代码块");
	}
	public  MyClass(){
		System.out.println("构造方法");
	}
}
class A{
	static int m=10;
	static {
		System.out.println("Load A");//类加载的时候执行
	}
	public A(){
		System.out.println("A");
	}
}

  运行结果:

例子2:

package day11;

public class TestDynamicBlock {

	public static void main(String[] args) {
//		new MyClass();
//		new A();
//		System.out.println(A.m);
//		new A();
		new B();
	}

}
class MyClass{
	static String field="实例属性";
	static {
		System.out.println(field);
		System.out.println("动态代码块");
	}
	public  MyClass(){
		System.out.println("构造方法");
	}
}
class A{
	static int m=10;
	static {
		System.out.println("Load A");//类加载的时候执行
	}
	public A(){
		System.out.println("A");
	}
}
class B extends A{
	static {
		System.out.println("Load B");
	}
	public B() {
		System.out.println("B");
	}
}

  运行结果:

 为什么会出现这样的结果? new B();先加载B(加载B得先加载父类),再实现B对象(先调用父类方法)

原文地址:https://www.cnblogs.com/SpringChuXin/p/13790539.html