1.继承性
1.1为什么要有类的继承性?(继承性的好处)
- 减少了代码的冗余,提高了代码的复用性
- 便于功能的扩展
- 为之后多态性的使用,提供了前提
1.2 Java中继承性的说明
- 一个类可以被多个子类继承。
- Java中类的单继承性:一个类只能有一个父类
- 子父类是相对的概念。
- 子类直接继承的父类,称为:直接父类。间接继承的父类称为:间接父类
- 子类继承父类以后,就获取了直接父类以及所间接父类中声明的属性和方法
1.3 java.lang.Object类的理解
- 如果我们没显式的声明一个类的父类的话,则此类继承于java.lang.Object类
- 所的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang.Object类
- 意味着,所的java类具有java.lang.Object类声明的功能。
1.4练习
package oop.zhong;
public class ManKind {
/**
定义一个ManKind类,包括
成员变量int sex和int salary
方法void manOrWoman()根据sex的值显示man(sex==1)或者woman(sex==0)
方法void employeed()根据salary的值显示“no job”(salary==0)或者“ job”(salary!=0)
*/
private int sex;
private int salary;
public ManKind() {
//super();
}
public ManKind(int sex, int salary) {
//super();
this.sex = sex;
this.salary = salary;
}
public void manOrWoman(){
if(sex == 1){
System.out.println("man");
}else if(sex == 0){
System.out.println("woman");
}
}
public void employeed(){
if(salary == 0){
System.out.println("no job");
}else{
System.out.println("job");
}
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
复制代码
package oop.zhong;
public class Kids extends ManKind{
/**
*定义类Kids继承ManKind,并包括
成员变量int yearsOld
方法printAge()打印yearsOld的值。
*/
private int yearsOld;
public Kids() {
//super();
}
public Kids(int yearsOld) {
//super();
this.yearsOld = yearsOld;
}
public int getYearsOld() {
return yearsOld;
}
public void setYearsOld(int yearsOld) {
this.yearsOld = yearsOld;
}
public void printAge(){
System.out.println("I am " + yearsOld + " years old.");
}
}
复制代码
package oop.zhong;
public class KidsTest {
/**定义类KidsTest,在类的main方法中实例化Kids的对象someKid,
* 用该对象访问其父类的成员变量及方法。
* */
public static void main(String[] args) {
Kids someKid = new Kids(12);
someKid.printAge();
someKid.setSalary(0);
someKid.setSex(1);
someKid.employeed();
someKid.manOrWoman();
}
}
复制代码
2.重写
2.1定义:
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
2.2要求:
- 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
- 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
- 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
- 父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
- 父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是double)
- 子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限(煎饼果子~)
- 子类不能重写父类中声明为private权限的方法
- 子类方法抛出的异常不能大于父类被重写方法的异常
2.3注意:
子类与父类中同名同参数的方法必须同时声明为非static的(即为重写),或者同时声明为static的(不是重写)。因为static方法是属于类的,子类无法覆盖父类的方法。
2.4练习
/*修改定义的类Kids,在Kids中重新定义employeed()方法,
* 覆盖父类ManKind中定义的employeed()方法
* 输出“Kids should study and no job.”
* */
复制代码
2.5区分方法的重写和重载?
-
二者的概念:
-
重载和重写的具体规则:
-
表现形式:
- 重载:不表现为多态性。
- 重写:表现为多态性。
重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。
Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。 对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为**“早绑定”或“静态绑定”**;
而对于多态,只等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为**“晚绑定”或“动态绑定”**。
引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚绑定,它就不是多态。”
3.权限修饰符
4.关键字super
/*
* super关键字的使用
* 1.super理解为:父类的
* 2.super可以用来调用:属性、方法、构造器
*
* 3.super的使用:调用属性和方法
*
* 3.1 我们可以在子类的方法或构造器中。通过使用"super.属性"或"super.方法"的方式,显式的调用
* 父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
* 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显式的
* 使用"super.属性"的方式,表明调用的是父类中声明的属性。
* 3.3 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显式的
* 使用"super.方法"的方式,表明调用的是父类中被重写的方法。
*
* 4.super调用构造器
* 4.1 我们可以在子类的构造器中显式的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
* 4.2 "super(形参列表)"的使用,必须声明在子类构造器的首行!
* 4.3 我们在类的构造器中,针对于"this(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
* 4.4 在构造器的首行,没有显式的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
* 4.5 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器
*/
复制代码
5.Instance继承性
/*
* 子类对象实例化的全过程
*
* 1. 从结果上来看:(继承性)
* 子类继承父类以后,就获取了父类中声明的属性或方法。
* 创建子类的对象,在堆空间中,就会加载所有父类中声明的属性。
*
* 2. 从过程上来看:
* 当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,...
* 直到调用了java.lang.Object类中空参的构造器为止。正因为加载过所有的父类的结构,所以才可以看到内存中有
* 父类中的结构,子类对象才可以考虑进行调用。
*
*
* 明确:虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
*
*/
public class InstanceTest {
}
复制代码
5.1Instance继承性和super练习
//不贴了
复制代码
6.多态
package oop.polymorphism;
/*
* 面向对象特征之三:多态性
*
* 1.理解多态性:可以理解为一个事物的多种形态。
* 2.何为多态性:
* 对象的多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)
*
* 3. 多态的使用:虚拟方法调用
* 有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。
* 总结:编译,看左边;运行,看右边。
*
* 4.多态性的使用前提: ① 类的继承关系 ② 方法的重写
*
* 5.对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
*/
public class PersonTest {
public static void main(String[] args) {
Person p1 = new Person();
p1.eat();
Man man = new Man();
man.eat();
man.age = 25;
man.earnMoney();
System.out.println("********************************");
//对象的多态性:父类的引用指向子类的对象
Person p2 = new Man();
//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
p2.eat();//Ctrl到Person
p2.walk();
//p2.earnMoney();//报错。
//earnMoney() is undefined for the type Person
System.out.println(p2.id);//1001
//Person1001 Man1002
}
}
复制代码
6.1举例
package oop.polymorphism;
import java.sql.Connection;
public class AnimalTest {
public void func(Animal animal){//Animal animal = new Dog();
animal.eat();
animal.shout();
// if(animal instanceof Dog){
// Dog d = (Dog)animal;
// d.watchDoor();
// }
}
public static void main(String[] args) {
AnimalTest test = new AnimalTest();
test.func(new Dog());
//狗吃骨头
//汪!汪!汪!
test.func(new Cat());
//猫吃鱼
//喵!喵!喵!
}
// public void func(Dog dog){
// dog.eat();
// dog.shout();
//}
//public void func(Cat cat){
// cat.eat();
// cat.shout();
//}
}
class Animal{
public void eat(){
System.out.println("动物:进食");
}
public void shout(){
System.out.println("动物:叫");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void shout(){
System.out.println("汪!汪!汪!");
}
public void watchDoor(){
System.out.println("看门");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void shout(){
System.out.println("喵!喵!喵!");
}
}
//举例二:
class Order{
public void method(Object obj){
//只要Object,就能继承重写,能用多态
}
}
//举例三:
class Driver{
public void doData(Connection conn){
// conn = new MySQlConnection(); / conn = new OracleConnection();
//规范的步骤去操作数据
// conn.method1();
// conn.method2();
// conn.method3();
//MySQlConnection或者OracleConnection的method都可以重写后直接在这调用
}
}
复制代码
6.2多态的不适用性
//对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)
//对象的多态性:父类的引用指向子类的对象
Person p2 = new Man();
System.out.println(p2.id);//1001
//Person1001 Man1002
复制代码
6.3虚拟方法调用
package oop.polymorphism1;
import java.util.Random;
//面试题:多态是编译时行为还是运行时行为?运行
//证明如下:
class Animal {
protected void eat() {
System.out.println("animal eat food");
}
}
class Cat extends Animal {
protected void eat() {
System.out.println("cat eat fish");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("Dog eat bone");
}
}
class Sheep extends Animal {
public void eat() {
System.out.println("Sheep eat grass");
}
}
public class InterviewTest {
public static Animal getInstance(int key) {
switch (key) {
case 0:
return new Cat ();
case 1:
return new Dog ();
default:
return new Sheep ();
}
}
public static void main(String[] args) {
int key = new Random().nextInt(3);
System.out.println(key);
Animal animal = getInstance(key);
animal.eat();
}
}
复制代码