静态方法是java中很重要的一个方法,它有如下好处:
① 静态方法可以直接通过 类名.方法名 来调用,而实例方法则需要事先实例化对象,然后才能调用。
② 节约内存,一个方法声明了static 之后,无论多少个方法调用它,它在只占用了一个内存;如果没有声明static,一个方法被调用一次,它就占用一次内存。
③ 访问速度较快,因为静态不需要实例化就能使用
④ 静态方法生命周期很长,所以不担心过期问题
静态方法既然有那么多好处,呢什么时候定义静态呢?
其中给出的一个答案是:当功能内部没有使用到非静态数据(对象的特有数据)那么该功能可以定义成静态的。
疑问:静态不能访问非静态数据?
搜索答案发现:大多给出的解释是这样的:类的静态方法随类的加载而加载,也就是说类创建了,静态方法就存在在方法区了,可是可能这个时候还没有进行对象的初始化,既然没有对象初始化,那对象的成员变量,成员方法自然就不存在,静态方法就访问不了,。。。
疑问:如果new出对象调用静态方法访问对象的成员那么就该能访问到吧?写出以下代码验证
<span style="font-size:12px;">class Person1
{
String name = "zhangsan";
static String cn = "china";
public static void speak()
{
System.out.println("name="+name);
}
}
class Person1Demo
{
public static void main(String[] args)
{
Person1 p1 = new Person1();
p1.speak();
}
}</span>
提示如图所示:
还是报错
最后发现问题是这样的:静态方法在编译的时候就加载到内存里,而对象的建立是发生在运行阶段,这有一个时间的先后问题!
也就是说:用STATIC修饰的方法和变量也叫类变量或类方法所属于类, 因为JVM加载一个类的时候, 这些由STATIC修饰的变量或方法是在给成员变量赋值之前进行的, 所以当一个STATIC方法里有一个成员变量的时候, JVM就不知道其中包涵的成员变量, 所以不能进行编译,会报错。
关于静态方法的使用:
① 直接通过 类名.方法名的方法 来调用(可以叫做类方法)
② 静态方法不能使用this(与实例相关)
③ 静态和最终方法(final修饰)不能被覆盖,只有实例方法才能被覆盖
④ 静态代码块:格式 :static{执行语句} 当类被载入时,静态代码块则被执行,且只被执行一次,静态代码块可用作不创建对象也可能需要执行的代码.
对于静态方法能不能被覆盖,通过以下代码来验证:
<span style="font-size:12px;">class fu
{
public static void fustatic()
{
System.out.println("fustatic");
}
public void funostatic()
{
System.out.println("funostatic");
}
}
class zi extends fu
{
public static void fustatic()
{
System.out.println("zistatic");
}
public void funostatic()
{
System.out.println("zinostatic");
}
}
class method
{
public static void main(String[] args)
{
//fu fu = new fu();
//fu.fustatic();//运行结果fustatic
//fu.funostatic();//运行结果funostatic
fu f = new zi();
f.fustatic();//运行结果fustatic
f.funostatic();//运行结果zinostatic
//zi z = new zi();
// z.fustatic();//运行结果zistatic
}
}</span>
现象:
多态时,调用和父类同名的静态方法运行的却是定义在父类中的方法
解释:
原因是静态方法是在编译的时候把就把静态方法和类的引用类型进行匹配,而不是在运行的时候和类引用进行匹配。因此我们得出结论:当我们在子类中创建的静态方法,它并不会覆盖父类中相同名字的静态方法。在java中方法间没有多态就不能覆盖。
结论:java中静态方法不能被覆盖。
子类转型为父类的规则:
只能调用父类的属性
只能调用父类未被复写的方法
只能调用被子类复写的方法