Java重修之路(六)面向对象初识,类与对象,成员变量,局部变量,封装,构造函数,构造代码块,this关键字

今天终于进入正题,Java的面向对象部分,也是Java的核心部分,如果之前只是学过C语言而没有接触其他面向对象的语言的同学,这里要转换思想还是有些难度的,需要多思考,弄清楚什么是面向对象,面向对象与面向过程的区别。不多说废话,开始了。

- 面向对象概述

面向过程是功能行为,就是将功能封装给对象,强调了具备有功能的对象,对象具有一定的特征和功能,在使用的时候只需要找到相应的对象,就能获得其特征和功能。

类与对象的关系

这里写图片描述
类是对对象的描述,包括对象的特征,功能。
对象是一个个实体。

- 成员变量与局部变量

成员变量作用于整个类中,局部变量作用于函数中或者语句中。
在内存中成员变量在堆内存中,因为对象的存在才在内存中存在,而局部变量存在于栈内存中。

匿名对象

没有变量名的对象。即没有指向它的引用

public class Hello {
    public static void main(String[] args) {
//      new Car().run();
        Car c=new Car();
        c.run();
    }
    public static class Car{
        String color="red";
        int num=3;
        public void run(){
            System.out.println("color="+color+"\nnum="+num);
        }
    }
}

这两种写法效果是一样的,但是接下来往下看:

public class Hello {
    public static void main(String[] args) {
//      new Car().run();
        Car c=new Car();
        c.num=5;
        c.run();
    }
    public static class Car{
        String color="red";
        int num=3;
        public void run(){
            System.out.println("color="+color+"\nnum="+num);
        }
    }
}

输出结果为:
color=red
num=5

但是对于匿名对象来说,修改属性是没有意义的:

public class Hello {
    public static void main(String[] args) {
        new Car().num = 5;
        new Car().run();
    }

    public static class Car {
        String color = "red";
        int num = 3;

        public void run() {
            System.out.println("color=" + color + "\nnum=" + num);
        }
    }
}
输出结果为:
color=red
num=3

可见属性的修改并没有预期的效果,因为

new Car().num = 5;
new Car().run();

根本就是操作的两个不同的对象,当执行到第二条语句时,第一个对象已经成为垃圾,第二条语句时重新new了一个对象,并且修改了它的一个属性,但是并没有用,因为修改了也不使用,没有指向它的引用。

  1. 特点:
    匿名对象操作其属性没有意义,只能调用其方法。
  2. 适用场景:
    对对象的方法只需要调用一次,可以用匿名对象,这样比较简便,如果需要对多个成员进行调用,必须要有对象引用。
    可以将匿名对象作为实际参数传递
public class Hello {
    public static void main(String[] args) {
        // Car c=new Car();
        // changeCar(c);
        changeCar(new Car());
    }

    public static class Car {
        String color = "red";
        int num = 3;

        public void run() {
            System.out.println("color=" + color + "\nnum=" + num);
        }
    }

    public static void changeCar(Car c) {
        c.num = 100;
        c.color = "aaa";
        c.run();
    }
}
输出结果:
color=aaa
num=100

两种情况的内存图

这里写图片描述

两者还有一点区别就是:匿名对象作为实际参数传递,当函数调用完成,生命周期结束,匿名对象又沦为垃圾,而第一种不会。

- 封装

Java三大特性之一

这里写图片描述

public static void show(int x) {
    check(x);
}

private static void check(int x) {
    if (x <= 0) {
        System.out.println("数据不合法!");
    } else {
        System.out.println(x);
    }
}
在一个类中有这两个方法,只需要将show方法暴露出去给人使用,而check方法时内部检查使用,不需要暴露出去,所以用private修饰。
封装不是私有,私有仅仅是封装的一种表现形式。
public class Person {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age < 0 || age > 200) {
            System.out.println("年龄不合法!");
            return;
        }

        this.age = age;
    }

    public String getName() {
        return name;
    }

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

}
这里将age,int的权限设为private,所以不能通过对象.属性来设置值,因为外边访问不到,然后对外提供setAge方法,只能通过此方法设置值。

- 构造函数

这里写图片描述

对象一建立就会调用与之对应的构造函数。

public class Hello {
    public static void main(String[] args) {
        new Demo();
    }

    public static class Demo {
        Demo() {
            System.out.println("这是构造函数!");
        }
    }

}
输出结果:
这是构造函数!

由于构造函数的特性,可以在构造函数里面进行初始化。
多个构造函数之间是重载的形式出现的。

构造函数的重载
public Person() {
    }

    public Person(int age) {
    }

    public Person(int age, String name) {
    }

    public Person(String name, int age) {
    }

每一个类都有一个默认的空参数的构造函数,但是一旦你自己写了构造函数,则默认的构造函数就不存在了。
构造函数和一般方法的区别:
构造函数在对象一建立就执行,一般方法是需要对象主动调用才执行。
一个对象建立,构造函数只执行一次,一般方法可以被对象调用多次。
构造函数适用情景:
对象本身具有的一些特征,在构造函数里面初始化。

- 构造代码块

给对象化初始化,对象一建立就执行,而且优先于构造函数执行。
和构造函数的区别:
构造代码块是给所有的对象统一初始化,而构造函数是给对应的的对象初始化。
适用情景:对象的公共属性在构造代码块里面统一初始化。

- this关键字

首先下边的场景:

import javax.print.DocFlavor.STRING;

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        name = name;
    }

}
这里给name赋值的时候,左边的name指的是本类中的成员变量,右边的name指的是传经来的参数,但是如果按这种写法,name并没有成功赋值:
Person person = new Person();
person.setName("zhangsan");
System.out.println(person.getName());
输出结果是:
null

所以必须要有一个关键字,告诉程序将传进来的值赋给本类的成员变量,所以用到关键字this,this代表的是本类。

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

就能成功赋值。

- this关键字在构造函数之间的调用

public class Person {
    private int age;
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public Person(int age, String name) {
        // this.name = name;
        this(name);
        this.age = age;
    }

}
有两个构造函数,但是设置姓名的构造函数在前边已经有了,此时就可以用this来调用,但是注意:
this(name);必须放在最前面,不能放在this.age = age;后边至于为什么,看下边的代码:
import javax.print.DocFlavor.STRING;

public class Person {
    private int age;
    private String name;

    public Person(String name) {
        this.name = "abcd";
    }

    public Person(int age, String name) {
        // this.name = name;
        this(name);
        this.age = age;
    }
}

假设是:
this.name = name;//此时name=传进来的参数
this(name);//name=“abcd” 覆盖掉了
下边这种 情况:
this(name);//

public Person(String name) {
this.name = name;
}

this.name = name;
注意区分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值