基础——面向对象

Java面向对象

一、类

  1. java程序的最基本单位
  2. 对一类有共同属性和行为事物的抽象叫做类

二、对象

1、定义

实实在在看得见摸得着的实体叫对象

  • 注:new出来的对象存在于内存的中,有默认值。比如Stringnullint0

代码执行过程中内存原理分析

Demo

  • 类的定义
package com.student;

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public void show(){
        System.out.println("name=" + name + " , " +"age=" + age);
    }
}

2、单对象内存原理

  • 测试
package com.student;

public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("小明");
        s1.setAge(18);
        s1.show();
    }
}

1、main方法在内存中进栈
在这里插入图片描述
执行构造方法,创建一个Student类得实例对象s1,于是在内存的堆空间开辟空间存储s1成员变量,并初始化成员变量。构造方法出栈。
2、setName方法在内存中进栈
在这里插入图片描述
s1指向堆中的对象实例地址(假设是001),this指向的方法调用者实例,也就是s1.
方法执行结束出栈。
之后setAge方法同理。
4、执行show方法,show方法在内存
在这里插入图片描述

3、多对象内存原理

  • 测试
package com.student;

public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();
        s1.setName("小明");
        s2.setName("小红");
        s1.setAge(18);
        s2.setAge(20);
        s1.show();
        s2.show();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
后续方法调用同理,都是一个类方法执行,先进入内存栈区域,如果是赋值操作,那么调用者对象便指向内存堆区域的真实地址,对成员变量进行赋值操作,在方法执行完毕之后,会将方法进行出栈,随后后续方法接在内存中入栈,执行响应操作。

以demo的测试代码为例,接下来是Student的setAge方法入栈,调用者是s1,便指向s1在内存堆中的真实地址,对s1的age属性进行赋值,之后setAge方法出栈,接着又是Student的setAge方法入栈,可这回调用者是s2,于是指向s2在内存堆中的真实地址,对s2的age属性进行赋值,之后setAge方法出栈。接下来要执行的是Student类的show方法,两个对象都有调用,依次是s1先调用show方法入栈,执行过后出栈,然后是s2调用show方法入栈,执行后出栈。最后main方法执行完毕,释放s2,s1在内存中为存储成员变量开辟的空间,之后main方法出栈。到此为止测试执行完毕。

4、对象指向相同地址的内存原理

  • 测试
package com.student;

public class StudentDemo {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("小明");
        s1.setAge(18);
        Student s2 = s1;
        s2.setName("小红");
        s2.setAge(20);
    }
}

在这里插入图片描述

三、类中的变量

区别 成员变量 局部变量
类中位置 类方法之外 类方法内或类方法声明中
内存中位置
生命周期 因为在堆中,所以随着类得创建而创建,随着类的销毁而销毁 因为在栈中,所以随着类方法的调用而产生,随着方法的执行完毕而销毁
初始化 有初始化 没有初始化,必须要先创建,然后赋值,才能被使用

this指针

this修饰的变量指代成员变量

  • 作用:解决局部变量隐藏成员变量的问题。
  • 方法中this的指向:方法被哪个对象调用this就指向哪个对象。

private修饰符

属于权限操作符,修饰类成员

  • 作用:保护类成员不被其他类使用,被private修饰的变量只能本类使用!

四、构造方法

  • 如果没有定义构造方法,默认使用无参构造方法。
  • 如果定义了构造方法,系统将不再提供构造方法(建议都手动加上无参构造方法)

五、面向对象三大特征:封装、继承、多态

(一)封装

封装是面向对象编程语言对客观世界的模拟,客观世界里的成员变量都是隐藏在对象内部,外界是无法直接操作的

  • 原则:将类得某些信息通过private属性隐藏在类内部,外界不能直接访问,需要通过该类提供的public方法进行操作或访问。
  • 好处:
  1. 通过方法来控制成员变量的操作,提高了代码的安全性。
  2. 把代码用方法进行封装,提高了代码的复用性。

(二)继承

