一、调用属性
观察如下代码:
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(); } }