Java核心技术系列之华东师范大学Java核心技术第四章对象与类,话谈Java中的赋值与变量交换底层原理、构造函数、信息隐藏、this

Java中的赋值与引用

该课堂笔记为华东师范大学在mooc网上的Java核心技术课程学习笔记。1

在Java中,如果对基本类型进行赋值,实际上是直接值拷贝的;如果对对象进行赋值,实际上是引用赋值,这个引用赋值可以理解为C/C++中的指针。

举两个例子,

赋值

新建两个变量和两个对象,然后对其中一个变量初始化,另一个变量和初始化后的变量相同。即:
对于数值型,a初始化为10, b = a;
对于对象型,obj1中的num初始化为5, obj2 = obj1;

package chapter4;

public class ComparedObjectWithVariable {
    public static void main(String[] args) {
        int a = 10, b;
        b = a;
        System.out.println("before: a is " + a + ", and b is " + b);
        b = 20;
        System.out.println("after: a is " + a + ", and b is " + b);

        MyNumber obj1 = new MyNumber();
        MyNumber obj2 = new MyNumber();
        obj1.num = 5;
        obj2 = obj1;
        System.out.println("before: obj1.num is " + obj1.num + ", and obj2.num is " + obj2.num);
        obj2.num = 20;
        System.out.println("after: obj1.num is " + obj1.num + ", and obj2.num is " + obj2.num);

    }
}

MyNumber这个类如下:

package chapter4;

public class MyNumber {
    int num = 5;
}

此时,输出结果为:

before: a is 10, and b is 10
after: a is 10, and b is 20
before: obj1.num is 5, and obj2.num is 5
after: obj1.num is 20, and obj2.num is 20

从结果中可以看出:
1、数值型变量重新赋值时,不改变原来变量a的数值。这是因为对数值型变量赋值时,直接拷贝,重新开辟内存空间的过程。因此,输出为一个5, 一个 10。
在这里插入图片描述
2、类初始化的时候,初始状态如下:
在这里插入图片描述
然后obj1 = obj2,此时,相当于将 obj1 的指针指向 obj2,即两者共用一个内存空间。
在这里插入图片描述
此时,将 obj2.num 赋值为 20, 即为两者的值都改变了。

变量交换

MyNumber类的代码和赋值章节中的代码一致。变量交换代码如下:

package chapter4;

public class ArgumentPassing {

    public static void swap(int m, int n) {
        System.out.println("before: m is " + m + ", and n is " + n);
        int s = m;
        m = n;
        n = s;
        System.out.println("after: m is " + m + ", and n is " + n);
    }

    public static void swap(MyNumber obj3, MyNumber obj4) {
        int m = obj3.num;
        obj3.num = obj4.num;
        obj4.num = m;
    }

    public static void main(String[] args) {
        int a = 10, b = 5;
        System.out.println("before: a is " + a + ", and b is " + b);
        swap(a, b);
        System.out.println("after: a is " + a + ", and b is " + b);

        MyNumber obj1 = new MyNumber();
        MyNumber obj2 = new MyNumber();
        obj2.num = 10;
        System.out.println("before: obj1.num is " + obj1.num + ", and obj2.num is " + obj2.num);
        swap(obj1, obj2);
        System.out.println("after: obj1.num is " + obj1.num + ", and obj2.num is " + obj2.num);

    }
}

该代码运行结果如下:

before: a is 10, and b is 5
before: m is 10, and n is 5
after: m is 5, and n is 10
after: a is 10, and b is 5
before: obj1.num is 5, and obj2.num is 10
after: obj1.num is 10, and obj2.num is 5

发现交换前后,对于数值型变量来说,交换并没有成功;而对于对象的数值型交换成功了。这是为什么呢?

是这个样子的,

  • 对于数值型变量赋值,之前说了是直接赋值的,那么经过swap函数之后呢,在内存空间里是这个样子的:
    在这里插入图片描述
    故而在变量交换前后,是指m和n的数值交换,但是对于a和b来说,交换前后输出的值不变。
  • 对于对象来说,对象的赋值是赋值指针,那么,交换开始时四个对象在内存空间中分布如下:
    在这里插入图片描述
    obj1obj3 指向同一个内存, obj2obj4 指向同一个内存。
    在交换完成后,交换的是 obj3obj4num数值。但是因为obj1obj3 指向同一个内存, obj2obj4 指向同一个内存,故而, obj1obj2num数值也完成了交换。

对象的生成

对象如何建立

产生一个对象:A obj = new A();
99%的情况下是通过关键字 new 来进行建立,1% 的情况下是用克隆和反射生成。

new 出一个对象后的默认值

对于数值型的对象默认值为0(或者0.0),对于布尔变量,默认为 false, 对于 char 变量,默认为 \u0000。类的成员变量都是有默认值的,函数中的临时变量必须要初始化(没有默认值)。

