区别类方法、实例方法和字段的调用本例根据一个实例来说明类方法和实例方法调用的区别,以及不同修饰符下的
区别类方法、实例方法和字段的调用
本例根据一个实例来说明类方法和实例方法调用的区别,以及不同修饰符下的属性调用的区别,并对这种区别作出解释。
父类定义:
Parent obj1 = new Son(); //一个本指向一个子类对象的句柄强行转换为Parent obj1.sayHello(); //static被定义在类栈的静态区域(它是在加载JVM时候已经编译了),所以指向父类栈中 obj1.sayBye(); //而一般方法不会预编译,但他跟类定义跑,在new Son()的时候的动态连接Son类栈中的sayBye()方法。
同意,不过只是连接,应该并非编译了方法栈地址,而这个操作应该是在类定义的时候编译的。
恩,根据引用所指对象的类型信息来动态调用方法,这应该就是所谓连接吧。
我的理解是,当Parent类被加载进入JVM的时候,静态方法的地址绑定到类的方法表中,静态字段name作为类变量、常量age和birth作为编译时常量存入方法区,编译之后他们的地址和值不再改变,故曰静态绑定。
而引用是以指向对象的指针存在的,在执行期间,父类的引用有可能指向不同子类的实例方法(也就是多态),这种在执行期间才确定具体方法的机制叫动态绑定。
不过,不知楼上所讲虚拟方法指的是什么呢? 3 楼 C_J 2009-04-19 我说的虚拟方法是指
virtual(C++) abstract(JAVA)
不过 ,你说到“引用”,我一直归纳为“指针”,但指针这个词总有点变扭,我暂称“句柄”
涉及到“多态”,我想势必就会涉及到
虚拟方法,我不知道JAVA有没有像C++那种“虚表”的 机制。
另外static方法与一般方法存储的类栈区域肯定是
有区别的,你不能笼统的归纳到引用“类的方法表”中。 4 楼 idealab 2009-04-19 1、Java中开发人员可操作的只有引用,不能直接操作指针,但是在底层实现引用的却是指针:JVM会将指向已加载类的引用由“符号引用(该类的全限名称)”替换为指针。类似的,底层对方法的调用也用到指针。
2、Java对多态的实现是依靠跟C++中“虚表”类似的方法表。同样的,方法表中数组元素是指向超类、接口的方法的指针,也通过偏移量来,但是由于Java编译期间的方法只是用符号代替的,故只有运行时方法被第一次调用之后,方法表中的元素才能够获得所指向的方法地址,进而指向它。
3、类方法与实例方法的存储是否有区别我也还不太明了,需要进一步研究。望与楼上共同进步~ 5 楼 C_J 2009-04-20 引用Java中开发人员可操作的只有引用
这句话有什么根据么? 我所知道C++说引用的特性是,他是对象地址(当然还包括基本数据类型)的副本,而这个副本,我的理解是竟然是副本,就没有去更改的理由,因为你改的不是“原件”。
对JAVA中的可变类,我理解的是直接操作指针的,如参数传递进去的可变类对象,是可以直接被更改的。
对于不可变类,上述更改就无效了,因为不可变类操作的是指针的副本,也就是“引用”了。
当然,大家共勉,共同进步! 6 楼 idealab 2009-04-20 Java中开发人员不可以操作指针这是大学课程中就讲过的。引用在JVM中直接就是指向对象的指针,而不是你所理解的C++中对象的副本。正因为此,通过引用是可以找到对象并其做更改。
关于参数传递:如果对象作为参数传递给方法,则传递的是引用的“拷贝”,但是利用该拷贝调用方法时,却调用了所指向的实际对象的方法,因此可以更改对象,详细信息请参考:http://www.iteye.com/topic/4189#
个人感觉C_J总是根据C++经验去理解Java,Java中很多事情是没那么复杂的。比如
对JAVA中的可变类,我理解的是直接操作指针的,如参数传递进去的可变类对象,是可以直接被更改的。
对于不可变类,上述更改就无效了,因为不可变类操作的是指针的副本,也就是“引用”了。
java中可变类和不可变类通过访问控制修饰符final来实现的,参考这里
7 楼 C_J 2009-04-22 我觉得我们沟通还是没那么充分
引用 public void call(Test t) {
Test t2 = new Test();
t2.setName("cba');
t.setName("abc");
t = t2 ;
}
public static void main(String[] arg) {
Test obj = new Test();
call (obj) ;
System.out.println("obj"+obj.getName());
}
这位大哥的Test没有告诉我是不可变类和可变类(暂认为是可变类)
所以操作的是指针,传递的也可以认为是指针
竟然是
可变类,所以 t.setName("abc"); 是行得通的,因为他们指向的是
同一个地址。
但还是用C++的方式来理解的话
t和obj都是“指针”(目前产生了2个指针),目前指向了同一个地址 然后 t=t2,这里只改变了 t 这个
“指针”,并没有改变
“指针内容”,所以作者说 并没有影响“obj”,
所以打出的是abc 其实final就有点“引用”的味道了。用C++的指针概念来理解JAVA对象也不错嘛
哎,其实是经历了一次惨痛的面试!!
8 楼 idealab 2009-04-22 首先希望共患难的兄弟能够尽早振作起来,找工作十有八九不如意,心态要好才能越来越坚强,祝早日找到满意的工作!
这个问题不在于Test是可变类还是不可变的,而是关于以类实例为参数的方法倒底传入了什么!在java中,传入的实际是引用的拷贝,类似于你以前说的“副本”,这就意味着call()方法里的t“复制”了obj,和obj指向Test的同一个实例(也就是实际对象)。但同时,我在贴子最开始有个引用:
引用当JVM调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当JVM调用一个实例方法是,它会基于实际对象的类(只能在运行时得知)来选择所调用的方法。
这样看,无论是obj.setName("abc");还是t.setName("abc");其实都调用了实际对象的那个实例方法。但是t=t2;这句便只是让t具有了指向t2的指针。 9 楼 C_J 2009-04-22 哈哈 首先感谢你的祝福
引用这个问题不在于Test是可变类还是不可变的
不同意
你可以试试传个
String 对象进去
引用这就意味着call()方法里的t“复制”了obj,和obj指向Test的同一个实例(也就是实际对象)。
同意
这里的复制,不管在C++也好,JAVA也好都是“参数拷贝”。这句话咱达成了共识。
引用无论是obj.setName("abc");还是t.setName("abc");其实都调用了实际对象的那个实例方法
同意
因为都指向了同一个地址
10 楼 xiasheng 2009-04-28 是不是一般方法,当类被加载的时候已经被编译,但并未连结,页静态方法则是在类加载时就已经被连结了???/ 11 楼 C_J 2009-04-28 xiasheng 写道是不是一般方法,当类被加载的时候已经被编译,但并未连结,页静态方法则是在类加载时就已经被连结了???/
我的理解:是的
所有方法都被编译
静态在加载就连接
一般在new操作时进行连接