封装
封装特点
- 该露的露,该藏的藏,追求高内聚,低耦合。高内聚就是类的内部操作细节自己完成,不允许外部干涉。低耦合就是紧暴漏少量的方法给外部使用。
- 封装:即数据的隐藏。通常,应禁止访问一个对象中数据的实际表示,而应通过接口来访问,这成为信息隐藏
- 其实就是属性私有,而用get/set方法来修改
public与private修饰属性
我们新建一个student类,并新建一个对象wqy(没错哈,就是我名字的缩写),我们可以通过wqy.name/id/sex给相关属性赋值,因为这些变量前有public的修饰,如果没有这些修饰,这些属性只能在他们所在的类中使用。
如果我们用private修饰这些属性,这时再用wqy.name/id/sex将无法修改这些属性,而我们的一般做法正是这样。
难道我们这样做,就不修改这些属性的值了吗,不是的,因为我们有另外更安全的方法
get/set方法
我们定义get/set方法来对这些属性的值进行操作
自动生成get/set方法的快捷键:alt+insert
如图,我们可以选择创建get方法,set方法或get和set一起创建
接着我们选择创建方法对应的属性,按住ctrl以实现多选
(我们可以观察到,private修饰的属性被锁住了,而public修饰的属性是开锁状态)
把这三个属性对应的get/set方法都创建出来,我们就可以用这些方法对属性进行操作了:
另外,介绍一个快捷键:***.sout相当于System.out.println(***)
封装的优势
即用private修饰属性,用方法修改属性值的优势
- 提高程序安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 增加系统可维护性
继承
继承简介
在现实生活中,孩子经常可以继承父母的财产,而在Java的类中,也存在这种继承关系。
- 继承的本质是对某一批类的抽象
- extends的意思是扩展,子类是父类的扩展
- Java中类只有单继承,没有多继承
- 继承是类与类之间的一种关系,除此之外的关系还哦于依赖,组合,聚合等
- 继承关系的两个类,一个是父类,一个是子类,子类继承父类,用extends表示
如图,这样,学生类就继承了人类
另外,可以使用alt+enter实现一些快捷操作
如图,student继承了person的方法(也能继承属性)
idea中使用快捷键CTRL+h可以查看该类的继承树
如图我们看到Person上还有一个Object类,他是最大的类
我们发现,一个Student类下有很多我们未定义的方法,其实他们就是Object定义的方法
我们按住ctrl鼠标左键单击String进入他的类并用ctrl+h找继承关系,会发现他也继承了object类
总结:- Java中所有的类默认继承Object类
- 子类继承父类会继承父类的所有方法
super关键字
先观察代码
由图可得,this指向的是该类中的属性,super指向的是父类的属性
对于方法的调用同理:
而当我们用private修饰Person中的test1时,将会报错
私有的东西无法被继承!
如图,箭头表示有父类或子类,该程序在调用Student时,先调用了Person,这是继承后的一个特点
即Student(){}中有一段隐藏代码,调用了父类的构造器
我们也可以主动调用父类构造器,结果如图所示:
而this调用也要在第一行,因此二者只能二选一:
在这张图片里,this无限调用了Student(){}
如图,在Person类里定义一个有参构造器,那么默认的无参构造器就不存在了,Student构造器就会报错,因为它无法默认添加Person的无参构造器了
super注意点
- super调用父类的构造方法,必须在构造方法的第一个
- super只能出现在子类的方法或构造方法中
- super和this不能同时构造方法
- this和super写成this()和super()时默认调用此类和父类的构造器
- 在这里我们写的东西很多,如果想要搜索某一关键词,可使用ctrl+f快捷键
方法重写
重写都是方法的重写,与属性无关
如图:我们在B类中写一个test方法,在继承B类的A类中再写一个test方法,在Application中新建A类中的对象并调用test方法,结果发现调用了子类的方法
我们发现,A继承了B,那么我们也可以利用B类调用A的构造器创建对象,且它调用的方法为B类中的方法,因为A类构造器中有B类的的构造器!
再来一串代码帮助理解构造器:
结论,方法的调用,只与左边,定义的对象类型有关。
我们也可以使用快捷键alt+insert选择重写方法或者ctrl+o直接重写
注解:即有功能的注释,override意即重写
注意,无法重写static修饰的方法,因为类与静态方法一同加载,private修饰的方法也不能重写,重写的方法应为public
重写总结
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:重写后范围可以扩大(范围大小public>protected>default>private)
- 抛出异常的范围:可以缩小,但不能扩大(抛出异常以后讲)
多态
多态简介
- 即同一方法根据发送对象的不同采取多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
- 多态存在的条件
- 有继承关系
- 子类重写父类方法
- 父类引用子类对象
- 多态是方法的多态,属性没有
我们在创建变量时,一个对象的实际类型是确定的,但它可以指向的引用类型就不确定了
在Person类中写一个run方法,并用s1,s2分别调用该方法
子类重写了父类的方法,因此s4.run执行子类的方法,输出的是son,而s2调用的是Person类,因此无影响
总结:- 子类能调用自己的或者从父类继承的方法
- 父类可以指向子类,但不能调用子类独有的方法
- 对象能执行的方法有哪些,主要决定于对象左边的类型,但如果一个父类对象调用子类方法,调用的会是重写后的方法
- 对象的类型也能强制转换
父类对象调用子类独有的方法会报错:
强制类型转换后即可调用:
但如果对用Preson类构造器创建的Person类对象用类型强转虽不报错但仍不能正常运行:
提示:- 类型转化异常时会报错:ClassCastException!
- idea注释快捷键ctrl+/行注释,ctrl+shift+/块注释
- 存在条件:继承关系,方法的重写,父类引用指向子类对象
instanceof
判断两个对象之间是否有继承关系
看一个示例,在该示例中,Student类和Teacher类继承Person类,该对象为Student构造器构造的对象,它既是人,又是对象,但不是字符串和老师
再看另一示例:Person类创建的变量与String比较直接报错,因为Person类和String类是并列关系,怎么可能有继承关系
另一种理解:
Person obj=new Student();Student student=(Student) obj;
上述代码中,第一句中发生了自动类型转换,因为是低级转为高级,无需强转
而第二句则是强制类型转换,高级转为低级,需要强转
另外,子类转换为父类,可能会丢失自己的一些方法