Java类体中有类方法和实例方法。
类方法
用static修饰的方法。由于类方法是属于整个类的,并不属于类的哪儿个对象,所以类方法的方法体中不能有与类的对象有关的内容。即类方法体有如下限制:
1.类方法中不能引用对象变量;
2.类方法中不能调用类的对象方法;
3.在类方法中不能调使用super,this关键字;
4.类方法不能被覆盖。
实例方法
当一个类创建了一个对象后,这个对象就可以调用该类的方法(对象方法)。
1.实例方法中可以引用对象变量,也可以引用类变量;
2.实例方法中可以调用类方法;
3.对象方法中可以使用super,this关键字。
区别
在类的初始化过程中,首先加载的是类方法,其次才是实例方法。
类方法:在该类的字节码被加载到内存时,就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用,类方法的入口地址直到程序退出时才被取消。类中的类方法不可以操作实例变量,也不可以调用实例方法,这是因为在类创建对象之前,实例成员变量还没有分配内存,而且实例方法也没有入口地址。
实例方法:当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。
注意:当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。
关于这一点的解释如下:在创建对象时,实例方法的入口地址被保存在方法区中,而有人会有疑问:方法区不是线程共享的区域么?对的,因为如果实例方法也随着实例的增加而增加的话,那么将消耗很大的内存。为了保证多个实例的方法入口地址共享一小段内存,且方法中的数据又仅提供给当前实例使用,Java是通过this关键字做到的。比如:instance1.instanceMethod(); instance2.instanceMethod(); 因为我们也知道方法中的局部变量是存储于方法栈中,而方法栈是线程私有的。所以也就是:共享方法的入口地址,但方法中的数据及局部变量都是私有的。
在传递给对象参数的时候,Java 编译器自动先加上了一个this参数,它表示传递的是这个对象引用,虽然他们两个对象共用一个方法,但是他们的方法中所产生的数据是私有的,这是因为参数被传进来变成call stack内的entry,而各个对象都有不同call stack,所以不会混淆。其实调用每个非static方法时,Java 编译器都会自动的先加上当前调用此方法对象的参数,有时候在一个方法调用另一个方法,这时可以不用在前面加上this的,因为要传递的对象参数就是当前执行这个方法的对象。
总结:
方法入口是同一个,只不过方法内的局部变量以及局部数据(也就是方法中所产生的数据都是私有的)是线程私有的。
方法入口是存放在方法区(线程共享),局部变量是存在方法栈(线程私有)。