目录
类与类之间的继承用extends关键字
- class Animal {
- public String name;
- public int age;
-
- public void eat() {
- System.out.println(name + "正在吃饭");
- }
-
- private int hehe;
- }
-
- // 子类 继承 父类
- class Dog extends Animal {
- public void dack() {
- System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
- }
- }
上面的代码是Dog类继承了Animal类
子类继承父类之后,会将父类的所有属性和方法都继承过来,但是父类中被private修饰的成员不可以直接访问
- class Animal {
- public String name;
- public int age;
-
- public void eat() {
- System.out.println(name + "正在吃饭");
- }
-
- private int hehe;
- }
-
- // 子类 继承 父类
- class Dog extends Animal {
- public void dack() {
- System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
- }
- }
- public class Test {
- public static void main(String[] args) {
- Dog dog = new Dog();
- dog.name = "旺财";
- dog.age = 10;
- //dog.hehe = 100; //父类中的私有权限不可以直接访问 可以通过对外接口的方式
- dog.eat();
- dog.dack();
- }
- }
子类中如果有成员和父类的成员重名,那么在调用时不会调用父类的成员,会优先调用子类的成员
- class Animal {
- public String name = "haha";
- public int age;
-
- public void eat() {
- System.out.println(name + "正在吃饭");
- }
-
- private int hehe;
- }
- class Dog extends Animal {
- public String name = "hehe";
- public void dack() {
- System.out.println(name + " 在汪汪叫 " + "年龄:" + age);
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Dog dog = new Dog();
- System.out.println(dog.name);
- }
- }
这时的打印是hehe
如果我们想在子类方法中调用父类的重名成员就要用super关键字。
调用父类的普通成员变量和方法直接用 super. 即可
当调用父类的构造方法是则要用到super(...)
在调用子类的构造方法时,需要先调用父类的构造方法
调用方法就是super() 括号里面进行传参,并且super()必须在子类构造方法的第一条语句,如果子类的构造方法里没有写super(),那么编译器会默认生成一个空的super()。
- class Animal1 {
- public String name;
- public int age;
-
- public Animal1() {
-
- }
- public Animal1(String name, int age) {
- this.name = name;
- this.age = age;
- System.out.println("Animal1(String ,int )");
- }
-
- public void eat() {
- System.out.println(name + " 吃饭 ");
- }
-
- public static void staticEat() {
- System.out.println("父类静态方法");
- }
- }
-
- /**
- * super
- * super. 在子类中可以调用 父类普通成员 变量
- * super. 在子类方法中可以调用 父类普通成员 方法
- * super() 调用父类构造方法
- */
- class Dog1 extends Animal1 {
-
- public boolean still;
- public String name = "hello";
-
- //调用子类的构造方法要先调用父类的构造方法
- //不构造会默认给一个super()
- public Dog1(String name, int age, String name1, boolean still) {
- super(name, age);
- this.name = name1;
- this.still = still;
- }
- public void func() {
-
- super.staticEat();//不建议用super调用父类的静态方法
-
- System.out.println(super.name + " " + age + " " + name + " " + still);
- }
-
- }
调用顺序为 先静态,后实例,再构造 在继承中会先将父类的实例和构造调用完,再调用子类的实例和构造 1.父类的静态 2.子类的静态 3.父类的实例 4.父类的构造 5.子类的实例 6.子类的构造
- package inherit;
-
- /**
- * 调用顺序为
- * 1.父类的静态 2.子类的静态
- * 3.父类的实例 4.父类的构造
- * 5.子类的实例 6.子类的构造
- */
-
- class Animal1 {
- public String name;
- public int age;
-
- public Animal1() {
-
- }
-
- static {
- System.out.println("Animal1::static{}");
- }
-
- {
- System.out.println("Animal1::{}");
- }
- public static void staticEat() {
- System.out.println("父类静态方法");
- }
- }
- class Dog1 extends Animal1 {
-
- public boolean still;
- public String name = "hello";
- static {
- System.out.println("Dog1::static{}");
- }
-
- {
- System.out.println("Dog1::{}");
- }
-
- }
-
- public class Test2 {
- public static void main(String[] args) {
- Dog1 dog1 = new Dog1("hello", 10, "heihei", false);
- }
- }
输出的顺序则是:
Animal1::static{}
Dog1::static{}
Animal1::{}
Animal1(String ,int )
Dog1::{}
Dog1(String ,int ,String ,boolean )
Java中的继承,可以将父类继承给多个子类,但是一个子类只能继承一个父类,不可以进行多继承,如果想继承多个类,可以让继承的父类去继承其他类。
final可以修饰变量,方法,类
被final修饰的变量,表示为常量,不可以再被修改
被final修饰的方法不可以被重写(多态会说明重写)
被final修饰的类不可以被继承
- //此时Animal类将不能被继承
- public final class Animal {
- ...
- }
父类中的方法在子类中被重新实现,称为重写
所谓重写,是将父类方法的外壳保存,只将里面的内容进行修改
被重写的方法不可以是构造方法 也不可以是被static、final、private修饰的方法,且重写后的方法,其使用权限一定是 大于等于 重写前的方法的。
- class Animal00 {
- public String name;
- public int age;
- public void eat() {
- System.out.println(name + " 吃饭 ");
- }
- }
-
- /**
- * 子类Dog00中的eat()方法是 父类Animal00类中eat()方法的重写
- * 父类中被private限定符修饰的不可以被重写
- * 重写的方法的范围一定要大于等于重写前方法的范围
- * 但是不能对呗 final 或者 static 修饰的方法以及 构造方法 进行重写
- */
-
- class Dog00 extends Animal00 {
-
- public boolean still;
- public String name;
- public void eat() {
- System.out.println(name + "正在吃狗粮");
- }
- }
向上转型是小范围向大范围的转型,也就是子类对象转型成父类对象
Animal00 animal = new Dog00();
父类对象向上转型之后只可以访问父类自己特有的属性和方法,不可以访问子类特有的属性和方法
在被调用子类重写后的方法时,不会调用父类的方法,而是调用子类重写后的方法,这个时候,多态就被体现出来了
- public static void function(Animal00 animal) {
- animal.eat();
- }
-
- public static void main(String[] args) {
- //向上转型 小范围向大范围转换
- Animal00 animal = new Dog00("哈士奇", 10, "德牧", false);
- function(animal);
- Cat00 cat = new Cat00("咪咪", 20);
- Animal00 animal1 = cat;
- function(animal1);
- }
当子类对象转型成父类对象后,还想调用子类特有的属性,这是要用到向下转型。
- public static void main4(String[] args) {
- Animal00 animal = new Cat00("咪咪", 10);
- Cat00 cat = (Cat00) animal;//向下转型
- cat.funcm();//Cat00类特有方法
- cat.eat();//Animal00类的特有方法
- }
但是向下转型是很不安全的,因为如果有多个类继承了同一个父类,那么在转型时可能出现在同属与Animal类的Dog类对象去调用Cat类对象的情况,这是不允许的,所以Java中引入了instanceof
左侧放父类,右边放子类则返回true
右边不是子类则返回false
- public static void main5(String[] args) {
- Animal00 animal00 = new Dog00("二哈", 18, "二哈000", true);
- //如果是返回true 不是返回false
- if (animal00 instanceof Cat00) {
- Cat00 cat = (Cat00) animal00;
- cat.funcm();
- }
- }
这样提高了代码的安全性
因为在调用子类的构造方法时,会先调用父类的构造方法,如果这时在父类的构造方法中调用重写的方法,由于子类对象还没有构造,可能会出现属性未初始化的现象。