实例方法只能由对象来调用吗?
例如 有如下类:
class A {
public void normalFunc(){
System.out.println("我只是一个普通的实例方法")
}
}
我们想调用这个普通方法之前,是不是得先new 一个对象,A a=new A() ;然后用对象调用a.normalFunc();
那么为什么静态方法可以通过类名直接调用,实例方法不可以通过类名直接调用呢?事实上在类加载的时候,类的相关信息都已经存进了方法区了。
这一个问题大多数人都可以回答。因为没有实例化的对象,如果调用实例化方法的话,可能会触及到一些没有被初始化的东东。例如如下这个类:如果没有实例一个对象出来就可以直接调用的话,那么这个v变量,就根本没被初始化,连null都不是,连0都不是。
class A {
private int v;
public A(){
v=5;
}
public void normalFunc(){
System.out.println(v)
}
}
所以为了避免这种情况,java规定实例方法只能是对象实例化后才可以调用,这就完了吗?别急。
一个最常见的实例化对象的方式就是调用构造方法:A a=new A()。再看下面一个类:
class A {
private int v;
public A(){
normal();
System.out.println("A的构造方法");
v=5;
}
public void normal(){
System.out.println("A的实例方法");
}
}
其中构造方法中调用了普通实例方法。哎?不是说只能实例化后才能调用吗?怎么构造方法都还没有完就开始调用了呢?
这里其实是我理解的一个误区。我们都知道构造方法的作用就是初始化对象。所以我理所当然的认为实例化就是在构造方法执行完之后。其实new对象 的时候在构造方法执行之前就已经实例化了。
这里我们就需要回顾一下java在new对象的时候做的事情了。这个过程网上很多,简要好说一下(不考虑静态变量静态方法):
1,分配内存,
2,0值初始化(这个时候其实对象就已经有一个默认的初始化了,例如默认字符串属性字段为null,int属性字段为0,这一阶段是系统的默认初始化-实例化)。
3,最后才去调用构造方法(这一阶段是人为的初始化-实例化,只是在系统0值初始化的基础上去变更一些值而已,如果不变更,那么构造方法就可以什么都不做)。
所以最后才引出我们的结论。
1,实例化方法不是只能由对象来调用,而是必须对象实例化(初始化)后才能调用。
2,对象的实例化(初始化)并非是执行构造方法,而是构造方法执行前,就已经有系统默认实例化(初始化)了。
其实这些都不是什么新知识点。所以文章标题才叫没用的思考。不过兜兜转转了一圈,对基础知识的理解更深刻了。
接下来,我留下一个小问题,供大家思考:
public class ExtendsTest {
public static void main(String[] args) {
A a=new B();
}
}
class A {
public A(){
System.out.println("A的构造方法");
normal();
}
public void normal(){
System.out.println("A的普通方法");
}
}
class B extends A{
private String vb;
public B(){
System.out.println("B的构造方法");
vb="hello";
}
public void normal(){
System.out.println("B重写的A的普通方法"+String.valueOf(vb));
}
}
请问这一段代码会输出什么呢?