目录
封装
封装:隐藏对象的内部细节,对外提供接口(访问方式)。
封装的原则:将类的某些信息隐藏在类内部,不允许外界直接访问,而是给外界提供接口(方法)。外 界通过接口访问内部的数据以及类的功能。
private 私有的
private可以修饰类中的属性和方法,修饰属性的时候,表示属性私有,外界无法直接访问
所谓的直接访问是通过对象名.属性名访问,但在属性所在的类中可以访问
通过setter、getter方法访问属性
继承
Java提供了继承(inherit)功能。Java中通过extends关键字来实现继承。
父类:在继承关系里,被继承的类叫做父类,也叫基类或超类。
子类:在继承关系里,继承别的类的类叫子类,也叫派生类。
继承的语法:
public class 类名 extends 父类名{
//属性
//方法
}
super关键字
在java中,super表示超类(就是我们俗称的父类),当子类需要引用父类的字段时,我们就可以使用super.FieldName.
super只对公有字段起作用
super()之构造方法
构造方法的super()必须放在函数体第一句
子类构造方法默认会调用super(),如果父类(超类)没有默认的构造方法(就是没有参数的构造方法),super(参数列表)就会和有参的构造函数冲突。这时子类就必须显式调用super(),并且必须使用父类中的某个构造方法的参数。
super()之成员方法
对于可继承的成员函数,如果子类在重写父类的方法同时想要调用(实现)与父类相同的方法,那么就用super.func(obj,obj,…)。与构造函数不同的是,super.func()可以不用放在函数一开始的位置,而构造方法的super()必须放在函数体中最前面的位置。
super()之成员变量
通过super.变量名就可以在子类中访问父类的成员变量,但是只有protected和public的成员变量可以被访问,而private的变量子类是访问不到的。
super只是关键字,而this是当前对象
this()调用本类中的构造方法,写在构造方法第一行;
父类、子类构造方法
子类可以从父类中继承属性和方法,无法继承构造方法,但可以调用父类中的构造方法为我们继承过来 的属性赋值。
继承中构造方法的访问特点:如果子类构造方法中没有明确写出调用哪个父类构造方法,会默认调 用父类的无参构造方法,即super(); -----即使你没有写super(),系统也会默认在第一行代码中调用 super()。如果父类不提供无参构造方法,提供有参数的构造方法,子类会报错。
成员方法
继承中实例方法的访问特点:
1.首先在子类中查找要调用的方法,如果有直接调用;
2.如果没有, 在父类中查找要调用的方法,如果有就执行;
3.如果没有,继续向上找父类,如果更上一级父类中 有要调用的方法,就执行,如果没有继 续向上找,直到根类Object,如果Object中也没有,就报错。
方法重写
方法重写:在继承关系里,如果子类中的某个方法和父类中的方法相同(方法名和参数也要相同),称为子类重写了父类的方法。
子类重写父类方法往往是因为父类的方法满足不了子类的需求,所以子类才需要自己实现这个方法。
方法重写、方法重载的区别:
方法重载:在同一个类中,如果多个方法具有相同的方法名,但是参数个数或者参数类型不同(或 都不同),这称为方法的重载。
方法重写:在继承关系里,父类的实现满足不了子类的需求,子类可以重新实现父类中定义的方 法,这是方法重写。
如果子类重写了父类的方法,我们习惯上在重写的方法上面添加@Override注解。@Override注解的作用是检测方法是否和父类中的方法相同。
父类子类成员变量
在继承中,子类对象的堆区内存里,既会有子类自身实例变量,也会有父类继承来的实例变量。如 果子类和父类有同名的变量,堆内存会有2个变量。
两个变量不会互相覆盖
总结
继承是Java提供一种语法,这种语法允许子类得到父类的属性和方法。
继承能在保证程序功能不变的情况下,大大简化代码量,因此继承能帮我们更好的去设计类。
在Java中使用extends关键字实现继承。被继承的类叫做父类,或超类,或基类。
继承的特点
- 1. 一个类只能有一个父类。----不允许多继承
- 子类会继承父类全部的属性和方法(私有的也能继承,只是不能直接访问),无法继承构造方法。
- 如果要访问父类中的属性、方法、构造方法使用super关键字。
- 子类可以重写父类的方法。调用时默认调用子类的方法
- 可以多层继承。A extends B,B extends C,这样A将拥有B和C中的内容
- 所有类的根类是Object。如果一个类没有继承任何类,默认继承Object类。
- 通常在子类的构造方法中调用父类的构造方法。
利
1. 提高了代码的复用性(多个类相同的内容可以放到同一个类中)。
2. 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)
弊
继承让类与类之间产生了关联,类的耦合性增强了,当父类发生变化时,子类也不得不跟着变化, 削弱了子类的独立性。
多态
多态:指的是对象的多态性,同一对象在不同时刻表现出来的不同形态。
eg:
我们可以说猫是猫:猫 cat = new 猫();
也可以说猫是动物:动物 animal = new 猫();
这里猫在不同的时刻表现出来了不同的形态,就是多态。
多态的前提:
- 有继承或者实现关系
- 有方法重写
- 父类引用指向子类对象(或子类的对象赋值给父类的引用)
实现关系:,类和接口(interface)就是实现关系,类实现接口。 实现关系也可以看成是继承关系
在Java中多态有2种:
- 父类名 对象名 = new 子类()
- 接口名 对象名 = new 实现类()
多态中成员的访问特点⭐⭐⭐⭐⭐
因为实例方法有重写,实例变量没有。所以实例变量和实例方法的访问不一样
(属性没有多态,方法有多态)
Animal animal2 = new Cat();//父类引用指向子类对象(或子类的对象赋值给父类的引用)
animal2.a; //a的值为父类Animal中的a,
animal2.eat(); //编译器期eat()方法为父类中的方法 运行期eat()方法为父类中的方法
故如果父类中没有eat()方法,会在编译期报错;
因此父类不能使用子类独有的方法
animal2.getA();//调用get方法访问得到的是子类的属性值(因为get方法是子类的方法)⭐
编译期:Java源代码(.java)编译成字节码文件(.class)的时期。
运行期:运行字节码的时期。
成员 | 编译器 | 运行期 |
---|---|---|
成员变量(实例变量) | 看等号左边(即父类) | 看等号右边(即父类) |
实例方法(成员方法) | 看等号左边(即父类) | 看等号右边(即子类) |
多态的应用
参数多态
p.raiseAnimal(cat);//猫可以看做动物。raiseAnimal要求的参数是Animal(即父类 型),我们把子类型赋值给了父类型,这就是多态。
p.raiseAnimal(dog);//狗可以看做动物。raiseAnimal要求的参数是Animal(即父类 型),我们把子类型赋值给了父类型,这就是多态。
数组元素多态
//创建Animal数组存放猫和狗。---多态
Animal[] animals = new Animal[6];
animals[0] = c1;//把Cat看成Animal存入数组
animals[1] = c2;//把Cat看成Animal存入数组
animals[2] = c3;//把Cat看成Animal存入数组
animals[3] = d1;//把Dog看成Animal存入数组
animals[4] = d2;//把Dog看成Animal存入数组
animals[5] = d3;//把Dog看成Animal存入数组
for(int i = 0; i < animals.length; i++) {
Animal a = animals[i];
a.eat();//多态的对象在运行期,执行子类的方法。
}
数组元素或方法返回值多态
用Animal数组存放Cat和Dog。遍历数组,如果元素是猫,执行抓老鼠的方法,如果是狗执 行看门方法。
//创建猫和狗
Cat c1 = new Cat();
Cat c2 = new Cat();
Cat c3 = new Cat();
Dog d1 = new Dog();
Dog d2 = new Dog();
Dog d3 = new Dog();
//创建Animal数组存放猫和狗。---多态
Animal[] animals = new Animal[6];
animals[0] = c1;//把Cat看成Animal存入数组
animals[1] = c2;//把Cat看成Animal存入数组
animals[2] = c3;//把Cat看成Animal存入数组
animals[3] = d1;//把Dog看成Animal存入数组
animals[4] = d2;//把Dog看成Animal存入数组
animals[5] = d3;//把Dog看成Animal存入数组
for(int i = 0; i < animals.length; i++) {
Animal a = animals[i];
if(a instanceof Cat) {
Cat c = (Cat)a;//强制类型转换
c.catchMouse();
}else if(a instanceof Dog) {
Dog d = (Dog)a;
d.lookDoor();
}
}
Dog d = (Dog)a;//使用强制类型转换,使(主类)Animal类型的a转换成(子类)Dog类型
进而使用子类中独有的成员方法
父类实例不能使用子类独有的方法
返回值多态:
public class AnimalManager {//动物管理员类
public Animal getAnimalByIndex(int index) {
Cat c1 = new Cat();//猫猫类对象实例
Cat c2 = new Cat();
Cat c3 = new Cat();
Dog d1 = new Dog();//狗狗类对象实例
Dog d2 = new Dog();
Dog d3 = new Dog();
Animal[] animals = new Animal[6];//父类对象数组
animals[0] = c1;//把子类实例赋给父类数组
animals[1] = c2;
animals[2] = c3;
animals[3] = d1;
animals[4] = d2;
animals[5] = d3;
return animals[index];//这里是返回一个父类Animal对象实例,它可以用子类Cat和子类Dog代替
}
}
public class ClassTest {
public static void main(String[] args) {
AnimalManager am = new AnimalManager();
Cat a = (Cat)am.getAnimalByIndex(0);
a.eat();
a.catchMouse();
Dog b = (Dog)am.getAnimalByIndex(3);
b.eat();
b.lookDoor;
}
}
intanceof关键字
作用:判断对象是不是某个类的实例。
例如:a instanceof Cat是判断对象a是否是Cat类的实例,如果是就返回true,否则就是false 如果a是Cat子类的实例,Cat继承于Animal,那么a instanceof Animal也是true。
向上转型:子类类型转换为父类类型。即把子类对象赋值给父类引用。系统自动完成。
向下转型:父类类型转换为子类类型。需要强制类型转换。
方法的返回值类型也可以使用多态(即父类型),实际返回的是子类对象。
多态的好处和弊端
好处:提高了程序的扩展性,容易设计出通用的代码。
弊端:屏蔽了子类独有的功能。(不过,可以强转类型)
总结
- Java中继承使用extends关键字来完成。
- 子类能从父类继承所有属性和方法(不能继承构造方法,构造方法的方法名必须和类名相同)。
- 不能盲目继承,两个类满足is a关系时才使用继承。 例如:狗可以继承动物,香蕉可以继承水果等。
- 子类继承父类后,发现父类继承来的方法不满足自己的需要,子类可以重写父类中继承过来的方法。
- 子类想访问父类中的内容可以借助super关键字。
- 多态指的是把子类当做父类来使用,但执行方法时执行的还是子类重写后的方法。例如:把猫当做动物 来使用,调用eat()方法时,执行的是猫的eat()方法,不是父类的eat()方法。
- 多态能写出通用代码。