this关键字

本文介绍了Java中构造方法的使用及其与this关键字的关系,包括如何通过this关键字正确初始化类属性,调用类中的方法及构造方法之间的调用,同时展示了this如何表示当前对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、调用属性

观察如下代码:

class Book {
	private String title;
	private double price;

	public Book(String t, double p) {
		title = t;
		price = p;
	}

	// setter、getter略
	public String getInfo() {
		return "书名:" + title + ",价格:" + price;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Book book = new Book("Java开发", 98.3);
		System.out.println(book.getInfo());
	}
}

但是下面来观察如下一点:

public Book(String t, double p) {
		title = t;
		price = p;
	}

此处使用的是一个构造方法,而这个构造方法的主要功能是为title与price两个属性初始化使用,可是有一点不好,就是方法中的参数名称不好。既然现在在构造方法中的参数目的是为了类中的属性初始化,那么最好的方式是直接将参数设置为与属性名称保持一致。

public Book(String title, double price) {
		title = title;
		price = price;
	}

修改为以上的形式参数的作用就算是合理了,但是发现最终在构造方法传递的参数内容并没有传递到属性之中。

在Java程序里面它是以“{}”为界限,如果现在属性名称与参数名称出现了重名的情况下,如果没有加入任何的限制,指的都是最近的“{}”内的变量名称。所以在这种情况下,为了可以明确的找到要访问的变量属于类中的属性的时候,需要在变量前加上this,这样就可以准确的进行属性的标记。

class Book {
	private String title;
	private double price;

	public Book(String title, double price) {
		this.title = title;
		this.price = price;
	}

	// setter、getter略
	public String getInfo() {
		return "书名:" + this.title + ",价格:" + this.price;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Book book = new Book("Java开发", 98.3);
		System.out.println(book.getInfo());
	}
}

在以后的程序开发之中,只要是访问类中的属性前面必须加上“this”。


二、调用方法

通过之前的代码发现,所谓的this实际上指的就是明确的标记本类的结构,而在一个类里面除了成员之外,还包含有方法(普通方法、构造方法),利用this可以调用本类的普通方法或构造。

1、调用普通方法

class Book {
	private String title;
	private double price;

	public Book(String title, double price) {
		this.title = title;
		this.price = price;
	}

	public void print() {
		System.out.println("*****");
	}

	// setter、getter略
	public String getInfo() {
		this.print();// 调用本类方法
		return "书名:" + this.title + ",价格:" + this.price;
	}
}

调用普通方法的时候是否在方法前加入“this”,并没有一个明确的要求,即使不加this,也表示本类调用的方法,但是为了代码的严谨性,一定要加上this。

在一个类里面除了普通方法之外,还会包含构造方法。这个时候表示多个构造方法之间要进行互相调用,而使用的形式“this(参数,参数)”。

下面将通过一个简短的代码来分析,为什么需要构造方法间的互相调用?

范例:观察问题

现在定义的Book类里面有三个构造方法,但是要求不管调用哪一个构造方法都要输出一行提示信息“新的Book类对象产生”。

class Book {
	private String title;
	private double price;

	public Book() {
		// 把这句话想象成20行代码
		System.out.println("一个新的Book类对象产生");
	}

	public Book(String title) {
		this.title = title;
		System.out.println("一个新的Book类对象产生");
	}

	public Book(String title, double price) {
		this.title = title;
		this.price = price;
		System.out.println("一个新的Book类对象产生");
	}

	// setter、getter略
	public String getInfo() {
		return "书名:" + this.title + ",价格:" + this.price;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Book book = new Book("Java开发", 98.3);
		System.out.println(book.getInfo());
	}
}

此时代码里面有重复代码,有重复代码就必须想办法消除掉重复代码。

class Book {
	private String title;
	private double price;

	public Book() {
		// 把这句话想象成20行代码
		System.out.println("一个新的Book类对象产生");
	}

	public Book(String title) {
		this();// 调用本类的无参构造
		this.title = title;

	}

	public Book(String title, double price) {
		this(title);// 调用本类的单参构造
		this.price = price;
	}

	// setter、getter略
	public String getInfo() {
		return "书名:" + this.title + ",价格:" + this.price;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Book book = new Book("Java开发", 98.3);
		System.out.println(book.getInfo());
	}
}

虽然以上实现了构造方法间的互相调用,但是此处依然会存在一些限制:

  • 使用“this()”调用构造方法形式的代码只能放在构造方法的首行;
  • 进行构造方法互相调用的时候,一定要保留调用的出口。

范例:观察错误的代码

class Book {
	private String title;
	private double price;

	public Book() {
		// 把这句话想象成20行代码
		this("Hello",56.6);
		System.out.println("一个新的Book类对象产生");
	}

	public Book(String title) {
		this();// 调用本类的无参构造
		this.title = title;

	}

