一.继承
1.相关概念
1.1继承概念
java针对多个类中有相同的部分的话,可以将相同的部分提取出来,单独放到一个类中A, 然后其他类与这个A类产生一个关系,这样的话 其他类中就拥有了A类中的属性或者行为。这个关系叫做继承, java提供了一个关键字 extends来表示继承关系
1.2子类与父类
类在继承关系中称之为子类/派生类,父类在继承关系中称之为父类/基类/超类
1.3继承的好处
1.提高了代码的复用性:多个类相同的成员可以放到同一个类中
2.提高了代码的维护性:如果功能的代码需要修改,修改一处即可
3.让类与类之间产生了关系,是多态的前提:其实这也是继承的一个弊端:类的耦合性很强
1.4相关格式
class 子类类名 extends 父类名
package com.shujia.day7;
class Person{
String name;
int age;
public void study(){
System.out.println("学习");
}
public void eat(){
System.out.println("吃饭");
}
}
class Student extends Person{
}
public class ExtendsDemo1 {
public static void main(String[] args) {
Student student = new Student();
student.study();
student.eat();
}
}
/*运行结果
学习
吃饭
*/
2.继承的特点
2.1子类无法继承父类的构造方法
package com.shujia.day7;
class Person1{
String name;
int age;
public Person1() {
}
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
public void study(){
System.out.println("学习");
}
public void eat(){
System.out.println("吃饭");
}
}
//创建子类
class Student2 extends Person1{
}
public class ExtendsDemo2 {
public static void main(String[] args) {
// Student2 student2 = new Student2("NAME",18);报错原因是子类无法继承父类的构造方法
}
}
子类可以自己添加自己的构造方法
package com.shujia.day7;
class Person1{
String name;
int age;
public Person1() {
}
public Person1(String name, int age) {
this.name = name;
this.age = age;
}
public void study(){
System.out.println("学习");
}
public void eat(){
System.out.println("吃饭");
}
}
//创建子类
class Student1 extends Person1{
public Student1() {
}
public Student1(String name, int age) {
this.name=name;
this.age=age;
}
}
public class ExtendsDemo2 {
public static void main(String[] args) {
// Student2 student2 = new Student2("NAME",18);报错原因是子类无法继承父类的构造方法
Student1 student1 = new Student1("kkk",18);//这样可以的原因是子类自己写了自己的构造方法
}
}
2.2无法多继承,只允许单继承
一个子类无法同时继承2个类 例如
class Zi extends Fu,Mu 这样会报错的
2.3允许多重继承
例如
class Ye
class Fu extends Ye
class Zi extends Fu
2.4子类无法继承父类的私有变量以及私有方法
package com.shujia.day7;
class Fu{
//定义成员变量
String name="qq";
private int age=10;
//定义成员方法
public void fun1(){
System.out.println("aaaaa");
}
private void fun2(){
System.out.println("bbbbb");
}
}
class Zi extends Fu{
}
public class ExtendsDemo3 {
public static void main(String[] args) {
Zi zi = new Zi();
System.out.println(zi.name);
// System.out.println(zi.age); 子类无法继承父类的private变量
zi.fun1();
// zi.fun2() 子类无法继承父类的私有方法
}
}
/*
运行结果
qq
aaaaa
*/
3.继承与成员变量的关系
3.1.就近原则
首先在子类局部范围找
然后在子类成员范围找
最后在父类成员范围找(肯定不能访问到父类局部范围)(且不能访问父类中方法的局部变量)
如果还是没有就报错。(不考虑父亲的父亲…)
package com.shujia.day7;
class Fu1{
int a=10;
}
class Zi1 extends Fu1{
int a=20;
public void show1(){
int a=30;
System.out.println(a);
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Zi1 zi1 = new Zi1();
zi1.show1();
}
}
3.2.获取子类的成员变量
this.子类成员变量名
package com.shujia.day7;
class Fu1{
//定义父类的成员变量
int a=10;
}
class Zi1 extends Fu1{
//定义子类的成员变量
int a=20;
public void show1(){
//定义子类的局部变量
int a=30;
System.out.println(a); //打印局部变量
System.out.println(this.a);//打印子类的成员变量
System.out.println(super.a);//打印父类的成员变量
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Zi1 zi1 = new Zi1();
zi1.show1();
}
}
3.3获取父类成员变量
super.父类成员变量名
package com.shujia.day7;
class Fu1{
//定义父类的成员变量
int a=10;
}
class Zi1 extends Fu1{
//定义子类的成员变量
int a=20;
public void show1(){
//定义子类的局部变量
int a=30;
System.out.println(a); //打印局部变量
System.out.println(this.a);//打印子类的成员变量
System.out.println(super.a);//打印父类的成员变量
}
}
public class ExtendsDemo4 {
public static void main(String[] args) {
Zi1 zi1 = new Zi1();
zi1.show1();
}
}
3.4使用父类的私有成员变量
1.全是私有变量
1.在父类中创建对应属性的set以及get方法还有show方法(因为show方法不是私有的,但是里面展示的是私有成员),然后在测试类中创建子类,再通过子类名.set方法赋值,再通过show方法输出
2.父类中的有参构造方法,在子类中调用,传入的是父类的私有变量(这里的变量不是继承,只是使用),然后在测试类中创建子类,通过有参传值即可
package com.shujia.day7;
//定义父类
class Fu3{
//定义私有成员
private String name;
private int age;
//定义构造无参方法
public Fu3() {
}
//定义有参构造方法
public Fu3(String name, int age) {
this.name = name;
this.age = age;
}
//定义set以及get方法
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;
}
//定义show方法,主要是用来展示成员变量
public void show(){
System.out.println("姓名是:"+this.name);
System.out.println("年龄是:"+this.age);
}
}
//定义子类
class Zi3 extends Fu3{
//调用父类的构造方法
//创建子类无参构造方法
public Zi3() {
}
//创建子类有参调用方法
public Zi3(String name, int age) {
super(name, age);
}
}
//定义测试类
public class ExtendsDemo6 {
public static void main(String[] args) {
//测试Fu3类
//创建Fu3对象
Fu3 fu3D1 = new Fu3();
//
// //无参传值
fu3D1.setAge(18);
fu3D1.setName("黄大大");
fu3D1.show();
//有参传值
Fu3 fu3D2 = new Fu3("黄大大", 18);
fu3D2.show();
//测试Zi3类
//创建Zi3对象
Zi3 zi3D3 = new Zi3();
//无参传值
//通过父类的set以及get方法使用父类的私有变量
zi3D3.setName("黄大大");
zi3D3.setAge(18);
zi3D3.show();
//有参传值
Zi3 zi3D4 = new Zi3("黄大大", 18);
zi3D4.show();
}
}
/*
姓名是:黄大大
年龄是:18
姓名是:黄大大
年龄是:18
姓名是:黄大大
年龄是:18
姓名是:黄大大
年龄是:18
*/
2.混合型
package com.shujia.day7;
//定义父类
class Fu3{
//定义私有成员
private String name;
private int age;
int id;
//定义构造无参方法
public Fu3() {
}
//定义有参构造方法
public Fu3(String name, int age,int id) {
this.name = name;
this.age = age;
this.id = id;
}
//定义set以及get方法
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 int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//定义show方法,主要是用来展示成员变量
public void show(){
System.out.println("姓名是:"+this.name);
System.out.println("年龄是:"+this.age);
System.out.println("id是:"+this.id);
}
}
//定义子类
class Zi3 extends Fu3{
//调用父类的构造方法
//创建子类无参构造方法
public Zi3() {
}
//创建子类有参调用方法
public Zi3(String name, int age,int id) {
super(name, age,id);
}
}
//定义测试类
public class ExtendsDemo6 {
public static void main(String[] args) {
//测试Fu3类
//创建Fu3对象
Fu3 fu3D1 = new Fu3();
//
// //无参传值
fu3D1.setAge(18);
fu3D1.setName("黄大大");
fu3D1.setId(1001);
fu3D1.show();
//有参传值
Fu3 fu3D2 = new Fu3("黄大大", 18,1001);
fu3D2.show();
//测试Zi3类
//创建Zi3对象
Zi3 zi3D3 = new Zi3();
//无参传值
//通过父类的set以及get方法使用父类的私有变量
zi3D3.setName("黄大大");
zi3D3.setAge(18);
zi3D3.setId(1001);
zi3D3.show();
//有参传值
Zi3 zi3D4 = new Zi3("黄大大", 18,1001);
zi3D4.show();
}
}
/*
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
*/
4继承与构造方法的关系
4.1.子类默认第一句话有super() (直接初始化父类)
默认调用的是父类的无参构造方法
package com.shujia.day7;
class Fu2{
public Fu2() {
System.out.println("这是父类的构造方法");
}
//定义父类的构造方法
}
class Zi3 extends Fu2{
public Zi3() {
// super(); 默认是第一句话
System.out.println("这是子类的构造方法");
}
}
public class ExtendsDemo5 {
public static void main(String[] args) {
Zi3 zi3 = new Zi3();
}
}
这是父类的构造方法
这是子类的构造方法
想调用有参构造方法直接写
package com.shujia.day7;
class Fu2{
//定义父类的构造方法
public Fu2() {
System.out.println("这是父类的构造方法");
}
//定义父类的有参构造方法
public Fu2(String s){
System.out.println("这是父类的有参构造方法"+s);
}
}
class Zi3 extends Fu2{
public Zi3() {
// super(); 默认是第一句话
//调用父类的有参构造方法
super("黄大大");
System.out.println("这是子类的构造方法");
}
}
public class ExtendsDemo5 {
public static void main(String[] args) {
Zi3 zi3 = new Zi3();
}
}
/*
这是父类的有参构造方法黄大大
这是子类的构造方法
*/
4.2.间接初始化父类
package com.shujia.day7;
class Fu2{
//定义父类的构造方法
public Fu2() {
System.out.println("这是父类的构造方法");
}
//定义父类的有参构造方法
public Fu2(String s){
System.out.println("这是父类的有参构造方法"+s);
}
}
class Zi3 extends Fu2{
public Zi3() {
this("黄大大");
System.out.println("这是子类的构造方法");
}
public Zi3(String s){
super(s);
}
}
public class ExtendsDemo5 {
public static void main(String[] args) {
Zi3 zi3 = new Zi3();
}
}
/*
这是父类的有参构造方法黄大大
这是子类的构造方法
*/
super(…)或者this(….)必须出现在第一条语句
5.继承与成员方法的关系
5.1也遵循就近原则
package com.shujia.day7;
class Fu4{
//定义父类的成员方法
public void fun1(){
System.out.println("打游戏");
}
}
class Zi4 extends Fu4{
//定义子类的成员方法或者说重写父类方法fun1
public void fun1(){
System.out.println("打王者");
}
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
zi4.fun1();
}
}
/*
打王者
*/
5.2子类使用父类的私有方法
在父类中定义一个公有方法来调用父类的私有方法,然后在子类中直接调用这个公有方法
package com.shujia.day7;
//定义父类
class Fu3{
//定义私有成员
private String name;
private int age;
int id;
//定义构造无参方法
public Fu3() {
}
//定义有参构造方法
public Fu3(String name, int age,int id) {
this.name = name;
this.age = age;
this.id = id;
}
//定义set以及get方法
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 int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//定义父类私有方法
private void fun(){
System.out.println("这是父类的私有方法");
}
//普通方法,直接在父类中调用父类的私有方法
public void fun1(){
fun();
}
//定义show方法,主要是用来展示成员变量
public void show(){
System.out.println("姓名是:"+this.name);
System.out.println("年龄是:"+this.age);
System.out.println("id是:"+this.id);
}
}
//定义子类
class Zi3 extends Fu3{
//调用父类的构造方法
//创建子类无参构造方法
public Zi3() {
}
//创建子类有参调用方法
public Zi3(String name, int age,int id) {
super(name, age,id);
}
}
//定义测试类
public class ExtendsDemo6 {
public static void main(String[] args) {
//测试Fu3类
//创建Fu3对象
Fu3 fu3D1 = new Fu3();
//
// //无参传值
fu3D1.setAge(18);
fu3D1.setName("黄大大");
fu3D1.setId(1001);
fu3D1.show();
//有参传值
Fu3 fu3D2 = new Fu3("黄大大", 18,1001);
fu3D2.show();
//测试Zi3类
//创建Zi3对象
Zi3 zi3D3 = new Zi3();
//无参传值
//通过父类的set以及get方法使用父类的私有变量
zi3D3.setName("黄大大");
zi3D3.setAge(18);
zi3D3.setId(1001);
zi3D3.show();
//有参传值
Zi3 zi3D4 = new Zi3("黄大大", 18,1001);
zi3D4.show();
zi3D4.fun1();
}
}
/*
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
姓名是:黄大大
年龄是:18
id是:1001
这是父类的私有方法
*/
6.方法的重写
6.1概念
子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写
6.2使用
1.用@override检测是否能重写
package com.shujia.day7;
class Fu4{
//定义父类的成员方法
public void fun1(){
System.out.println("打游戏");
}
}
class Zi4 extends Fu4{
//定义子类的成员方法或者说重写父类方法fun1
@Override
public void fun1(){
System.out.println("打王者");
}
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
zi4.fun1();
}
}
/*
打王者
*/
2.无法重写父类的私有成员方法
package com.shujia.day7;
class Fu4{
//定义父类的成员方法
public void fun1(){
System.out.println("打游戏");
}
//定义父类私有的成员方法
private void fun2(){
System.out.println("听歌");
}
}
class Zi4 extends Fu4{
//定义子类的成员方法或者说重写父类方法fun1
@Override
public void fun1(){
System.out.println("打王者");
}
// @Override
// private void fun2(){
// System.out.println("听周杰伦");
// } 报错原因是无法重写父类的私有成员方法
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
zi4.fun1();
// zi4.fun2(); 报错原因是无法重写父类的私有成员方法
}
}
/*
打王者
*/
3.可以重写比父类方法修饰符大于等于的修饰符
public>protected>默认>private
package com.shujia.day7;
class Fu4{
//定义父类的成员方法
public void fun1(){
System.out.println("打游戏");
}
//定义父类私有的成员方法
private void fun2(){
System.out.println("听歌");
}
//定义父类的成员方法被默认修饰符修饰
void fun3(){
System.out.println("看小说");
}
}
class Zi4 extends Fu4{
//定义子类的成员方法或者说重写父类方法fun1
@Override
public void fun1(){
System.out.println("打王者");
}
//重写父类的fun2
// @Override
// private void fun2(){
// System.out.println("听周杰伦");
// } 报错原因是无法重写父类的私有成员方法
//重写父类的fun3
@Override
void fun3(){
System.out.println("看斗破苍穹");
}
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
zi4.fun1();
// zi4.fun2(); 报错原因是无法重写父类的私有成员方法
zi4.fun3();
}
}
/*
打王者
看斗破苍穹
*/
4.无法重写父类的静态方法,但是可以使用
package com.shujia.day7;
class Fu4{
//定义父类的成员方法
public void fun1(){
System.out.println("打游戏");
}
//定义父类私有的成员方法
private void fun2(){
System.out.println("听歌");
}
//定义父类的成员方法被默认修饰符修饰
void fun3(){
System.out.println("看小说");
}
//定义父类的静态方法
public static void fun4(){
System.out.println("这是父类的静态方法");
}
}
class Zi4 extends Fu4{
//定义子类的成员方法或者说重写父类方法fun1
@Override
public void fun1(){
System.out.println("打王者");
}
//重写父类的fun2
// @Override
// private void fun2(){
// System.out.println("听周杰伦");
// } 报错原因是无法重写父类的私有成员方法
//重写父类的fun3
@Override
void fun3(){
System.out.println("看斗破苍穹");
}
//定义子类的静态方法
// @Override
// public static void fun4(){
// System.out.println("这是子类的静态方法");
// }//报错原因是子类无法重写父类的静态方法
}
public class ExtendsDemo7 {
public static void main(String[] args) {
Zi4 zi4 = new Zi4();
zi4.fun1();
// zi4.fun2(); 报错原因是无法重写父类的私有成员方法
zi4.fun3();
zi4.fun4(); //这里可以使用父类的静态方法
}
}
/*
打王者
看斗破苍穹
这是父类的静态方法
*/
6.3重写与重载的区别
1、重载是发生在同一个类中的,方法名相同,参数列表不同,与返回值无关的现象
2、重写是发生在继承关系中的,返回值类型,方法名,参数列表都和父类一模一样,只是实现不一样,使用 @Override检测方法能否重写
7.final关键字
7.1类被修饰
不能被继承
7.2引用数据变量被修饰
变量变常量
package com.shujia.day7;
class Final{
int a=10;
final int b=20;
}
class FinalZi extends Final{
public void show(){
a=100;
// b=200; 报错的原因是b前面有fianl修饰,变常量,不能被修改
System.out.println(a);
System.out.println(b);
}
}
public class FinalDemo1 {
public static void main(String[] args) {
FinalZi finalZi = new FinalZi();
finalZi.show();
}
}
/*
100
20
*/
7.3方法被修饰
不能被重写但是可以使用
package com.shujia.day7;
class Fu5{
//定义父类的show1方法
public void show1(){
System.out.println("这是父类的show1方法");
}
//定义父类的被final修饰的show2方法
public final void show2(){
System.out.println("这是父类的被final修饰的show2方法" );
}
}
class Zi5 extends Fu5{
@Override
public void show1(){
System.out.println("这是子类的重写show1方法");
}
// @Override
// public final void show2(){
// System.out.println("这是子类的重写show1方法");
// }报错是因为 被final修饰的父类成员方法无法被重写
}
public class FinalDemo2 {
public static void main(String[] args) {
Zi5 zi5 = new Zi5();
zi5.show1();
zi5.show2();//不能被重写,但是可以使用
}
}
/*
这是子类的重写show1方法
这是父类的被final修饰的show2方法
*/
7.4对象被修饰
可以修改一次不是被final修饰的变量
package com.shujia.day7;
class Demo1{
int a=10;
}
public class FinalDemo3 {
public static void main(String[] args) {
final Demo1 demo1 = new Demo1();
demo1.a=100;
System.out.println(demo1.a);
}
}
/*
100
*/
7.5注意事项
1.被final修饰的变量,必须要手动赋值之后才能使用,并且只能赋值一次
package com.shujia.day7;
class Demo2{
int a=2;
// final int b; 报错的原因被fianl修饰的变量必须手动赋值才能使用
}
public class FinalDemo4 {
}
2.必须在构造方法结束之前手动赋值
a.使用构造代码块进行赋值
package com.shujia.day7;
class Demo2{
int a=2;
// final int b; 报错的原因被fianl修饰的变量必须手动赋值才能使用
final int b;
// 使用代码块手动赋值
{
b=100;
}
}
public class FinalDemo4 {
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
System.out.println(demo2.b);
}
}
b.在构造方法内部进行赋值
package com.shujia.day7;
class Demo2 {
int a = 2;
// final int b; 报错的原因被fianl修饰的变量必须手动赋值才能使用
final int b;
//构造方法赋值
Demo2() {
b=200;
}
}
public class FinalDemo4 {
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
System.out.println(demo2.b);
}
}
8继承里面的代码块
1.首先初始化父类的静态代码块,再是子类的静态代码块
2.再是父类的构造代码块,再是父类的构造方法
3.再是子类的构造代码块,再是子类的构造方法
二.多态
1.相关概念
1.1什么是多态
某一个事物,在不同时刻表现出来的不同状态。
1.2多态的前提
1.有继承关系
2.有方法重写
3.有父类引用指向子类对象
1.3相关格式
父类名 变量名 =new 子类名();
package com.shujia.day7;
//创建父类
class Water{
//创建父类成员方法
public void drink(){
System.out.println("水可以喝");
}
}
//创建子类
class GuTaiWater extends Water{
//重写父类方法
@Override
public void drink(){
System.out.println("固态水也可以喝");
}
}
public class DuoTaiDemo1 {
public static void main(String[] args) {
//父类的引用指向子类对象
Water water=new GuTaiWater();
water.drink();
}
}
/*
固态水也可以喝
*/
2.多态访问成员的特点
2.1成员变量
编译看左边,运行看左边
package com.shujia.day7;
class Fu6{
int a=10;
public void show1(){
System.out.println("黄大大");
}
public static void show2(){
System.out.println("hello");
}
}
class Zi6 extends Fu6{
int a=20;
@Override
public void show1(){
System.out.println("郑心怡");
}
public static void show2(){
System.out.println("java");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu6 fu6=new Zi6();
System.out.println(fu6.a);
fu6.show1();
fu6.show2();
}
}
/*
10 原因是编译看左边,先去找Fu6中有没有a这个变量,如果有那么编译不报错,再去Fu6中寻找a的变量,输出a
郑心怡 原因是编译看左边,先去找Fu6中有没有show1这个方法,如果有那么编译不报错,再去Zi6中show1这个方法,
hello 原因是编译看左边,先去找Fu6中有没有show2这个方法,如果有那么编译不报错,再去Fu6中show1这个方法,
*/
2.2成员方法
编译看左,编译看右
package com.shujia.day7;
class Fu6{
int a=10;
public void show1(){
System.out.println("黄大大");
}
public static void show2(){
System.out.println("hello");
}
}
class Zi6 extends Fu6{
int a=20;
@Override
public void show1(){
System.out.println("郑心怡");
}
public static void show2(){
System.out.println("java");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu6 fu6=new Zi6();
System.out.println(fu6.a);
fu6.show1();
fu6.show2();
}
}
/*
10 原因是编译看左边,先去找Fu6中有没有a这个变量,如果有那么编译不报错,再去Fu6中寻找a的变量,输出a
郑心怡 原因是编译看左边,先去找Fu6中有没有show1这个方法,如果有那么编译不报错,再去Zi6中show1这个方法,
hello 原因是编译看左边,先去找Fu6中有没有show2这个方法,如果有那么编译不报错,再去Fu6中show1这个方法,
*/
2.3静态方法
编译看左边,运行看左边
package com.shujia.day7;
class Fu6{
int a=10;
public void show1(){
System.out.println("黄大大");
}
public static void show2(){
System.out.println("hello");
}
}
class Zi6 extends Fu6{
int a=20;
@Override
public void show1(){
System.out.println("郑心怡");
}
public static void show2(){
System.out.println("java");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
Fu6 fu6=new Zi6();
System.out.println(fu6.a);
fu6.show1();
fu6.show2();
}
}
/*
10 原因是编译看左边,先去找Fu6中有没有a这个变量,如果有那么编译不报错,再去Fu6中寻找a的变量,输出a
郑心怡 原因是编译看左边,先去找Fu6中有没有show1这个方法,如果有那么编译不报错,再去Zi6中show1这个方法,
hello 原因是编译看左边,先去找Fu6中有没有show2这个方法,如果有那么编译不报错,再去Fu6中show1这个方法,
*/
2.4例题
package com.shujia.day7;
class A
{
public void show()
{
show2();
}
public void show2()
{
System.out.println("我");
}
}
class B extends A
{
public void show2()
{
System.out.println("爱");
}
}
class C extends B
{
public void show()
{
super.show();
}
public void show2()
{
System.out.println("你");
}
}
public class TextDemo1 {
public static void main(String[] args) {
A a = new B();
a.show();
B b = new C();
b.show();
}
}
/*
爱
分析原因:类A中有show方法,所以编译不报错,运行看右。类B中直接继承了类A的show方法,然后调用类B的show2方法,打印 爱
你
分析原因:类B中有继承类A的show方法,所以不报错,运行看右。类C中的show方法直接调用类B的show方法,,而类B的show方法也是调用show2方法,这个调用是就近原则所以打印你
*/
3.多态的好处
3.1提高了程序的扩展性
1.不用多态
package com.shujia.day8;
//创建父类Animal
class Animal{
//创建父类成员变量
String name;
int age;
//创建父类无参构造方法
public Animal() {
}
//创建父类有参构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
//创建父类成员方法
public void eat(){
System.out.println("吃");
}
//创建父类成员方法
public void sleep(){
System.out.println("睡");
}
}
//创建子类
class Tiger extends Animal {
//创建子类的无参构造方法
public Tiger() {
}
//创建子类的有参构造方法
public Tiger(String name, int age) {
super(name, age);
}
//重写父类eat方法
@Override
public void eat(){
System.out.println("🐅吃🥩");
}
//重写父类sleep方法
@Override
public void sleep(){
System.out.println("🐅趴着睡");
}
class Bear extends Animal{
public Bear() {
}
public Bear(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("🐻吃🐅");
}
@Override
public void sleep() {
System.out.println("🐻侧着睡");
}
}
}
class Bear extends Animal{
public Bear() {
}
public Bear(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("🐻吃🐅");
}
@Override
public void sleep() {
System.out.println("🐻侧着睡");
}
}
public class DuoTaiDemo1 {
public static void main(String[] args) {
//创建虎1对象
Tiger tiger1 = new Tiger("虎大", 2);
tiger1.eat();
tiger1.sleep();
// //创建虎2对象
Tiger tiger2 = new Tiger("虎二", 1);
tiger2.eat();
tiger2.sleep();
//创建熊1对象
Bear bear1 = new Bear("熊大", 5);
bear1.eat();
bear1.sleep();
// //创建熊2对象
Bear bear2 = new Bear("熊二", 3);
bear2.eat();
bear2.sleep();
}
}
/*
🐅吃🥩
🐅趴着睡
🐅吃🥩
🐅趴着睡
🐻吃🐅
🐻侧着睡
🐻吃🐅
🐻侧着睡
*/
2.用多态
package com.shujia.day8;
//创建父类Animal
class Animal{
//创建父类成员变量
String name;
int age;
//创建父类无参构造方法
public Animal() {
}
//创建父类有参构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
//创建父类成员方法
public void eat(){
System.out.println("吃");
}
//创建父类成员方法
public void sleep(){
System.out.println("睡");
}
}
//创建子类
class Tiger extends Animal {
//创建子类的无参构造方法
public Tiger() {
}
//创建子类的有参构造方法
public Tiger(String name, int age) {
super(name, age);
}
//重写父类eat方法
@Override
public void eat(){
System.out.println("🐅吃🥩");
}
//重写父类sleep方法
@Override
public void sleep(){
System.out.println("🐅趴着睡");
}
class Bear extends Animal{
public Bear() {
}
public Bear(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("🐻吃🐅");
}
@Override
public void sleep() {
System.out.println("🐻侧着睡");
}
}
}
class Bear extends Animal{
public Bear() {
}
public Bear(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("🐻吃🐅");
}
@Override
public void sleep() {
System.out.println("🐻侧着睡");
}
}
//创建工具类
class AnimalTool{
/*
1、构造方法私有化
2、成员方法必须是静态的
*/
public static void useAnimal(Animal animal){ //这里相当于 Animal animal=new Tiger("虎大", 2);编译看左,Animal类中有eat方法,编译不报错,运行看右,Tiger类的eat方法
animal.eat();
animal.sleep();
}
}
public class DuoTaiDemo1 {
public static void main(String[] args) {
//创建虎1对象
Tiger tiger1 = new Tiger("虎大", 2);
//调用工具类的useAnimal方法,传入的是Animal类的对象tiger1
AnimalTool.useAnimal(tiger1);
//创建虎2对象
Tiger tiger2 = new Tiger("虎二", 1);
//调用工具类的useAnimal方法,传入的是Animal类的对象tiger2
AnimalTool.useAnimal(tiger2);
//创建熊1对象
Bear bear1 = new Bear("熊大", 5);
//调用工具类的useAnimal方法,传入的是Animal类的对象bear1
AnimalTool.useAnimal(bear1);
//创建熊2对象
Bear bear2 = new Bear("熊二", 3);
//调用工具类的useAnimal方法,传入的是Animal类的对象bear2
AnimalTool.useAnimal(bear2);
}
}
/*
🐅吃🥩
🐅趴着睡
🐅吃🥩
🐅趴着睡
🐻吃🐅
🐻侧着睡
🐻吃🐅
🐻侧着睡
*/
3.2提高了程序的维护性
1.通过继承保证,因为想修改直接去父类的成员方法修改
4.多态的转型
4.1向下转型
1.使用向下转型的原因
不能访问子类特有功能
2.多态变成子类引用指向子类本身的对象
package com.shujia.day8;
//定义父类
class Fu{
//定义父类的成员方法
public void fun1(){
System.out.println("这是父类中的方法fun1");
}
}
//定义子类
class Zi extends Fu{
//重写父类的fun1方法
@Override
public void fun1(){
System.out.println("这是重写后的fun1方法");
}
//定义子类自己的成员方法
public void show1(){
System.out.println("hello world");
}
}
public class DuoTaiDemo2 {
public static void main(String[] args) {
//父类的引用指向子类对象
Fu fu=new Zi();
fu.fun1();
// fu.show(); 报错原因是使用多态过后,不能访问子类的方法
//子类的引用指向子类对象
Zi zi=new Zi();
zi.show1();
}
}
/*
这是重写后的fun1方法
hello world
*/