Java入门之继承多态使用及说明
作者:小菘爱编程
Java继承多态
本文主要讲述继承多态的基本知识,后续会专门出代码篇
1.继承
- 概念:继承就是对每个类的共性进行了抽取,从共性的类索取。
- 实例:
public class Dog { public String name; public int age; public void run(){ System.out.println(this.name+"正在玩球"); } } class Cat { public String name; public int age; public void run() { System.out.println(this.name + "正在奔跑"); } }
其中我们不难发现狗和猫这两个类有太多的重合,所以为了代码的简化优化,我们可以将两个类相同的进行抽取,定义出新的一个类"Animal"。
- 下面是演示
public class Text extends Animal { public static void main(String[] args) { Dog dog = new Dog(); dog.run("小黄"); } } class Cat extends Animal { } class Dog extends Animal{ } class Animal{ public String name; public int age; public void run(String name) { this.name=name; System.out.println(this.name + "正在奔跑"); } }
输出结果:小黄正在奔跑
其中"extends"关键字代表继承的含义,这样我们就实现了代码的简洁优化。
- 什么是子类和父类?
在Java中子类是继承父类的,上述代码狗和猫就是子类,动物是父类。
- 如果子类也有成员方法与父类的成员方法同名访问的是子类还是父类呢?
下面是演示:
public class Text extends Animal { public static void main(String[] args) { Dog dog = new Dog(); dog.eat("小黄"); } } class Dog extends Animal{ public void eat(String name){ this.name=name; System.out.println(this.name+"正在吃狗粮"); } } class Animal{ public String name; public int age; public void eat(String name){ this.name=name; System.out.println(this.name+"正在吃饭"); } }
输出:小黄正在吃狗粮
如果访问的成员方法子类中有,优先访问自己的成员变量
同理我们也可以推导出:如果访问的成员变量子类中有,优先访问自己的成员变量
- 若成员方法的名不同那么该如何访问?
public class Base { public void methodA(){ System.out.println("Base中的methodA()"); } } public class Derived extends Base{ public void methodB(){ System.out.println("Derived中的methodB()方法"); } public void methodC(){ methodB(); // 访问子类自己的methodB() methodA(); // 访问父类继承的methodA() // methodD(); // 编译失败,在整个继承体系中没有发现方法methodD() } }
2.super关键字
super关键字是专门用来访问父类的成员变量与this关键字的用法基本相同
- 1.可以访问父类的成员变量
- 2.可以访问父类的成员方法
- 3.可以访问父类的构造方法
- 4.只能在方法中的第一行使用
- 5.只能在类的非静态方法中使用,用来访问非静态成员方法和字段
示例:
public class Text { public static void main(String[] args) { Dog dog=new Dog(); dog.text(); } } class Dog extends Animal{ public void text(){ super.eat("大黑",10); } } class Animal{ public String name; public int age; public void eat(String name,int age){ this.age=age; this.name=name; System.out.println(this.name+this.age+"岁"+"正在吃饭"); } }
输出:大黑10岁正在吃饭
public class Text { public static void main(String[] args) { Dog dog=new Dog(); dog.text(); } } class Dog extends Animal{ public String name="huang"; public void text(){ System.out.println(super.name); } } class Animal{ public String name="大黑"; public int age; }
输出:大黑
3.子类父类的构造方法
- 在讲super引用构造方法前先了解子类父类的构造方法
父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法
class Dog extends Animal{ public String name="huang"; public Dog(String name, int age) { super(name, age); } } class Animal{ public String name; public int age; public Animal(String name, int age) { this.name = name; this.age = age; } }
如果父类出现了构造方法且带参数子类必须也需要出现构造方法,且需要将父类的构造方法的参数值初始化用super()关键字。
class Dog extends Animal{ public String name="huang"; public Dog(String name, int age) { } } class Animal{ public String name; public int age; public Animal() { this.name = name; this.age = age; }
如果父类的构造方法没有参数则不需要子类必须使用super(),因为系统会默认给一个super()或者可以不写子类的构造方法系统也会默认有子类的构造方法。
4.代码块与方法的执行顺序
- 什么是代码块?
代码块有静态代码块和实例的代码块
static { System.out.println("a"); }//静态 { System.out.println("a"); }//实例
如果一个程序有代码块,构造方法,子类父类顺序是怎样的呢?
- 先执行父类静态代码块再执行子类的静态代码块
- 再执行父类的实例代码块
- 再执行父类的构造方法
- 再执行子类的实例代码块
- 最后执行子类的构造方法
class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; System.out.println("cccc"); } { System.out.println("bbbb"); } static { System.out.println("aaaa"); } } public class Text{ public static void main(String[] args) { Person person1 = new Person("2",10); System.out.println("============================"); Person person2 = new Person("1",20); } }
输出:
aaaa
bbbb
cccc
bbbb
cccc
所以静态代码块只执行一次!并优先执行!
在使用访问限定符时我们要尽可能小范围,因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用 public。
5.向上转型
这里使用于子类访问父类的对象
- 三种形式
public class Text { public static void main(String[] args) { Animal animal=new Dog(); } } class Dog extends Animal{ } class Animal{ }//直接转型
public class Text { public static void main(String[] args) { Dog dog=new Dog(); fun(dog); } public static void fun(Animal animal){ } }//利用方法转型
public class Text { public static void main(String[] args) { Animal animal=fun(); } public static Animal fun(){ Dog dog=new Dog(); return dog; } }//利用返回值
- 向上转型的缺点
当子类有父类没有的成员方法时,不能用父类的引用指向子类的成员方法
public class Text { public static void main(String[] args) { Animal animal=fun(); animal.bark();//编译器会报错 } public static Animal fun(){ Dog dog=new Dog(); return dog; } } class Dog extends Animal{ public void bark(){ System.out.println("狗叫"); } }
6.动态绑定
当子类完成了向上转型,子类与父类的方法构成了重写,此时animal.bark()就要调用子类的成员方法
- 什么是重写
重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 类名返回值和形参都不能改变
示例:
public class Text { public static void main(String[] args) { Animal animal=new Dog("小黄",10); animal.eat(); } } class Animal { public String name; public int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat() { System.out.println(this.name + " 正在吃饭....."); } } class Dog extends Animal { public Dog(String name, int age) { super(name, age); } public void bark() { System.out.println(this.name + " 正在汪汪汪叫..."); } @Override public void eat() { System.out.println(this.name + " 正在吃狗粮..."); } }
输出:小黄 正在吃狗粮…
结语
以上是Java继承的内容,下次小编会带来多态的内容,希望读者们多提建议。
最后小编整理了一道题目
如下代码的 结果是什么 ? class Base { Base() { System.out.print("Base"); } } public class Alpha extends Base { public static void main( String[] args ) { new Alpha();//1 //调用父类无参的构造方法 new Base();//2 } } A.Base B.BaseBase C.编译失败 D.代码运行但没有输出 E.运行时抛出异常
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。