	public Book(String title, double price) {
		this(title);// 调用本类的单参构造
		this.price = price;
	}

	// setter、getter略
	public String getInfo() {
		return "书名:" + this.title + ",价格:" + this.price;
	}
}

此时调用的语句的确是放在了构造方法的首行。但是编译之后就会出现错误提示“构造方法递归调用”。

也就是说在使用“this()”互相调用的时候请至少保留一个构造没有使用this()调用其他构造的情况。

实例:定义一个雇员类(编号、姓名、工资、部门),在这个类里面提供四个构造方法:

· 无参构造:编号为0,姓名为无名氏,工资为0.0,部门设置为“未定”;

· 单参构造:传递编号,姓名为临时工,工资为800.0,部门设置为后勤;

· 双参构造:传递编号姓名,工资为2000.0,部门设置为技术部;

· 四参构造:传递编号姓名工资,部门设置为“未定”;

实现方式一:按照传统的风格实现

class Emp {
	private int empno;
	private String ename;
	private double sal;
	private String dept;

	public Emp() {
		this.empno = 0;
		this.ename = "无名氏";
		this.sal = 0.0;
		this.dept = "未定";
	}

	public Emp(int empno) {
		this.empno = empno;
		this.ename = "临时工";
		this.sal = 800.0;
		this.dept = "后勤部";

	}

	public Emp(int empno, String ename) {
		this.empno = empno;
		this.ename = ename;
		this.sal = 2000.0;
		this.dept = "技术部";
	}

	public Emp(int empno, String ename, double sal, String dept) {
		this.empno = empno;
		this.ename = ename;
		this.sal = sal;
		this.dept = dept;
	}

	public String getInfo() {
		return "雇员编号:" + this.empno + ",姓名:" + this.ename + ",工资:" + this.sal + ",部门:" + this.dept;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Emp ea = new Emp();
		Emp eb = new Emp(7392);
		Emp ec = new Emp(2132, "Alean");
		Emp ed = new Emp(2342, "Sdef", 4000.0, "财务部");
		System.out.println(ea.getInfo());
		System.out.println(eb.getInfo());
		System.out.println(ec.getInfo());
		System.out.println(ed.getInfo());
	}
}

虽然以上代码实现了功能,但是却存在有重复的操作,很明显,这种代码不符合要求。

实现方式二:利用构造方法简化代码

class Emp {
	private int empno;
	private String ename;
	private double sal;
	private String dept;

	public Emp() {
		this(0, "无名氏", 0.0, "未定");
	}

	public Emp(int empno) {
		this(empno, "临时工", 800.0, "后勤部");
	}

	public Emp(int empno, String ename) {
		this(empno, ename, 2000.0, "技术部");
		this.dept = "技术部";
	}

	public Emp(int empno, String ename, double sal, String dept) {
		this.empno = empno;
		this.ename = ename;
		this.sal = sal;
		this.dept = dept;
	}

	public String getInfo() {
		return "雇员编号:" + this.empno + ",姓名:" + this.ename + ",工资:" + this.sal + ",部门:" + this.dept;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Emp ea = new Emp();
		Emp eb = new Emp(7392);
		Emp ec = new Emp(2132, "Alean");
		Emp ed = new Emp(2342, "Sdef", 4000.0, "财务部");
		System.out.println(ea.getInfo());
		System.out.println(eb.getInfo());
		System.out.println(ec.getInfo());
		System.out.println(ed.getInfo());
	}
}

此时的操作就利用了构造方法间的互相调用解决了代码重复问题。


三、表示当前对象

所谓的当前对象指的就是当前正在调用类中方法的对象。

class Book {
	public void print() {
		// 哪个对象调用了print方法,this对象就自动与该对象保持一致
		// this就是当前调用方法的对象
		System.out.println("this = " + this);
	}

}

public class TestDemo {
	public static void main(String args[]) {
		Book booka = new Book();
		System.out.println("booka = " + booka);
		booka.print();
		Book bookb = new Book();
		System.out.println("bookb = " + bookb);
		bookb.print();
	}
}

在之前出现的“this.属性”实际上就属于当前对象中的属性,一定是堆内存保存的内容。

思考题:观察如下代码的执行

class A {
	private B b;

	public A() {// 2、执行A类的构造
		// 3、为B类对象b实例化
		this.b = new B(this);// 4、this就是temp
		this.b.get();// 7、调用B类的get方法

	}

	public void print() {// 10、调用print输出
		System.out.println("Hello World");
	}
}

class B {
	private A a;

	public B(A a) {// 5、参数a = temp
		this.a = a;// 6、保存A对象
	}

	public void get() {// 8、调用此方法
		this.a.print();// 9、this.a=temp
	}
}

public class TestDemo {
	public static void main(String args[]) {
		// 1、实例化A类对象,要调用A类的无参构造
		A temp = new A();
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值