Java编译器在初始化对象的时候,为同一类型(即同一类)的对象在栈区存储了函数副本(即使对static方法也是如此)。
为了区别不同对象,新对象生成时,会由编译器生成一个引用变量进行指向。
该引用变量指向堆区中存储具体对象域属性值的内存区域,即同属一类的对象,共享其类定义的函数。
既然函数为公用的,那么当同一方法被不同对象调用的时候,如何正确的区别调用此方法的对象以产生正确的行为呢?
Example:
class Test
{
int num;
Test(int i)
{num=i;}
print()
{ System.out.printl(num);}
}
main()
{
Test t1=t1(1);
Test t2=t2(2);
t1.print();
t2.print();
}
Test类具有两个对象 t1、t2,此处它们都调用了print()方法,根据print方法的定义,它们需要打印出自己的属性num的数值。
那么print方法是如何被调用,以保证被指向正确的内存空间的呢?我们调用函数的时候并没有显示的给出对象引用作为参数啊!
实质是:我们在通过对象调用方法的时候,编译器暗自的把“所操作对象的引用”作为第一个参数传递给了print。
e: t1.print(); -----> Test.Print(t1);//此处仅作为理解,并无实际意义
这样一来,方法就能准确的的根据编译器传递来的对象引用确定操作的对象,从而避免了出错。
e: print()----->print(){System.out.print(this.number)}//此处的this关键字(C++中称this指针)代表了执行该方法的对象。
this关键字并不常用,但遇到要将调用的对象作为范围值返回的情况,this还是很重要的。
Example:
class Dog
{
String name;
Dog(String dogname){dogname=name};
Dog bark()
{
System.out.printl(name+"is barking");
return this;
}
}
mian()
{
Dog dog=new Dog("Happy");
dog.bark().bark().bark();
}
调用bark()方法后,通过this指针返回调用对象本身,从而可以实现对bark()方法的无限调用!
在java中除静态方法外,其余的方法调用一定要与其调用对象联系在一起。
同一个类中,方法和域的操作都无需指明调用对象, 但是在一个类中调用另一个类得方法(静态方法、导出类调用基类方法除外),一定要指明调用对象。
值得一提的是static方法,static方法不能操作除static对象的域成员(static成员不能算是对象的域成员),static方法不需要this指针,故其不需要对象支持!
static方法一般提供一些全局的基本操作(在C++中称为全局方法),但是在Java中不允许脱离类而单独的存在方法,故将其放在类中做全局方法。
由于static方法,不能访问对象的域成员,故一般其需要的参数由调用的时候全部给出。
如 :
Package MathMethod
Class MathAdd
{
static double add(ball b1, ball b2){ return b1.diameter+b2.diameter ;}
}
此方法中就将计算两个球的总直径长度作为了一个静态方法,并将两个球的对象的引用作为参数传入。
(这是非常重要的,非static方法是隐式传递this指针,而static中必须显示给出对象引用,可以据此灵活编写静态方法)
由于static方法需要依附于任何对象进行调用,鼓起调用格式可以直接为 类名.static方法名。
java中的包机制,给予了其一种更为方便的调用方法,允许像C++中的全局方法一样方便的对其进行调用。
Example: 上例中add方法的包路径为: MathMethod.MathAdd.add;
由于add是静态方法,我们在别的包内可以直接调用它,只需要静态import 包。
e: Package Ballcal
import static MathMethod.MathAdd.*;
class Ball
{
double diameter;
Ball(float dia){diameter= dia};
addBall(Ball two)
{
add(this, two);
}
}
由于使用了import static添加包,可以实现对add方法的直接访问。(注意添加包的路径,一定是该方法根目录以上的目录)