一. this 关键字
this指向自己的引用, 即当前方法所在的对象. 它的一个主要的作用是将自己这个对象当作参数, 传送给别的对象中的方法.
用法一: 当成员变量与局部变量重名时, 用this来做区分
/***
* 当成员变量与局部变量重名时, 用this区分
* this表示当前对象的变量
* @author hlwyf_000
*
*/
public class TestThis {
int age;
public void changeAge(int age){
this.age = age;
}
public static void main(String[] args){
TestThis testThis = new TestThis();
testThis.age = 30;
testThis.changeAge(45);
System.out.println(testThis.age);
}
}
运行结果: 45
在下一代码中, 如果不用this.age而用age, 那么, 将无法区分怎么赋值, 出现自己赋值给自己的情况.
而使用了this.age, this表示当前对象的, 所以this.age就是当前对象的age, 从而区分开来.
public void changeAge(int age){
this.age = age;
}
用法二: 将自身作为一个对象传递给其他方法
看上去比较乱, 仔细理解里面的运作过程.
设计模式: 使用者模式
1 /***
2 * 把自身对象作为一个参数传递给其他方法
3 * @author hlwyf_000
4 *
5 */
6 public class ThstThis2 {
7 public static void main(String[] args){
8 A a = new A();
9 }
10 }
11
12 class A{
13 public A(){
14 B b = new B(this); //这里的this表示A对象,将整个A给传进去了!在B中就可以使用A的方法
15 b.print();
16 }
17 public void printA(){
18 System.out.println("print of A!");
19 }
20 }
21
22 class B{
23 A a;
24 public B(A a){
25 this.a = a; //这里的this表示B对象
26 }
27 public void print(){
28 System.out.println("A");
29 this.a.printA(); //这里也可以使用 a.printA();
30 }
31
32 }
运行结果:
问题分析: 在class B 中去掉 A a; 将会如何? 代码如下:
将class B修改为:
1 class B{
2 public B(A a){
3 a.printA();
4 }
5 public void print(){
6 System.out.println("A");
7 //a.printA();
8 }
9
10 }
运行结果:
正常!
去掉注释:
class B{
public B(A a){
a.printA();
}
public void print(){
System.out.println("A");
a.printA();
}
}
结果报错! 为什么会这样呢?
分析: public B(A a) 中的a是形参, 形参分配在局部变量那里, 放在内存的栈区, 当构造函数这个方法执行完毕之后, 它的生命周期就消失掉了, 那么内存就释放了.因此在下面如果再使用形参a, 由于在内存已经不存在了, 所以无法调用, 编译器报错! 而解决这一问题的方法就是如上面运行正确的代码所示, 即在类里面定义一个成员变量, 再把形参的值赋值给这个成员变量 (注意: 类里面的成员变量类型可以是 类, 数组, 接口, 在上一份笔记中有提及), 而成员变量的消失, 要等垃圾回收器, 这种情况下是内存已满的时候, 一般很少发生.
正确代码如下:
class B{
A a; //定义成员变量
public B(A a){
a.printA();
}
public void print(){
System.out.println("A");
this.a.printA();
}
}
View Code
二.类变量与实例变量的区别
注意: static属于类的, 不是属于对象的! 不是成员属性, 在内存中属于静态区!
/**易错知识点:
public class Person {
int age;
static String classer;
}
public class Mathod {
}
在同一个文件中, 不能定义两个public类, 只能定义一个public类, 在Mathod类中, 去掉public就正确.
****/
代码举例分析:
1 public class Person {
2 int age; //成员变量, 在内存中放在堆区里
3 static String classer; //类变量, 在内存中放在静态区里
4 }
5
6 class Mathod {
7 public static void main(String args){
8 //定义两个Person类对象
9 Person person1 = new Person();
10 Person person2 = new Person();
11
12 person1.age = 1;
13 person2.age = 2;
14
15 person1.classer = "ABC!";
16 System.out.println(person1.classer);
17 System.out.println(person2.classer);
18 }
19
20 }
初步编译, 无法编译通过, 寻找原因, 发现:
1. 文件名必须与public类名相同.
2. 编译器从public类的main函数入口进入, 如果没有main函数, 则不予编译. 那么, 上述代码中犯了这些错误.
修改如下:
1 class Person {
2 int age; //成员变量, 在内存中放在堆区里
3 static String classer; //类变量, 在内存中放在静态区里
4 }
5
6 public class Mathod {
7 public static void main(String[] args){
8 //定义两个Person类对象
9 Person person1 = new Person();
10 Person person2 = new Person();
11
12 person1.age = 1;
13 person2.age = 2;
14
15 person1.classer = "ABC!";
16 System.out.println(person1.classer);
17 System.out.println(person2.classer);
18 }
19
20 }
编译结果:
从这里看出, 在16行和17行中, 输出的内容一样. 因为, classer放在内存的静态区里, 对于在栈区的局部变量person1和person2都可以调用!
对于这个代码的内存分配图如下:
这就是类变量和实例变量的区别!
对象是通过类来创建的, 因此创建对象时需要加载相应的类. 一个类可以创建多个对象, 每个对象都有属于自己的实体.
区别:
1.类变量(如上面的classer)在类加载时分配内存, 实例变量(如上面的age)是在创建对象时分配内存, 类变量在程序退出时释放内存, 对象不存在, 实例变量就不存在.
2.类变量被所有对象共享, 即同一类的对象共享此类的类变量, 实例变量为每个变量独有, 操作自己的实例变量不会影响其他对象.
3.类变量一般通过类名来调用.
【学习笔记】java面向对象程序设计2