JavaSE学习之--继承和多态(一)+https://developer.aliyun.com/article/1413489
5.再谈初始化
先回顾一下静态代码块,实例代码块,构造方法之间执行的先后顺序!
class Test { int a; // 构造方法 public Test() { System.out.println("这是构造方法!!!"); } // 静态块 static { System.out.println("这是静态代码块!!!"); } // 实例代码块 { System.out.println("这是实例代码块!!!"); } } public class Test1 { public static void main(String[] args) { Test test1 = new Test(); System.out.println("============="); Test test2= new Test(); } }
执行结果:
总结:执行顺序-->静态代码块-->实例代码块-->构造方法
且静态代码块只会被执行一次
那如果既有父类的代码块和构造方法,又有子类的代码块和构造方法,执行顺序是怎样的呢?
先看代码:
class Test { int a; // 父类的构造方法 public Test() { System.out.println("这是构造方法!!!"); } // 父类的静态块 static { System.out.println("这是静态代码块!!!"); } // 父类的实例代码块 { System.out.println("这是实例代码块!!!"); } } class DTest extends Test { // 子类的构造方法 public DTest() { System.out.println("这是子类的构造方法!!!"); } // 子类的静态代码块 static { System.out.println("这是子类的静态代码块!!!"); } // 子类的代码块 { System.out.println("这是子类的代码块!!!"); } } public class Test1 { public static void main(String[] args) { DTest test1 = new DTest(); System.out.println("============="); DTest test2= new DTest(); } }
执行结果:
执行顺序:
1.父类,子类的静态代码块
2.父类实例代码块,构造方法
3.子类的实例代码块,构造方法
所有的静态代码块无论实例化多少个对象都只会被执行一次!!!
6.protected关键字
为了实现封装特性,引入了访问修饰限定符,不同的关键字有不同的权限
protected是“受保护的”,它的权限是可以在同包不同类访问,也可以在不同包但是此包的类是另一个包中类的子类,也就是两个包之间的类存在继承关系!
1.同一个包不同类中成员的访问
class B { private int a; int b; protected int c; public int d; } class C extends B { // 同一个包不同类 public void method() { super.a = 20;// err,private成员不能跨类访问 super.b = 20;// 默认权限的成员可以跨类访问 super.c = 20;// protected成员可以跨类访问 super.d = 20;// public成员可以跨类访问 } }
2.不同包不同类中成员的访问
class B { private int a; int b; protected int c; public int d; } // 不同包但存在继承关系之间成员的访问 class C extends B { public void method2() { super.a = 20;// err private成员不能跨类访问 super.b = 20;// err 默认权限成员不能跨包访问 super.c = 20;// protected成员在子类中可以访问 super.d = 20;// public成员可以跨包访问 } }
注意不要忘记引入父类的包:
总结:
1.继承是可以跨包的,如果另一个包中类是另一个包中的类的子类,则存在继承关系;子类会继承父类所有的成员和方法(但是不能全部访问,这取决于父类中成员或方法的访问权限)
2.我们有这么多的权限,那什么时候用什么权限呢?前期学习,大家都会使用一种粗暴的方法,把所有的成员设置为private,所有的方法设置为public,在前期对权限理解不深的时候我们可以这样设置,但使用哪个权限还是要具体问题具体分析,这取决于你对成员或方法的需求!
7.Java中的继承关系(三种)
8.final关键字
final关键字可以修饰变量,方法,类
1.修饰变量会使变量不能被修改(成为常量)
final int b = 20; b = 30;// err b是常量,无法修改常量的值
2.修饰类,代表此类无法被继承
final class B { private int a; int b; protected int c; public int d; } // 此时B就无法被继承 class C extends B { }
平常我们使用的String类就是被final修饰的
3.修饰方法,此方法无法被重写
9.继承与组合
继承反映的是类与类之间的关系,同样的,组合 也是一种反应类与类关系的一种思想!
它代表一个类可以由多个类组成,比如一个Person类可以由Leg,Nose,Head类组成,不同于继承的是组合并没有关键字,只需在类中包含其他类就可以实现类的组合,请看下面代码:
class Nose{}; class Head{}; class Leg{}; class Person{ private Nose nose;// 可以复用Nose类中的方法和属性 private Head head;// 可以复用Head类中的方法和属性 private Leg leg;// 可以复用Leg类中的方法和属性 } class Stu extends Person{ // 继承了人的鼻子,头,腿 };
二.多态
多态就是通过父类引用不同对象,调用同一个重写的方法时,所表现的行为不同(所产生的结果不同),这种现象就叫做多态!
要理解多态,需要理解几个基本概念:向上转型,重写,向下转型,动态绑定
1.向上转型
1.向上转型的定义:
父类引用引用子类对象就叫做向上转型(子类对象被父类引用)
class Animal{}; class Dog extends Animal{}; class Cat extends Animal{}; public class Test { public static void main(String[] args) { // 向上转型 Animal animal1 = new Dog(); Animal animal2 = new Cat(); }
2.实现向上转型的三种方式
1.直接赋值
2.方法传参
3.方法返回
1.直接赋值
Animal animal1 = new Dog(); Animal animal2 = new Cat();
2.方法传参
将方法形参设置为父类引用,实参是子类对象,通过调用方法实现将父类引用指向子类对象!
class Animal{ public void makeSound() { System.out.println("动物发出叫声!"); } }; class Dog extends Animal{ @Override public void makeSound() { System.out.println("小狗在汪汪叫!"); } }; //class Cat extends Animal{}; public class Test { public static void animalMakeSound(Animal animal) { animal.makeSound(); } public static void main(String[] args) { Animal mydog = new Dog(); animalMakeSound(mydog); }
在main方法中我们创建了一个Dog对象,并将其向上转型为Animal类型,接着在animalMakeSound方法中调用该对象,让父类引用指向该对象,在方法内部实现了向上转型!
通过上述代码我们可以看出,将形参设置为父类引用最大的好处就是增加了代码的通用性!因为实参可以是任意子类对象
JavaSE学习之--继承和多态(三)+https://developer.aliyun.com/article/1413491