构造函数

作用

作用:是指在类初始化的时候就给类的成员变量赋值。
举个例子,

package chapter4;

public class ConstructorFunction {
    int id;
    public ConstructorFunction(int id2) {
        id = id2;
    }

    public static void main(String[] args) {
        ConstructorFunction constructorFunction = new ConstructorFunction(10);
        System.out.println(constructorFunction.id);
    }
}

此时,ConstructorFunction这个构造函数就对该类成员变量id赋值了,上述代码输出为 10

构造函数注意点

对于构造函数来说,有以下几点需要注意:
在这里插入图片描述
Java中没有析构函数,那么变量消亡的时候,如何回收内存的呢?这是因为Java有个内存自动回收机制。对象回收的效率依赖于垃圾回收器(GC),其回收算法关系到性能好坏。
在这里插入图片描述
在这里插入图片描述
另外,

  • 对于一个类来说,可以有多个构造函数,只要形参列表不相同就好。【这个类似于函数重载(over load),函数重载是指函数名相同,形参不同】
  • new 对象的时候,根据实参的不同自动挑选相应的构造函数。如果实参形参匹配不上,则会报错。
    举个例子,
package chapter4;

public class MyPairNumber {
    int m;
    int n;
    public MyPairNumber() {

    }

    public MyPairNumber(int a) {
        m = a;
    }

    public MyPairNumber(int a, int b) {
        m = a;
        n = b;
    }

    public static void main(String[] args) {
        MyPairNumber myPairNumber1 = new MyPairNumber();
        MyPairNumber myPairNumber2 = new MyPairNumber(10);
        MyPairNumber myPairNumber3 = new MyPairNumber(10, 20);
//        MyPairNumber myPairNumber4 = new MyPairNumber(10, 20, 30); // error
        System.out.println("myPairNumber1 has " + myPairNumber1.m + "," + myPairNumber1.n);
        System.out.println("myPairNumber2 has " + myPairNumber2.m + "," + myPairNumber2.n);
        System.out.println("myPairNumber3 has " + myPairNumber3.m + "," + myPairNumber3.n);
    }
}

输出结果如下:

myPairNumber1 has 0,0
myPairNumber2 has 10,0
myPairNumber3 has 10,20

信息隐藏和this

信息隐藏

在这里插入图片描述
在这里插入图片描述
在Intellij中如何自动生成 get/set 方法
1、右键点击Generat(或者mac电脑用 command + N)
2、选择Getter/Setter方法
3、选择需要产生的get/set方法(如果需要选择多个,可以按住shift键)
举个例子,

package chapter4;

public class Person {
    private int age;
    private int height;
    private int name;
    private int weight;

    public void setAge(int age) {
        this.age = age;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setName(int name) {
        this.name = name;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public int getAge() {
        return age;
    }

    public int getHeight() {
        return height;
    }

    public int getName() {
        return name;
    }

    public int getWeight() {
        return weight;
    }
}

this

在这里插入图片描述
形参的id优先级更高一些,this指向本类中的成员变量。因此,函数内部的id指的是形参idthis指向的是本类中的成员变量id。在上述例子中靠左边的 id = id2id在本类成员变量中只有一个id变量,故而省略了this,将 this.id = id2 写成 id = id2
在这里插入图片描述
举个例子,

package chapter4;

public class MyPairNumber {
    int m;
    int n;
    public MyPairNumber() {
        this.n = 0;
        this.m = 0;

    }

    public MyPairNumber(int a) {
        this(a, 0);
    }

    public MyPairNumber(int a, int b) {
        this.m = a;
        this.n = b;
    }

    public static void main(String[] args) {
        MyPairNumber myPairNumber1 = new MyPairNumber();
        MyPairNumber myPairNumber2 = new MyPairNumber(10);
        MyPairNumber myPairNumber3 = new MyPairNumber(10, 20);
//        MyPairNumber myPairNumber4 = new MyPairNumber(10, 20, 30); // error
        System.out.println("myPairNumber1 has " + myPairNumber1.m + "," + myPairNumber1.n);
        System.out.println("myPairNumber2 has " + myPairNumber2.m + "," + myPairNumber2.n);
        System.out.println("myPairNumber3 has " + myPairNumber3.m + "," + myPairNumber3.n);
    }
}

上述代码中,

public MyPairNumber() {
        this.n = 0;
        this.m = 0;

    }

即表示this可以表示本类中的临时变量。

public MyPairNumber(int a) {
        this(a, 0);
    }

即表示this可以表示本类中的构造函数MyPairNumber(int a, int b)
输出结果如下:

myPairNumber1 has 0,0
myPairNumber2 has 10,0
myPairNumber3 has 10,20

  1. 华东师范大学在mooc网上的Java核心技术课程 ↩︎

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值