JAVA面向对象三大特征

一、封装

1. 介绍

封装就是将对象的属性保护起来,只能通过类内部的方法来访问
可以在修改属性时做一些检验防止意外发生,提高安全性
封装好以后其他人只需要知道怎么调用,不用考虑内部的实现原理

2. 实现步骤

  1. 将属性私有化(private),使其不能被外部访问
  2. 设置公共的(publicset方法来设置属性的值
  3. 设置公共的(publicget方法来获取属性的值

3. IDEA快捷键

alt + insert后选择getter和setter
快捷键

4. 与构造器结合

set方法写在构造器中,可以保证初始化的安全

5. 示例

public class Homework {
    private String password = "000000";

    public Homework(String password) {
        setPassword(password);
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        if(password.length() == 6){
            this.password = password;
        } else {
            System.out.println("密码不是六位,默认密码为000000");
        }
    }
}

二、继承

1. 为什么需要继承

有些类中有很多相同的方法,但是又有一些不同的方法,这就造成了代码冗余。
将共同的部分抽离成父类(也叫基类,超类),让子类(也叫派生类)去继承可以解决这个问题。
继承示意图

2. 基础语法

使用extends关键字
父类

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

    public float getScore() {
        return score;
    }

    public void setScore(float score) {
        this.score = score;
    }

    public void info() {
        System.out.println("姓名:" + name + " 年龄:" + age + " 分数" + score);
    }
}

子类

//让pupil类继承student类
public class Pupil extends Student{
    public void testing() {
//        这里用到了从父类继承的name属性
        System.out.println("小学生" + name + "正在考小学数学");
    }

    public static void main(String[] args) {
        Pupil pupil = new Pupil();
        pupil.name = "xiaoming";
        pupil.testing();

    }
}

3. 细节

  1. 子类继承了所有的属性和方法,但不一定能用。
    私有属性和方法不能直接去访问,非私有的属性和方法可以在子类直接访问,要通过父类提供的公共的方法去访问。

这里的score是私有属性,可以看到直接使用IDEA会报错
出错
2. 子类必须调用父类的构造器完成父类的初始化,因为子类中有一个隐藏的无参的super()函数,super函数在子类构造器的最上面,会被默认调用。
3. 创建子类对象时,无论子类使用哪个构造器,都会默认调用父类的无参构造器,如果父类没有无参构造器,则必须指明使用父类的哪个构造器。
4. 如果希望使用父类的某一个构造器,则需要显式得调用。
5. super必须放在构造器的第一行。
6. super()this()都只能放在第一行,因此两个方法不能共存。
7. 所有的类都是Object的子类,Object类是所有类的父类。(在IDEA中ctrl + H可以查看类之间的关系)。
ctrl+h快捷键

  1. 父类构造器的调用不限于直接父类,将一直追溯至Object。
  2. 子类只能直接继承一个父类,java是单继承机制。
  3. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。

4. 内存本质

在jvm中的内存

5. super

5.1 基本介绍

super是父类的引用,类似于this是子类本身的引用。
使用super可以访问父类的属性、方法和构造器。

5.2 基本语法

  1. super.属性名可以访问父类的属性,但不能访问私有属性。
  2. super.方法名可以访问父类的方法,但不能访问私有方法。
  3. super(参数)可以访问父类的构造器,必须放在第一句。

5.3 细节

  1. 调用父类构造器的好处:分工明确,父类由父类构造器初始化,子类由子类构造器初始化。
  2. 当子类与父类的属性和方法重名时,必须通过super来访问直接父类的属性和方法,如果不同名使用super和使用this效果相同。
  3. super的访问不限于直接父类,也可以访问爷爷类的成员,如果父类和爷爷类中也有重名类,则遵循就近原则

5.4 super与this

super与this的对比

6. 方法重写(override)

6.1 基本介绍

如果子类中的某个方法与父类(不一定是直接父类)中完全相同(方法名,返回类型,参数),则子类中的方法会覆盖掉从父类中继承来的方法。

6.2 细节

  1. 子类中重写的方法的返回类型可以是父类方法返回类型的的子类
    (例如父类返回Object,则子类可以返回String)。
  2. 子类的参数和方法名要和父类完全相同才可以重写。
  3. 子类方法不能缩小父类方法的访问权限。

6.3 重写和重载

重写和重载

6.4 重写练习题

题目要求
题目
代码

// 定义父类
class Person {
    private String name;
    private int age;
	// 父类的构造器
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void say() {
        System.out.println("我的名字是:" + name + 
        " 我的年龄是:" + age);
    }
}
// 定义子类
class Student extends Person{

    private String id;
    private float score;
	// 子类的构造器
    public Student(String name, int age, String id, float score) {
    	// 调用父类的构造器
        super(name, age);
        this.id = id;
        this.score = score;
    }
    
    public void say() {
    	// 调用父类的say方法
        super.say();
        System.out.println("我的学号是:" + id +
         "我的分数是:" + score);
    }

    public static void main(String[] args) {
        Student student = new Student("小明",18,"123456",99);
        student.say();
    }
}

三、多态

1. 基本介绍

建立在封装和继承之上。
指的是方法和对象具有多种形态,父类的引用可以指向子类。
看不懂没关系,往下继续看就明白了。
举一个动物给动物喂食的案例,不再需要每种动物都重载一次方法,直接使用动物的父类和食物的父类来指向各个子类。
之后再添加新的子类时也不需要修改feed方法。
在这里插入图片描述

2. 具体体现

2.1 方法的多态

重写和重载体现多态

2.2 方法的多态

  1. 一个对象的编译类型和运行类型可以不一样
  2. 编译类型在定义是就已经确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看等号的左边,运行类型看等号的右边

例如animal和cat是两个类
animal o = new cat();
定义的o编译类型为animal,运行类型为cat
示例

3. 细节

3.1 前提条件

两个对象(类)存在继承关系

3.2 向上转型

  1. 本质: 父类的引用指向了子类的对象
  2. 语法: 父类 引用名 = new 子类()
  3. 特点:
    • 编译类型看左边,运行类型看右边。
    • 可以直接调用父类中的所有成员(需要遵守访问权限)。
    • 不能调用子类中的特有成员,只能调用重写的成员,在编译阶段,能调用那些成员是由编译类型决定的。
    • 运行效果看子类的具体实现,调用方法时是从运行类型开始查找。

3.3 向下转型

  1. 向下转型的目的是为了调用子类的特有成员。
  2. 语法:子类 引用名= (子类类型)父类对象
  3. 只能强转父类的引用,不能强转父类的对象(向下转型的前提是向上转型,经历过向上转型的对象(引用)才可以被向下转型)
  4. 要求父类的引用必须指向当前目标类型的对象
  5. 可以调用子类的所有成员

3.4 属性的重写

  • 属性没有重写和转型一说,属性的值直接看编译类型
  • instanceof,可以查看一个对象是否是某个类型或者其子类型(运行类型)

例如:A instanceof B,检查A对象是否是B类型,或者A对象是否是B类型的子类型,返回布尔值

4. 应用场景

4.1 多态数组

  1. 定义:数组定义的类型为父类类型,实际存储的对象为子类类型。
  2. 数组中子类特有的方法可以通过向下转型调用。
  3. 可以使用instanceof关键字判断转型为哪个子类。
//Teacher类
public class Teacher extends Person{
    public static void main(String[] args) {
    	// 向上转型 将Student和Teacher都存储在Person数组中
        Person[] people = new Person[5];
        people[0] = new Person("砂糖",12);
        people[1] = new Student("刻晴",16,88.0);
        people[2] = new Student("蜜莓",14,80.0);
        people[3] = new Teacher("凯尔希",100,80000);
        people[4] = new Teacher("钟离",5000,0);

        for (int i = 0; i < people.length; i++) {
        	//instanceof 与 向下转型结合调用子类特有方法
            if(people[i] instanceof Student){
                Student student = (Student)people[i];
                student.study();
            } else if(people[i] instanceof Teacher){
                Teacher teacher = (Teacher)people[i];
                teacher.teach();
            }
           people[i].say(people[i].getAge(), people[i].getName());
        }


    }
    private int money;

    public Teacher(String name, int age, int money) {
        super(name, age);
        this.money = money;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    @Override
    public void say(int age, String name) {
        super.say(age, name);
        System.out.println("我的工资是:" + money);
    }

    public void teach(){
        System.out.println(getName() + "正在讲课");
    }
}
//Student 类
public class Student extends Person{
    private double score;

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public void say(int age, String name) {
        super.say(age, name);
        System.out.println("我的分数是:" + score);
    }

    public void study(){
        System.out.println(getName() + "正在学习");
    }
}
//Person 类
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        setAge(age);
        setName(name);
    }

    public Person() {

    }

    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 say(int age,String name) {
        System.out.println("我的名字是:" + name + "我的年龄是" + age);
    }

4.2 多态参数

方法定义的形参为父类,实参可以是子类。
题目示例

//test类
public class test {
    public static void main(String[] args) {
        sass tom = new sass("tom", 2000);
        less milan = new less("milan", 5000, 200000);
        test test = new test();
        test.show(tom);
        test.show(milan);
        test.testwork(tom);
        test.testwork(milan);
    }

    public void show(css e){
        System.out.println(e.getMoney());
    }
	// 形参参数为css父类,传入的实参为其子类
    public void testwork(css e){
        if(e instanceof less){
            ((less)e).manage();
        } else if(e instanceof sass){
            ((sass)e).work();
        } else {
            System.out.println("自己检查哪里出错了");
        }
    }
}
//css类
public class css {
    String name;
    private int money;

    public css(String name, int money) {
        this.name = name;
        this.money = money;
    }

    public int getMoney() {
       return money * 12;
    }
}

//sass类
public class sass extends css{
    public void work(){
        System.out.println("员工在工作");
    }

    public sass(String name, int money) {
        super(name, money);
    }
	//方法重写
    @Override
    public int getMoney() {
        return super.getMoney();
    }
}
// less类
public class less extends css {
    int bonus = 1000;

    public less(String name, int money, int bonus) {
        super(name, money);
        this.bonus = bonus;
    }

    public void manage(){
        System.out.println("领导在管理");
    }

    @Override
    public int getMoney() {
        return super.getMoney() + bonus;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值