面向对象(上)

一、面向对象程序设计的三条主线

​ 一、设计类

​ 二、新建类的对象。

​ 三、通过对象来调用类的属性和方法

二、面向对象的三大特点

​ 一、封装

​ 二、继承

​ 三、多态

三、如何理解类和对象

​ 类:类是抽象的、概念性的。

​ 对象:对象是类的派生,是 new 出来的,是实实在在存在的,在内存中占据着一定的空间。

在 Java 中,万事万物皆对象

​ 一、在 Java 语言本身的范畴中,我们都将功能、属性等封装到类中,通过类的实例化来调用具体的功能和属性。

​ 二、在 Java 与前端 html、后端数据库进行交互时,前后端的结构在与 Java 层面对应是,都体现为类。

四、创建一个类的内存解析

​ new 操作符的本意是分配内存。程序执行到 new 操作符时,因为知道了类型,才能知道分配多大的内存空间。分配完内存后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化;构造方法返回后,一个对象创建完毕,可以把他的引用发布到外部,在外部就可以操纵这个对象了。

如图:
在这里插入图片描述

​ (新建一个对象的内存解析)

​ 初始化的对象属性都是默认值,字符串类型默认为 null,整形默认为 0。

​ 当使用对象访问时,实际上时通过操作地址,访问该地址指向的内存,来访问变量。

代码实例:

public class TestStudent {
    public static void main(String[] args) {
        //新建一个 student 对象,并未对其进行赋值
        Student stdu1 = new Student();
        System.out.println("stdu1: " + stdu1 + ", stdu1.name: " + stdu1.name + ", stdu1.age: " + stdu1.age);
        //输出stdu1: ObjectTest.Student@1540e19d, stdu1.name: null, stdu1.age: 0
    }
}

//定义 Student 类
class Student {
    String name;
    int age;

    public Student() {

    }
}

对象是引用数据类型,所以当把对象赋值给一个变量时,其实是赋的它的地址

例:

public class TestStudent {
    public static void main(String[] args) {
        Student stdu1 = new Student();
        stdu1.name = "张三";
        stdu1.age = 10;
        System.out.println("stdu1: " + stdu1 + ", stdu1.name: " + stdu1.name + ", stdu1.age: " + stdu1.age);
        //新建一个对象,指向 stdu1
        Student stdu2 = stdu1;
        System.out.println("stdu2: " + stdu2 + ", stdu2.name: " + stdu2.name + ", stdu2.age: " + stdu2.age);
        //通过 stdu2 来更改 stdu1 的属性值
        stdu2.name = "李四";
        System.out.println("stdu1: " + stdu1 + ", stdu1.name: " + stdu1.name + ", stdu1.age: " + stdu1.age);

    }
}
/*结果:
stdu1: ObjectTest.Student@1540e19d, stdu1.name: 张三, stdu1.age: 10
stdu2: ObjectTest.Student@1540e19d, stdu2.name: 张三, stdu2.age: 10
stdu1: ObjectTest.Student@1540e19d, stdu1.name: 李四, stdu1.age: 10
*/

​ 可以看到,stdu1 和 stdu2 指向同一个内存地址,并且通过 stdu2 改变了 stdu1;

五、对象数组的内存解析

​ 创建一个对象数组,其实是在对空间中分配了对应大小的空间,然后返回改数组的首地址,如同上述所说,对象只能存储引用,所以数组中存储的实际上是对象的地址,如果不对其进行初始化,则为 null,如图:

对象数组内存解析

例:

public static void main(String[] args) {
    Student[] stdus = new Student[8];
    //输出数组地址
    System.out.println("stdus: " + stdus);
    //遍历未初始化的数组
    for(int i = 0; i < 8; i++) {
        System.out.print(stdus[i] + " ");
    }

    //初始化 stdus[0] 并且输出
    stdus[0] = new Student();
    System.out.println("\nstdus[0] " + stdus[0] + ", stdus[0].name: " + stdus[0].name + ", stdus[0].age: " + stdus[0].age);
}
/*运行结果:
stdus: [LObjectTest.Student;@1540e19d
null null null null null null null null 
stdus[0] ObjectTest.Student@677327b6, stdus[0].name: null, stdus[0].age: 0
*/

