Day14 多态、包

一、多态

多态是继封装、继承之后,面向对象的第三大特性。

1.概述

封装—>面向对象—>继承、多态
多态是出现在继承或者实现关系中的。
同种类型的对象,表现出的不同形态
eg:

Student s = new Student();
//学生形态    对象
Person p = new Student();
//人的形态    对象

父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();

前提:
(1)有继承关系
(2)有父类引用指向子类对象(Person p = new Student();)
(3)有方法重写

2.应用场景

Teacher,Student,Administrator
关于register(),里面的参数到底写谁?
可以写他们共同的父类Person

public void register(Person p){
}//注册学生时,相当于Person p = new Student

3.多态的好处和弊端

好处
(1)使用父类型作为参数,可以接收所有子类对象
(2)体现多态的扩展性与便利
弊端
不能调用子类特有的功能(父类里没有的方法),在编译时会先检查父类里有没有该方法,如果没有会报错
解决:调用者a变回子类类型即可

Dog d = (Dog) a;

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型 
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false
if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }

JDK14的时候提出了新特性,把判断和强转合并成了一行

//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){
    d.lookHome();
}else if(a instanceof Cat c){
    c.catchMouse();
}else{
    System.out.println("没有这个类型,无法转换");
}

4.多态调用成员的特点

Animal a = new Dog();
sout(a);
a.show();

(1)变量调用

编译看左边,运行看左边

<1>javac编译代码时,会看左边父类中有没有该变量,如果有,编译成功,否则不成功;
在子类对象中,会把父类成员变量也继承。父:name 子:name
<2>java运行代码时,实际获取的是左边父类成员变量中的值

(2)方法调用

编译看左边,运行看右边
<1>javac编译代码时,会看左边父类中有没有该方法,如果有,编译成功,否则不成功;
<2>java运行代码时,实际获取的是右边子类成员方法中的内容
如果子类对方法进行了重写,虚方法表中会把父类的方法进行覆盖

(3)内存解释

加载字节码顺序:main()—>Object—>Animal—>Dog
Animal a = new Dog();在堆内存开辟空间,一分为二,左边存储父类name = “动物”,右边存储子类name = “狗”,地址值赋给a;sout(a),看父类里有没有name,有的话输出。如果是Dog d = new Dog(),先看右边有没有name,有就输出,没有去父类里找。

二、包

1.什么是包

包就是文件夹,用来管理不同功能的Java类,方便后期代码维护。
包的命名规则:公司域名反写+包的作用,需要全部小写

2.使用其他类的规则

(1)使用同一个包中的类时,不需要导包
(2)使用java.lang包中的类时,不需要导包
(3)其他情况都需要导包
(4)如果同时使用两个包中的同名类,需要用全类名

//使用全类名的形式即可。
//全类名:包名 + 类名
//拷贝全类名的快捷键:选中类名crtl + shift + alt + c 或者用鼠标点copy,再点击copy Reference
com.itheima.homework.demo1.Student s1 = new com.itheima.homework.demo1.Student();
com.itheima.homework.demo2.Student s2 = new com.itheima.homework.demo2.Student();

三、final

1.可以修饰方法、类、变量

(1)修饰方法:表明该方法是最终方法,不能被重写(例如方法是一种规则,不希望被重写)
(2)修饰类:最终类,不能被继承
(3)修饰变量:叫做常量,只能被赋值一次

2.常量

命名规则
单个单词:全部大写
多个单词:全部大写,单词间用下划线隔开

3.final的细节

final修饰的变量是基本类型:变量存储的数据值不能发生变化
final修饰的变量是引用类型:变量存储的地址值不能发生变化,对象内部可以改变
new一个对象s,s的地址值不会变化,但s.setName(“王一博”)是不会报错,内部的属性值是可以修改的。

final int[] arr = {1,2,3,4};
arr[0] = 10;
arr[1] = 20;//不会报错

数组的地址值不能改变,但每个数组元素的值是可以修改的
—>字符串是不可变的, 在存储字符串时,实际是
private final byte[] value这样一个数组存储的,因此字符串无法改变

四、权限修饰符

1.概述

用来控制一个成员能够被访问的范围
可以修饰成员变量、方法、构造方法、内部类

2.分类

作用范围由小到大
private—>空着不写—>protected—>public

publicprotected默认private
同一类中
同一包中的类
不同包的子类
不同包中的无关类
实际开发中,一般只用private,public

五、代码块

1.局部代码块

写在方法一对 { } 里的代码,提前结束变量作用范围,节约内存

2.构造代码块

写在成员变量位置的代码块

public class Student{
	private String name;
	{
		sout("开始创建对象了!");
	}
	public Student(){}
	public Student(String name){
		this,name = name;
	}
}	

把多个构造方法里重复的代码写到构造代码块里,先执行构造代码块,再执行构造方法
如果多个构造方法同时执行一句话,可以通过this()实现,即上述代码修改如下:

public class Student{
	private String name;

	public Student(){
		this(null);//调用本类其他构造
	}
	public Student(String name){
		this,name = name;
	}
}	

3.静态代码块

(1)格式

static{}

(2)特点

需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只会执行一次

(3)使用场景

程序刚开始时做一些数据初始化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Heliotrope&G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值