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对象(先调用父类方法)

浙公网安备 33010602011771号