Thinking In Java中说,this关键字是对"调用这个方法和属性的对象的引用",那么按照这个逻辑去理解
public class A{
publi int i = 0;
public void test(){
System.out.print(this.i);
}}public class B extends A{
public int i =1; public static void main(String[] args){
A a = new B();
a.test();
}}按照这样理解话,a对象调用父类的test方法时,this指的就该是a对象的i,也就是1,但这显然是错误的。我的理解错误在哪呢?
public class A{
publi int i = 0;
public void test(){
System.out.print(this.i);
}}public class B extends A{
public int i =1; public static void main(String[] args){
A a = new B();
a.test();
}}按照这样理解话,a对象调用父类的test方法时,this指的就该是a对象的i,也就是1,但这显然是错误的。我的理解错误在哪呢?
a.test();
你这是new B(); this自然代表B类的对象
去看下多态
A a = new B();
然后调用a.test();方法
B并没有重写test();方法
所以调用的还是A中的test();方法
这样就向上转移到父类A中
执行A中的test();方法
test();方法执行System.out.print(this.i);
注意~这个时候执行代码处于A类中所以i是0
|
B| int i = 1;
| -------------------
| | int i = 0;
| |
|A|------------------
| | test();
| |------------------
|-------------------- A a = new B();
这个时候的a只是下面属于A的部分。
不知道这样是不是对你有用。
this指向当前类的实例,这个当前类指的是该this所处的那个类(这里就是A类)
因为是调用的A类的方法,所以this指的是A的成员变量
this指向当前类的实例,这个当前类指的是该this所处的那个类(这里就是A类)
publi int i = 0;
public void test(){
System.out.print(this.i);
} } public class B extends A{ public int i =1; public static void main(String[] args){
A a = new B(); //这里是一个A类的引用,指向的是A类的子类B的一个对象
a.test(); //可能涉及多态,但要注意,这里a就是一个A类型的引用,B类并没有覆盖父类的test()方法,所以还是调用父类A的方法test,这样以来,肯定是i=0的了,哪有这么复杂
} }
public int i = 0;
public void test(){
System.out.print(this.i);
} } public class B extends A{ public int i =1;
public void test() {//增加此方法,重写
System.out.print(i);
} public static void main(String[] args){
A a = new B();
a.test();
} }
如果像这种情况一般都是要在子类重载父的方法,也就是说在B类中应该定义一个test()方法。
是自己猜的吧, 实际上未必如你所说, 看看以下代码, 按照你的说法是test()是在A类中的,所以 test()内部的 this 就是指A类, 如果是这样,那么你猜一下, 执行this.getI() 返回的值是什么? 是"0"吗? 答案应该是"1"!
现在问题来了,为什么 this.i 返回是0, this.getI() 返回是1呢, 我不是专家,我不敢乱猜,等高手来解释吧.
class A { public int i = 0; public void test() {
System.out.print(this.getI());
} public int getI() {
return i;
} public void setI(int i) {
this.i = i;
}}class B extends A { public int i = 1; public int getI() {
return i;
} public void setI(int i) {
this.i = i;
}}
系统在栈中为a 的引用分配一块内存,指向堆中的B的对象的实例,由于是父类的对象指向子类的引用,但是子类并没有重写父类的方法test();所以并没有多态存在,子类的成员变量 i = 1 父类是不能够访问的;当系统调用test()方法是自然不会有多态产生,也就不会访问子类的成员变量i.
在运行时,记住,是运行时,不是编译时,JAVA多态的三大要点:
1、实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的。
2、静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。
3、成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。
这里我们关注上面的第三点!
为什么运行结果是“0”呢,因为在test()方法中调用了成员变量。这里的this.i,this指的是B类型的对象,这大家都赞同,但是这个B类型对象的引用变量a却是声明为A类型的,所以,这里的this.i的成员变量i是与A类型中的成员变量i绑定在一起的。所以结果是“0”。
关于A a = new B();a.test(); 这里相信很多人都被束缚了,这和new B().test()有什么区别?没有区别。a这个引用这是用来控制new B()的行为而已。22楼的兄弟的说法我认为是恰当的,test()方法在父类,而父类的方法是无法访问子类属性的。所以i=0。而父类当中的this也并不指的是当前类的实例,还是Thinking In Java当中的那句话,谁调用这个方法this就指谁。
大家可以在A类的test()方法中打印this.getClass(),得到的结果是B类,而并不是A类。
这种情况也只会在继承碰到,如果A和B不是继承关系,那不可能一个对象去调用A中的方法结果是得到自己的属性,首先在A种定义这个不属于自己的属性的时候就会有错。
所以我姑且认为
public void test(){
System.out.print(this.i);
} 这个this.i在A中,所以是指的A的i....过几天再来看更微妙的答案
A a = new A();
A a = new B();
B a = new B();
B a = new A(); //这条当然是不行的
也在子类里重写了test方法
甚至把this也去掉了直接打i发现:
LZ这个例子貌似不是阐述this关键字的好例子
子类中有个父类对象super
a 引用动态绑定的是 B
a.test()相当于 在子类中调用 super.test()
这时的 this 指的是 super 也就是 A对象所以i是A中的属性i
B类中的i=1
B继承A A类中都为public 所以全部继承
注:A类有public int i = 0;
B类有public int i = 1;
B继承A 发生覆盖
这时可以理解B类为
public class B(
public int i = 0;
public void test(){
System.out.print(this.i);
} )
这时this指向的i就是0啦
public void test(){
super.test();
// System.out.print(this.i);
}
看一下输出也许有助于理解
在父类中this.i调用的是父类本身定义的变量i,即当前类中的变量i
而getI()中调用的i是当前对象的变量值,即被子类覆盖的i值
A a = new B();后
A:i(0) <==> B: super.i(0)
A: this.i(0) <==> B: super.i(0)
B: this.i(1) <==> B: i(1)
无论A a = new B(); 还是 B a = new B();
输出i都是0, 可见是调用了A的test(),里面的this指向A如果B重写test();
无论A a = new B(); 还是 B a = new B();
输出i都是1
当A a = new B();时,多态
当B a = new B();时,就直接调用自己的test();不知道这样理解对不对
private int i=0;
public void test() {
System.out.println(this.i); //this.i是引用该类中的成员变量i
}
}
public class B extends A {
private int i=1; public static void main(String[] args) {
A a = new B(); // 首先new出一个B类的实例,然后向上转型为A类,然后执行A类的test()方法;不过B类的继承A类的时候没有重写A类的test()方法,所以 a.test()依然是调用A类的test()方法.因此结果是 0.
a.test(); }}
this指的是自身, super指的是父类(猜测一下:单继承或许就是为了这个super的便于管理)
如楼主代码, 在main方法执行过程中, A a = new B(); 虽然只在堆中new了一个B的实例对象, 但是, 这个对象其实不仅有一个this的引用指向自身, 还有一个super的引用指向一个父类的实例. 这个时候, 我们就可以比较容易理解多态以及楼主的问题了, 在计算机领域, 优先级永远都是局部大于全局, this中有, 就用this, this中没有就找super, super本身还有super, 直到找到为止. 对于楼主的问题, 由于B类没有重写test方法, 所以使用的是super引用指向的对象的方法, 那么结果是什么, 可向而知.
对于20楼朋友提出的getI()方法的现象, 还用解释了吗? this指向的对象(也就是自身)所属的类已经重写了getI()方法, 局部大于全局, 执行this指向的对象的方法, 结果不是一目了然吗?
改成这个:System.out.print(this.getClass().getName());看看,this指向的是B!但是为什么第一句是0,我不知道。
在子类中你用this.i指的是子类的i,你想要在子类中调用父类的i,super.i
父类对象实例化了子类B ,如果子类B中没有重写或重载test方法,那a.test()方法调用的是A类的test方法 i是0啊
this.i 调用当前类的成员变量
当父类的引用指向子类的对象时,当前的this当然指向的是父类中的i
输出0