1、this关键字的含义
- this是一个关键字翻译为:这个
- this是一个引用,this是一个变量,this变量中保存了内存地址指向了自身,this存储在JVM堆内存java对象内部。
- 创建100个java对象,每一个对象,都有this,也就是说100个不同的this。(可以是同一个类)也就是说new一次就会产生一个java对象,且产生的对象的地址不同,因此他们的this所存储的内容也不同。
- ==每个非static方法中都隐含着一个this指针,指向当前正在调用该方法的对象。==构造方法和实例方法都含有this指针。
图中所说的,c1、c2就是this是指它们的内容是一致的。并不是说明他们就是完全等效,因为毕竟一个在堆内存,一个在栈内存中。
2、实例方法
概念:没有static关键字的方法被称为“实例方法”。当一个行为/动作执行的过程当中是需要对象参与的,那么这个方法一定要定义为“实例方法”。
例如:顾客购物,如果在顾客这个类中发生了购物这个动作(方法),由于购物这个方法需要顾客这个对象去执行的,因此这个购物方法一定是实例方法,不需要加static关键字。因此大多数方法都是第一位实例方法,一般一个行为或者一个动作在发生时都需要对象的参与。但是也有例外,例如:多数的工具类中的方法都是静态方法,因为工具类就是为了方便编程,为了方便方法的调用,自然是不需要去新建对象。
疑问:那这个动作需要对象去执行,这个对象一定指的是当前这个类所实例化的对象吗?对的。
示例:
//测试类
public class CustomerTest {
public static void main(String[] args) {
Customer c1 = new Customer();
Customer c2 = new Customer();
c1.name = "liSi";
c2.name = "zhangSan";
//使用引用.进行调用
c1.goShopping();
c2.goShopping();
}
}
//顾客类
public class Customer {
String name;
public Customer() {
}
//以下定义示例方法,因为每一个顾客在真正的购物的时候,最终的结果是不同的。所以这个动作在完成的时候必须有对象的参与。
public void goShopping(){
//当zhangSan在购物时,输出zhangSan在购物。
//当liSi在购物时,输出liSi在购物.
//省略写法 System.out.println(name + "去购物");
//name是实例变量,因此需要用引用.进行访问。
System.out.println(this.name + "去购物");
}
}
注意:
- 实例方法一定要通过
引用.
的方法进行调用
- this可以出现在“实例方法”当中,this指向当前正在执行的这个动作的对象。(this代表当前对象)
- this在多数情况下是可以省略的。
- 带有static关键字的方法中是不能出现this的,因为static方法是不需要创建对象来调用函数的,直接通过
类名.
的方式。并且静态方法是在类加载时就已经进行了初始化了,此时main()函数尚且未执行,更不要说对象的创建了,因此系统在运行到类加载时,this指针尚未建立,去调用一个尚未存在的this指针当然会报错。
- 带有static关键字的方法中不能直接访问实例变量和实例方法。因为实例变量和实例方法都需要对象的存在。而static中是没有this的。也就是说当前对象不存在,自然也是无法访问当前对象的实例变量和实例方法。
为何在static方法中实例化对象之后,便能通过引用.的方法进行调用?存疑
3、什么时候this.不能省
用来区分进一步变量和实例变量时不能省略。
例如:
public class Account {
//账号
private String achno;
//余额
private double balance;
//无参数构造器
public void setAchno(String achno) {
this.achno = achno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
第9行、17行代码均不能省略。我们可以看见形参中的局部变量与成员变量同名了,此时构造方法中不使用this.加以修饰的话,那么构造方法中的ahno则均是局部变量,但是当我们加上了this之后,这个this就表示我们当前正在调用这个方法的对象了,通过对象是可以对实例变量进行访问的,因此此时的“=”的左边的achno就变成了成员变量了。
4、this()的用法
this()可以使用在构造方法中,通过当前构造方法去调用其他的构造方法。(构造方法是含有this指针的,因此可以使用this())
语法格式是:this(实参);
实例:
//Date类
public class Date {
private int year;
private int mouth;
private int day;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMouth() {
return mouth;
}
public void setMouth(int mouth) {
this.mouth = mouth;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
//无参数构造器
// 需求:当调用该无参数够构造器时,要求默认创建的日期是1970-7-1
public Date() {
this.year = 1970;
this.mouth = 7;
this.day = 1;
}
//有参数构造器
public Date(int year, int mouth, int day) {
this.year = year;
this.mouth = mouth;
this.day = day;
}
public void printf(){
System.out.println(this.year + "年" + this.mouth + "月" + this.day + "日");
}
}
//测试类
public class ThisTest {
public static void main(String[] args) {
Date t = new Date();
Date t1 = new Date(2008,1,1);
t.printf();
t1.printf();
}
}
观察在Data类中,两个构造器出现了功能重叠的部分,因此可以采用一个构造器调用另一个构造器的方法来优化程序,即使用this()函数。
改进如下:
public Date() {
new Date(1970,7,1);
}
若采用这种方法,虽然也能完成初始的赋值,但是重新创建了一个新的对象。因为在main方法中已经创建了一个对象了,若不想创建新的对象,那么就使用this()的方法改写。如下:
public Date() {
this(1970,1,1);//只能出现在构造方法的第一行。
}
注意:
this()只能出现在该构造方法的第一行,也就是说一个构造方法想通过this()语法来调用其他的构造方法,只能使用一次。
5、实例方法与类方法间的相互调用
5.1、实例方法调用类方法
带有static的方法其实既可以采用类名进行访问,也可以采用引用的方式进行访问,但是即使是采用引用的方式进行访问,实际上执行的时候和引用指向的对象无关,在使用IDEA进行开发时,使用引用的方法去访问带有static的方法,程序会出现警告。所以带有static的方法尽量还是使用“类名.”的方式。
实例1:
public class Test02 {
public static void main(String[] args) {
Test02 t = new Test02();
t.doSome();
//引用是空
t = null;
t.doSome();//并不会出现空指针异常。
}
public static void doSome(){
System.out.println("doSome");
}
}
分析:当给引用赋null时,再去调用方法,并未出现空指针异常错误,这更加充分的说明了,实际上执行与引用指向的对象无关。
总结:实例方法调用类方法(静态方法):1、类名. 2、引用.(实际上本身与对象无关,不推荐)
5.2、关于相互调用的总结
实例:
public class Test01 {
//没有static的变量
int i = 10;
//不带static的方法
public void doOther(){
System.out.println("doOther");
}
//带有static的方法
public static void doSome(){
System.out.println("doSome");
}
public static void method01(){
//调用doSome
//完整的方法调用
Test01.doSome();
//省略的方法调用
doSome();
//调用doOther
//完整的方法调用
Test01 t1 = new Test01();//因为static函数中没有this,所以要重新开辟一个对象。
t1.doOther();
//省略的方法调用
//访问 i
//完整的方法访问
System.out.println(t1.i);
//省略的方法访问
}
public void method02(){
//调用doSome
//完整的方法调用
Test01.doSome();
//省略的方法调用
doSome();//此处是省略了this指针,并不是省略了Test01类名。
//调用doOther
//完整的方法调用
this.doOther();//当前所在的方法没有static,含有this,因此可以这样写。
//省略的方法调用
doOther();
//访问 i
//完整的方法访问
System.out.println(this.i);
//省略的方法访问
System.out.println(i);
}
public static void main(String[] args) {
//要求在这里编写程序调用method01
//使用完整的方法
Test01.method01();
//使用省略的方法
method01();
//要求在这里编写程序调用method02
//使用完整的方法
Test01 t1 = new Test01();
t1.method02();
//使用省略的方法
}
}
总结:
实例方法调用实例方法:若当前类中已经有新建的对象之后,可以直接通过==
this.
或者引用.
==进行调用访问。实例方法调用静态方法:
类名.
。静态方法调用实例方法:无论之间是否有新建对象,都需要重新新建对象,再通过==
引用.
==的方式进行调用,不能直接访问