【学习笔记】java面向对象基础编程2

一. 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 }

运行结果:

A

print of A!

问题分析: 在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 }

运行结果:

print of A!

A

正常!
去掉注释:

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 }

 

编译结果:

ABC!

ABC!

从这里看出, 在16行和17行中, 输出的内容一样. 因为, classer放在内存的静态区里, 对于在栈区的局部变量person1和person2都可以调用!

对于这个代码的内存分配图如下:

【学习笔记】java面向对象基础编程2

这就是类变量和实例变量的区别!

对象是通过类来创建的, 因此创建对象时需要加载相应的类. 一个类可以创建多个对象, 每个对象都有属于自己的实体.

区别:

1.类变量(如上面的classer)在类加载时分配内存, 实例变量(如上面的age)是在创建对象时分配内存, 类变量在程序退出时释放内存, 对象不存在, 实例变量就不存在.

2.类变量被所有对象共享, 即同一类的对象共享此类的类变量, 实例变量为每个变量独有, 操作自己的实例变量不会影响其他对象.

3.类变量一般通过类名来调用.

 

三. 类方法和实例方法的区别

类加载时,类方法被分配入口地址, 实例方法是在第一个对象创建时被分配入口地址.

类方法一般通过类名来调用.

类方法, 就是加上static

在类方法中不能使用 this 关键字, 因为this代表当前对象, 类方法是在类加载时就存在, 而此时对象还不存在

类方法和类变量被所有的对象共享

class Person {

    int age; //成员变量, 在内存中放在堆区里

    static String  classer; //类变量, 在内存中放在静态区里

    static void classmathod(){

        System.out.println("这是一个类方法");

    } 

    void mathod(){

        System.out.println("这是一个实例方法");

    }

}



public class Mathod {

        public static void main(String[] args){

            //定义两个Person类对象

            Person person1 = new Person();

            Person person2 = new Person();

            

            System.out.println("Person1分别调用类方法和实例方法");

            person1.mathod();

            person1.classmathod();

            

            System.out.println("Person2分别调用类方法和实例方法");

            person2.mathod();

            person2.classmathod();

            

            System.out.println("Person类分别调用类方法");

            Person.classmathod();

            //注意不能调用实例方法!!!

            

        }

        

}

运行结果:

Person1分别调用类方法和实例方法

这是一个实例方法

这是一个类方法

Person2分别调用类方法和实例方法

这是一个实例方法

这是一个类方法

Person类分别调用类方法

这是一个类方法

 

你可能感兴趣的:(java)