六、属性(成员变量)和局部变量

​ 1、相同点:

​ 1.1 定义的格式相同:都是 变量类型 变量名 = 值

​ 1.2 都有其对应的作用域

​ 2、不同点:

​ 2.1 定义的位置不同

​ 2.2 存储的位置也不同

​ 2.3 修饰符不同,局部变量不能用 public 等关键字来修饰

七、方法的重载

一个类中两个同名的方法,参数列表(参数个数或者参数类型)不同就构成了重载。

​ 如何确定使用哪个方法:在调用方法的过程中,先看方法名,如果方法名相同,再看参数列表。

注:重载与返回值类型无关,因为如果两个方法如果参数列表相同,仅返回值类型不同,则无法确定使用哪个方法。

​ 方法重载的典型示例:

public class OverLoadTest {
    public static void main(String[] args) {
        int[] array1 = new int[]{1, 2, 3};	// int 类型的数组
        char[] array2 = new char[]{'a', 'b', 'c'};	// char 类型的数组
        System.out.println(array1);
        System.out.println(array2);
    }
}
/*结果:
[I@1540e19d
abc
*/

分析原因:使用 IDE 打开调用的方法,发现调用的是两个不同的方法:

​ 输出 int 类型的数组时,调用的是 PrintStream 类中 public void println(Object x) 方法;而输出 char 类型的数组时,调用的是 PrintStream 类中 public void println(char x[]) 方法。

八、可变个数的形参

可变个数的形参语法是: 参数类型 … 参数名,实现的机制就是在参数中使用数组实现的,访问每个参数的方式也与访问数组的方式相同。

​ 例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gzvKydRR-1583279888269)(C:\Users\dell\AppData\Roaming\Typora\typora-user-images\1582553018597.png)]

​ 如图所示的两个 show 函数发生了编译错误,错误原因就是函数重复定义了,可以证明 … 和数组的实现方式相同。

​ 例:

public class ParameterTest {
    public static void main(String[] args) {
        ParameterTest pt = new ParameterTest();
        pt.show("成龙", "李连杰", "洪金宝");
    }

    //访问可变参数中的参数
    private void show(String ... names) {
        for(int i = 0; i < names.length; i++)   // names 也有 length 方法
            System.out.println(names[i]);       // 访问方式也是通过下标访问
    }

}

注:可变参数必须声明在最后一个参数的位置,因为如果不这样做就无法确定到底有几个参数了;进而,一个函数中,最多有一个可变参数。

九、对构造器的理解

​ 构造器不要理解成构造函数,因为在 Java 中,函数都是通过对象来访问的,而构造器是生成对象的。在构造器中,可以调用其他构造器,但如过有 n 个构造器,最多有 (n - 1) 个可以调用其他构造器,另一个是调用的 super() 。

例:

public class Person {
    int age;
    String name;

    public Person() {
        System.out.println("我是父类");
    }
}


class Student extends Person {
    int id;

    public Student() {
        System.out.println("我是构造器1");
    }

    public Student(int id) {
        this();
        this.id = id;
        System.out.println("我是构造器2");
    }

    public Student(int age, String name) {
        this(3);
        this.name = name;
        this.age = age;
        System.out.println("我是构造器3");
    }
}

/*运行结果
我是父类
我是构造器1
我是构造器2
我是构造器3
*/

​ 分析结果:可以看到,Student() 构造器并没有显示调用 super(),但还是输出了 “我是父类”,说明子类会自动调用父类的构造器。

十、属性赋值

​ 1、默认值

​ 2、显示赋值

​ 3、构造器中赋值

​ 4、通过对象进行赋值

十一、this 关键字

定义:this 关键字表示调用该方法对象的引用。

public class ThisTest {
    public static void main(String[] args) {
        ThisTest t = new ThisTest();
        System.out.println(t);
        t.getInfo();
    }

    public void getInfo() {
        System.out.println(this);
    }
}
/*结果
ObjectTest.ThisTest@1540e19d
ObjectTest.ThisTest@1540e19d
*/

分析结果:上述结果表明,this 和 t 是同一个地址,所以印证了 this 的定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值