`
f543711700
  • 浏览: 326997 次
  • 性别: 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 --this变量

    在上述代码中,`this.name`用于区分局部变量`name`和成员变量`name`,确保我们是在设置或访问实例字段,而不是覆盖方法内部的局部变量。 `this`还可以在构造器中调用其他构造器,这是一种称为构造器链的技术,可以...

    java 如何访问同名的方法或变量

    为了理解如何有效地访问这些同名的成员,我们需要深入理解Java的命名规则、作用域、访问修饰符以及多态性。以下是一些关键知识点: 1. **命名规则**:Java中的标识符(包括方法名和变量名)必须以字母、下划线(_)...

    Java中this关键字使用小结

    总的来说,`this` 关键字是 Java 中用于表示对象实例自身的一个关键字,它帮助我们访问成员变量、区分同名变量、在构造器间传递参数以及实现链式方法调用。理解并熟练运用 `this` 关键字对于编写清晰、高效的 Java ...

    java 匿名内部类的使用规范

    本篇文章将深入探讨Java匿名内部类的使用规范,帮助你更好地理解和应用这一特性。 首先,理解匿名内部类的基本概念。匿名内部类没有名字,它不能被其他类直接引用,但可以作为局部变量、成员变量或者方法参数。它...

    java中的this关键字

    // 使用this访问成员变量x,将局部变量x的值赋给成员变量x } } ``` 2. **构造函数中的`this`**:在构造函数中,`this`可以用来调用同一类中的其他构造函数。这有助于代码重用和保持一致性。例如: ```java ...

    java this关键字的使用

    初学者在学习Java时,理解和掌握`this`关键字的使用是至关重要的,因为它可以帮助我们更好地编写和理解类与对象之间的关系。下面我们将深入探讨`this`关键字的几个主要用法。 1. **成员变量的访问** 当类中的局部...

    JAVA内部类总结

    根据描述,本文将对Java内部类进行深入总结,包括内部类的不同类型、特点及其应用场景。 #### 一、内部类的基本概念 内部类分为四类:非静态成员内部类、静态成员内部类、局部内部类和匿名内部类。接下来将逐一...

    Java零基础-this关键字.md

    通过本文的学习,初学者能够深入理解`this`关键字的作用,掌握其在实例方法、构造方法及内部类中的使用技巧,并能够明确区分`this`与静态成员、方法参数及方法重载之间的关系。 #### 什么是`this`关键字? 在Java...

    Java内部类总结

    - **成员内部类**:这种类型的内部类是定义在外部类的一个成员位置上,它可以访问外部类的所有成员变量和方法。 - **静态内部类**:也称为静态嵌套类,这种内部类通过`static`关键字修饰,不能直接访问外部类的实例...

    java中带有this关键字的程序内存分析

    总结来说,`this`关键字在Java程序中用于明确地引用当前对象的实例变量或方法,帮助我们区分局部变量和实例变量。而Java的内存分配机制则确保了对象和其实例变量在堆内存中的正确存储和管理。理解`this`的关键字用法...

    java中的static变量,方法,代码块

    这意味着在静态方法内部,无法使用`this`或`super`关键字,也无法直接访问类的实例变量和实例方法,原因在于静态方法并不依赖于任何具体实例的存在。静态方法通常用于执行与类本身相关、而不依赖于任何特定实例状态...

    Java面向对象(进阶)- this关键字的使用

    当在方法或构造器内部需要访问类的成员变量或方法时,可以使用`this`关键字。虽然通常情况下可以省略`this`,但在变量名与形参名相同的情况下,`this`是必要的,以区分局部变量和成员变量。例如: ```java public...

    关于Java变量的可见性问题Java开发Java经验技巧共

    此外,了解变量可见性也有助于理解和解决多线程环境中的并发问题,如通过使用volatile关键字确保多线程环境下的变量可见性。 总的来说,Java变量的可见性是编程实践中不可或缺的一部分,熟练掌握这一概念能够帮助...

    this 引用句柄例子大解析

    // 使用this访问成员变量 } // 构造器2 public Person() { this("无名氏"); // 使用this调用构造器1 } // 修改名字的方法 public void setName(String newName) { this.name = newName; // 再次使用...

    Java 内部类的实现

    如上例所示,在`Inner`类的`print`方法中,通过`this.index`可以访问`Inner`类自己的成员变量`index`,而`Outer.this.index`则可以访问外部类`Outer`的成员变量`index`。 #### 总结 通过上述分析,我们可以看到...

    Java基础教程之对象的方法与数据成员

    本教程将深入探讨对象的方法与数据成员的概念,这对于理解和编写Java应用程序至关重要。 首先,数据成员是对象的状态,它们存储了关于对象的信息。在上述示例中,`Human` 类具有一个名为 `height` 的数据成员,它...

    Java关键字之this用法详解.rar

    在Java编程语言中,"this"是一个非常关键的引用关键字,它主要用来引用当前对象的实例变量,并在方法、构造器或初始化块中使用。理解并熟练运用"this"是成为一名合格的Java开发者的重要一步。下面我们将深入探讨...

    JAVA内部类

    ### JAVA内部类详解 #### 引言 自Java1.1版本起,内部类的引入为面向对象编程提供了更为灵活的封装机制。然而,如同所有强大的特性,内部类的不当使用可能导致代码复杂度的增加,甚至产生维护上的困难。本文旨在...

    this 和 super

    - 当在一个类的方法内部访问成员变量时,如果方法参数的名字与成员变量的名字相同,则可以使用“this”关键字来区分两者。例如: ```java public class DemoThis { private String name; public void setName...

Global site tag (gtag.js) - Google Analytics