`
f543711700
  • 浏览: 322909 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

对Java方法内部使用this访问成员变量的深入理解

阅读更多
      一直以为Java里面的this是指当前真实调用对象,今天突然发现不是那么回事。
       有两个注意点:
1、在Java中,直接访问域或静态成员(包括静态方法和静态成员变量)永远都是前期绑定。
2、在Java中,访问方法是后期绑定。
       不过这样容易出现一个疑点:若B类继承A类,A类和B类都包含一个public int i 这样的域,如果在A类中有一个方法通过this访问域,而这个方法的调用者却是B类的对象,那么访问到的域到底是A类中的i还是B类中的i呢?请看代码:
package com.wangf.test.javasuper;

class A {
	
	public int i = 100;
	
	public void p() {
		System.out.println(this.getClass().getName());
		System.out.println(this.i);
	}
}

class B extends A {
	
	public int i = 200; 
	
}

public class Test {

	public static void main(String[] args) {
		B b = new B();
		b.p();
	}
}

打印结果为:
com.wangf.test.javasuper.B
100

明显可看到,此时p()方法的调用者是B类的对象,然后i的值却不是200,而是100;
这就说明了在方法内部通过this访问的域永远都是:方法所在的类的域,我们只需要关注调用的方法是属于哪个类的就行了!
在上例中,虽然是通过B类的对象来调用p()方法,但p()方法是B类通过继承得到的,也就是说此时p()方法是属于A类的,所以访问到的i仍然是A类中的成员i

再来看看当p()方法在B类中被重写后的情况:
package com.wangf.test.javasuper;

class A {
	
	public int i = 100;
	
	public void p() {
		System.out.println(this.getClass().getName());
		System.out.println(this.i);
	}
}

class B extends A {
	
	public int i = 200; 
	
	@Override
	public void p() {
		System.out.println(this.getClass().getName());
		System.out.println(this.i);
	}
}

public class Test {

	public static void main(String[] args) {
		B b = new B();
		b.p();
	}
}

打印结果为:
com.wangf.test.javasuper.B
200

可以看出,此时访问到的i变量,已经是B类中的i变量了,因为此时通过B类的对象调用的p()方法,是B类覆盖过后的,也就是说这个方法已经“属于”B类,所以访问到的i是B类的成员变量i

插播一个当多态发生时的例子:
将Test类修改如为:
public class Test {

	public static void main(String[] args) {
		A a = new B();
		System.out.println(a.i);
		a.p();
	}
}

打印结果为:
100
com.wangf.test.javasuper.B
200
可以看到:直接通过a.i访问的域i和通过a.p()方法访问的域i并不是同一个i,因为在Java中,直接访问域永远都是编译前期绑定,即在编译时则通过引用a的类型A找到了成员变量i,所以这个i等于100;而方法访问则是运行期动态绑定,也就是说在运行时找到引用a的真实类型B,然后访问B的方法p(),所以p()方法此时“属于”B,所以在p()方法中打印出的i等于200


以上的讨论都是指通过this访问域,那么通过this访问方法呢?使用super访问父类的方法呢?
答案是:访问方法永远都会查找真实的调用对象,我们需要关注被调用的方法到底“属于”哪个类!

package com.wangf.test.javasuper;

class A {
	
	public int i = 100;
	
	public void q() {
		System.out.println("A类中的q()");
		System.out.println(this.i);
	}
	
	public void p() {
		System.out.println(this.getClass().getName());
		System.out.println(this.i);
		this.q();
	}
}

class B extends A {
	
	public int i = 200; 
	
//	public void q() {
//		System.out.println("B类中的q()");
//		System.out.println(this.i);
//	}
	
	@Override
	public void p() {
		super.p();
	}
}

public class Test {

	public static void main(String[] args) {
		B b = new B();
		b.p();
	}
}

打印结果为:
com.wangf.test.javasuper.B
100
A类中的q()
100
分析:通过B类的对象调用p()方法,在p()方法内部通过super.p()调用A类的p()方法,所以调用对象是B,此时p()方法是“属于”A的,所以访问到的i等于100,然后再通过this.q()访问q方法,由于B类中此时没有q()方法,所以访问的是A类中的q()方法(继承),所以打印出了这样的结果



若把B类中的注释去掉,可以得到结果如下:
com.wangf.test.javasuper.B
100
B类中的q()
200
因为此时B类已经重写了q()方法,所以访问的是B类中的q()方法,所以i也是B类中的i。

分享到:
评论

相关推荐

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    11.4.3 使用private修饰类的成员变量 318 11.4.4 使用private,然后呢? 320 11.4.5 变量的覆盖 322 11.4.6 使用final修饰成员变量 325 11.4.7 静态成员变量 326 11.4.8 局部变量的修饰符 326 11.4.9 当final...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    11.4.3 使用private修饰类的成员变量 318 11.4.4 使用private,然后呢? 320 11.4.5 变量的覆盖 322 11.4.6 使用final修饰成员变量 325 11.4.7 静态成员变量 326 11.4.8 局部变量的修饰符 326 11.4.9 当final...

    疯狂JAVA讲义

    学生提问:为什么静态内部类实例方法也不能访问外部类的实例属性呢? 207 学生提问:接口里是否能定义内部接口? 208 6.7.3 使用内部类 208 学生提问:既然内部类是外部类的成员,是否可以为外部类定义子类,在...

    java 编程入门思考

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    Java初学者入门教学

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    java联想(中文)

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    JAVA_Thinking in Java

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    Thinking in Java简体中文(全)

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    JAVA基础课程讲义

    属性(field,或者叫成员变量) 59 引用类型 60 类的方法 60 对象的创建和使用 60 构造器(或者叫做构造方法,constructor) 60 垃圾回收机制(Garbage Collection) 63 方法的重载(overload),构造方法的重载 63 this...

    Thinking in Java 中文第四版+习题答案

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    Thinking in java(中文)

    多形性 7.1 上溯造型 7.1.1 为什么要上溯造型 7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重...

    Think in Java(中文版)chm格式

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    ThinkInJava

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    thinkinjava

    7.2 深入理解 7.2.1 方法调用的绑定 7.2.2 产生正确的行为 7.2.3 扩展性 7.3 覆盖与过载 7.4 抽象类和方法 7.5 接口 7.5.1 Java的“多重继承” 7.5.2 通过继承扩展接口 7.5.3 常数分组 7.5.4 初始化接口中的字段 7.6...

    Visual C++ 2005入门经典--源代码及课后练习答案

    第8章 深入理解类 369 8.1 类的析构函数 369 8.1.1 析构函数的概念 369 8.1.2 默认的析构函数 370 8.1.3 析构函数与动态内存分配 372 8.2 实现复制构造函数 375 8.3 在变量之间共享内存 377 8.3.1 ...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    第8章 深入理解类 363 8.1 类析构函数 363 8.1.1 析构函数的概念 363 8.1.2 默认的析构函数 364 8.1.3 析构函数与动态内存分配 366 8.2 实现复制构造函数 369 8.3 在变量之间共享内存 370 8.3.1 定义联合 371...

    Scala程序设计(第2版)

    11.6 无须区分访问方法和字段:统一访问原则 280 11.7 对象层次结构的线性化算法 282 11.8 本章回顾与下一章提要 287 第12章 Scala集合库 288 12.1 通用、可变、不可变、并发以及并行集合 288 12.1.1...

Global site tag (gtag.js) - Google Analytics