继承就是有一堆的类,把这些类的共性方法抽取出来,作为一个父类(也可叫做超类、基类),之后这些类就作为它的子类,这些子类就能继承父类中的所有非私有成员。

  • 注意事项:
  1. 子类继承父类以后可以拥有父类的非私有成员
  2. 构造方法不能被继承,私有成员不能被继承,static修饰的成员不能被继承
  • 格式:class 子类 extends 父类
  • 访问成员变量:
  1. 不重名:如果访问父类的对象,那只能直接访问父类的非私有成员变量。如果访问子类的对象,那访问的是子类和父类的非私有成员变量。
  2. 直接使用中,父类对象、本类对象重名:优先访问=左边的对象类型的变量,如果要对其进行区别可以使用this来特指本类对象、super特指父类对象
  3. 通过方法使用时,父类对象、本类对象、本类中的局部变量都重名:主要先看使用的是哪个类的方法,在方法中优先访问本类的局部变量,访问本类成员使用this指代,访问父类的成员使用super指代。
  • 访问成员方法
  1. 不重名:如果访问的是父类的成员方法,那就只能访问父类的成方法。如果访问子类,那么访问的是子类的成员方法和父类的非私有成员方法。
  2. 重名:优先调用的同名方法主要看new的对象是什么类型,如果要显示进行区分最好使用thissuper来专门指代。
  • 方法的重写
  1. 要求:重写的方法必须和原来的方法一模一样,虽然可以在方法的返回值可以是原来方法的子类型,但一般还是写作一模一样的类型。

  2. 使用场景:

    a. 子类想对父类方法进行增强,一般加一句 super.method();
    b. 父类方法是抽象的需要子类进行具体化。

面向对象中的抽象

在继承中不得不谈到抽象,因为在现实世界中有很多东西的共性的十分抽象的,不能一句话说得清,比如人吃饭、狗吃饭、鱼吃饭,他们具体的吃饭行为大不相同,如果要把“吃饭”这个动作进行提取为一个公共函数,那么就必须使用抽象的方法,也就是说只声明方法名,并声明为抽象方法,具体实现我们先不管,等定义具体的实现类时在进行行为的定义。

  • 抽象方法:修饰符 abstract 返回类型 方法名(参数列表)

  • 抽象类: abstract class 类名

  • 注意事项:

  1. 将一类事物的共性方法抽取出来,但这个方法说不清道不明,就可以吧这个方法定义为抽象方法。
  2. 抽象方法一定要在抽象类中。
  3. 抽象类中不一定有抽象方法。
  4. 抽象类可以有成员变量、构造方法、普通方法。
  5. 抽象类不能直接实例化。
  6. 抽象类的构造方法是为了子实现类初始化时构造方法可以调用,用来初始化父抽象类中的成员变量
  7. 抽象类的子实现类必须重写父类的全部抽象方法
  • 使用场景:一般作为父类

(三)多态

现实世界中,一种事物有多种形态,比如我们自己,在学校是学生,在家是儿子。
一句话说多态就是:父类对象引用指向子类对象,调用父子共用的方法(子类重写后的方法)。

  • 前提
  1. 有父子继承关系(接口实现关系)
  2. 同名方法的重写
  3. 父类引用指向子类对象
    父类 对象名 = new 子类()
  • 多态的使用步骤
  1. 定义类

  2. 定义子类继承父类,重写父类方法

  3. 父类引用指向子类对象–>父类名 对象名 = new 子类() ,调用重写方法

    注意事项:
    1.必须有子父类继承关系(接口,实现类的关系)
    2.必须又方法的重写
    3.父类引用指向子类对象–>父类名父类名 对象名 = new 子类() ,调用重写方法

  • 多态中的访问特点
  1. 多态中如果出现子类和父类变量同名的访问:看=左边的类型,是什么类型就访问哪个类型的变量
  2. 多态中如果出现子类和父类方法同名的访问:看new的对象是什么类型,访问的就是哪个类型的方法

如果子类中没有变量或者方法就访问父类

  • 多态和普通面向对象的优点和缺点
  • 普通面向对象:
    优点:可以访问父类和本类的所有费私有方法
    缺点:扩展性差
  • 多态:
    优点:扩展性强,尤其在函数参数调用,重写方法调用上
    缺点:不能通过指向子类的引用来使用子类的特有方法

对于多态的缺点,也可以通过向下转型的方式解决。

  • 转型
  1. 向上转型:默认都是向上转型,也就是父类对象引用指向子类对象
  2. 向下转型:
//((Dog) animal).watchDoor();
Dog dog = (Dog) animal;
dog.watchDoor();

通过向下转型就可以调用子类的特有方法

  1. 向下转型可能会抛出异常:Exception in thread “main” java.lang.ClassCastException

对于这个异常可以通过关键字instanceof来解决,在转型的时候进行判断,判断对象是否属于某个类型。
使用方法:对象名 instanceof 类型

猜你喜欢

转载自blog.csdn.net/weixin_38708854/article/details/106423952