面向对象的语言有三大特征:封装、继承、多态
特征一:封装性(encapsulation)
为什么需要封装性
理论上:
- 高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
- 低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。
何为封装性
封装可以隐藏对象的内部实现细节,控制对象的修改与访问权限
Java如何实现数据封装
-
实现封装就是控制类或成员的可见性范围。这就需要依赖访问控制修饰符,也称为权限修饰符来控制。
-
权限修饰符:public、protected、缺省、private
修饰符 本类内部 本包内 其他包的子类 其他包非子类 private √ × × × default(缺省) √ √ × × protected √ √ √ × public √ √ √ √ 具体修饰的结构:
- 外部类:public、缺省
- 成员变量、成员方法、构造器、成员内部类:public、protected、缺省、private
封装性的体现
- 私有化(private)类的属性,提供公共(public)的get、set方法,对此属性进行获取和修改
- 将类中不需要对外暴露的方法,设置为private
- 单列模式中构造器private的了,避免在类的外部创建实例
封装的具体使用
属性封装
格式 :private 数据类型 属性;
例如:private修饰符将属性定义为私有属性,外部类无法访问,只能通过我们设置的共有方法get和set对属性进行操作
方法封装
格式:private 返回值类型 方法名 (){}
特征二:继承性
父类:(超类、基类)
子类:(派生类)
怎样去继承:子类extends(关键字)父类
注意:子类可以继承父类中私有和非私有成员,但是不能使用父类中私有成员
构造方法不能继承
概述:子类继承父类,可以直接使用父类中非私有成员,子类无需写重复代码,提高了代码的复用性
成员访问特点:
- 成员变量:看等号左边是谁,先调用谁中的成员变量,子类没有找父类
- 成员方法:看new的是谁,先调用谁的成员方法,子类没有找父类
方法重写的使用场景
- 概述:子类中有一个和父类从方法名及参数列表一样的方法
- 使用场景:功能升级改造,子类需要对父类的中已经实现好的功能进行重新改造
- 验证:@Override
- 前提:继承
- 访问:看new的是谁,先调用谁的,如果new的是子类,先调用子类重写的方法,子类没有找父类
- 注意事项:
- 子类重写父类方法之后,权限必须要保证大于等于父类权限
- 子类方法重写父类方法,方法名和参数列表要一样
- 私有方法、构造方法、静态方法不能被重写
- 子类重写父类方法之后,返回值类型应该是父类方法返回值类型的子类类型
继承中构造方法的特点
注意this、super关键字的使用
-
注意:new子类对象时,会先初始化父类(先走父类无参构造法)
-
原因:
每个构造方法的第一行,默认都会有一个super()
super()代表的是父类无参构造,在未声明时,会自动默认有super()
public class fu { public fu(){ System.out.println("我是父类中的无参构造"); } } public class zi extends fu { public zi() { System.out.println("我是子类中的无参构造"); } public zi(int x){ System.out.println("我是子类中的有参构造"); } } public class fuziText { public static void main(String[] args) { zi zi = new zi(); System.out.println("______"); zi zi1 = new zi(10); } }
输出: 我是父类中的无参构造 我是子类中的无参构造 ______ 我是父类中的无参构造 我是子类中的有参构造
继承的特点
- 继承只能是单继承,不能是多继承(即只能有一个父类)。
- 继承支持多层继承(即a继承b,b继承c)。
- 一个父类可以有多个子类。
- 构造方法、私有方法及静态方法可以被继承,但是不可以被重写。
为父类私有属性赋值
例:
public class student {
private String name;
private int age;
public student(){
}
public student(String name, int age){
this.name = name;
this.age = 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 work(){
System.out.println("工作");
}
}
public class teacher extends student{
}
public class manager extends student{
public manager() {
}
public manager(String uname, int uage) {
super(uname,uage);
}
}
public class textts {
public static void main(String[] args) {
teacher teacher = new teacher();
teacher.setName("理论");
teacher.setAge(20);
System.out.println(teacher.getName() + "..." + teacher.getAge());
manager manager = new manager("看看",24);
System.out.println(manager.getName() + "..." + manager.getAge());
}
}
输出:
理论...20
看看...24
特征三:多态性
介绍与基本使用
1.前提:
必须有子类继承或者接口实现关系
必须有方法的重写(没有重写,多态没有意义),多态主要玩的是重写方法
new对象:父类引用指向子类对象
Fu fu = new Zi()理解为大类型接收了一个小类型的数据
比如:double b = 10
2.注意:
多态下不能直接调用子类特有功能
public abstract class animal {
public abstract void eat();
public abstract void drink();
}
public class cat extends animal{
public void eat() {
System.out.println("cateat");
}
@Override //判断是否为方法重写
public void drink(){
System.out.println("catdrink");
}
public void aaa(){
System.out.println("cataaa");
}
}
public class dog extends animal {
public void eat() {
System.out.println("dogeat");
}
public void drink(){
System.out.println("dogdrink");
}
public void walk(){
System.out.println("dogwalk");
}
}
public class acdtext {
public static void main(String[] args) {
dog dog = new dog();
dog.eat();
dog.drink();
dog.walk();
System.out.println("_____");
cat cat = new cat();
cat.eat();
cat.drink();
cat.aaa();
System.out.println("_____");
//多态,父类调用子类重写,但不可直接调用子类特有
animal animal = new dog();
animal.eat();
animal.drink();
// animal.walk(); 此方法为子类特有,调用会报错
}
}
输出:
dogeat
dogdrink
dogwalk
_____
cateat
catdrink
cataaa
_____
dogeat
dogdrink
多态条件下成员的访问特点
成员变量与成员方法
对于成员变量来说:看等号左边是谁,先调用谁中的成员变量
对于方法来说:new的是谁,先调用谁中的成员方法,子类没有,找父类
public class fuziText {
public static void main(String[] args) {
fu fu = new zi();
System.out.println(fu.num);
fu.method();
}
}
public class zi extends fu {
int num = 100;
@Override
public void method(){
System.out.println("我是子类中的method方法");
}
}
public class fuziText {
public static void main(String[] args) {
fu fu = new zi();
System.out.println(fu.num);
fu.method();
}
}
输出:
1000
我是子类中的method方法
多态的好处
1.多态方式和原始方法new对象的优缺点:
原始方式:
优点:既能调用重写的,还能调用父类非私有的,还能调用自己特有的
缺点:扩展性差
多态方式:
优点:扩展性强
缺点:不能直接调用子类特有功能
public abstract class animal {
public abstract void eat();
public abstract void drink();
}
public class cat extends animal{
public void eat() {
System.out.println("cateat");
}
@Override //判断是否为方法重写
public void drink(){
System.out.println("catdrink");
}
public void aaa(){
System.out.println("cataaa");
}
}
public class dog extends animal {
public void eat() {
System.out.println("dogeat");
}
public void drink(){
System.out.println("dogdrink");
}
public void walk(){
System.out.println("dogwalk");
}
}
public class acdtext {
public static void main(String[] args) {
animal animal = new dog();
animal.eat();
animal = new cat();
animal.eat();
dog dog = new dog();
method(dog);
cat cat = new cat();
method(cat);
}
public static void method(animal animal) {//animal animal = dog animal animal = cat
animal.eat();
}
}
输出:
dogeat
cateat
dogeat
cateat
形参传递父类类型,调用此方法父类类型可以接收任意他的子类对象
传递那个子类对象,就指向那个子类对象,就调用那个子类对象重写的方法
多态中的转型
向上转型
父类引用指向子类对象
好比:double b = 1;
向下转型
1.向下转型:好比强转,将大类型强转成小类型
2.表现方式:
父类类型 对象名1 = new 子类对象()
double b = 1;
子类类型 对象名2 = (子类类型)对象名1
int i = (int)b;
3.想要调用子类特有功能,我们就需要向下转型
public abstract class animal {
public abstract void eat();
public abstract void drink();
}
public class dog extends animal {
public void eat() {
System.out.println("dogeat");
}
public void drink(){
System.out.println("dogdrink");
}
public void walk(){
System.out.println("dogwalk");
}
}
public class acdtext {
public static void main(String[] args) {
//向上转型
animal animal = new dog();
animal.eat();
//向下转型
dog dog = (dog) animal;
dog.walk();
}
}
输出:
dogeat
dogwalk
转型中可能出现的问题
1.如果等号左右两边类型不一致,会出现类型转换异常(ClassCastException)
2.解决:
在向下转型之前,先判断类型
3.怎么判断类型: instanceof
判断结果是 boolean 型
4.使用:
对象名 instanceof 类型
判断的是关键字前面的对象是否符合关键字后面的类型
public abstract class animal {
public abstract void eat();
public abstract void drink();
}
public class cat extends animal{
public void eat() {
System.out.println("cateat");
}
@Override //判断是否为方法重写
public void drink(){
System.out.println("catdrink");
}
public void aaa(){
System.out.println("cataaa");
}
}
public class dog extends animal {
public void eat() {
System.out.println("dogeat");
}
public void drink(){
System.out.println("dogdrink");
}
public void walk(){
System.out.println("dogwalk");
}
}
public class acdtext {
public static void main(String[] args) {
dog dog= new dog();
method(dog);
System.out.println("------");
cat cat= new cat();
method(cat);
}
public static void method(animal animal) {
animal.eat();
/*这里会出现类型转换异常(ClassCastException)
原因:当调用method,传递cat对象时,animal代表的就是cat对象
此时我们将代表cat对象的animal强转成了dog
此时等号左右两边类型不一致了,所以出现了类型转换异常
dog dog = (dog) animal;
dog.walk();
*/
if(animal instanceof dog) {
dog dog = (dog) animal;
dog.eat();
dog.walk();
}
if(animal instanceof cat) {
cat cat = (cat) animal;
cat.eat();
cat.aaa();
}
}
}
输出:
dogeat
dogeat
dogwalk
------
cateat
cateat
cataaa
Instanceof关键字
意义:判断对象与我们是否属于这个类或者这个类的子类创建的对象
是Java中的二元运算符,左边是对象,右边是类;当对象是右边类或子类创建的对象时,返回true;否则,返回false。