在java
中存在继承的思想,来提高代码的复用性,代码的拓展性。
程序中的继承,是类与类之间的特征和行为的一种赠予或获取。一个类可以将自己的属性和方法赠予其他的类,一个类也可以从其他的类中获取他们的属性和方法。
两个类之间的继承,必须满足is a 的关系
两个类之间,A类将属性和特征赠予B类。此时A类被称为是父类,B类被称为是子类,两者之间的关系是子类继承自父类。
**定义:**在程序中只要被final修饰的内容是不能再被改变的。
int a = 5; //这是定义了一个int型的变量a 赋值成5。如果我们给它加上修饰词final final int a = 5; //这里a就相当于变成了常量,值一直是5,不能在被改变
可以修饰的内容:
public class Demo6 { public static void main(String[] args) { Animal animal = new Animal(); //name是常量,值不能改变. //animal.name = "chen"; } } //1.类:final修饰的类不能有子类,外界只能用不能改 //final class Animal{ class Animal{ //2.成员变量:变量是一个终值,不能再被改变.所以在定义时必须先手动给一个值. final String name = "bing"; //4.方法:final修饰的方法不允许重写 public final void show(){ //3.局部变量:被final修饰的局部变量是一个终值,不能再被改变 final int a = 4; //a++; System.out.println(a); } }
//接上面的代码 class Bird extends Animal{ //这里暂时没有赋值 final String model; public Bird(String model){ this.model = model;//这里完成赋值 } }
Object类:是java
继承体系中所有类的父类,Object类没有父类。(包含11个方法,相当于所有子类都默认有这些方法)
将多个具体的类中相同的属性和行为提取出来到一个类中。
/Phone类没有显示的父类,默认父类是Object类 class Phone {} //Iphone类继承自Phone类 class Iphone extends Phone { }
访问权限修饰符,就是修饰类、属性的访问级别
当前类 | 同包其他类 | 跨包子类 | 跨包其他类 | |
---|---|---|---|---|
private | √ | × | × | × |
default(不能写出, 不写权限, 默认就是这个权限) | √ | √ | × | × |
protected | √ | √ | √ | × |
public | √ | √ | √ | √ |
解决:子类可以继承到父类中的属性和方法,但是有些方法,子类的实现与父类的方法可能实现的不同。当父类提供的方法已经不能满足子类的需求时,子类中可以定义与父类相同的方法。
子类方法完成了对父类方法的覆盖,又叫重写(Override)
class Phone extends Object{ String color; int model; public void callPhone(){ System.out.println("打电话"); } public void show(){ return null; } } class Iphone extends Phone{ String gui; public void fangShui(){ System.out.println("防水"); } @Override public void callPhone(){ //公共的功能 //System.out.println("打电话"); //通过super调用父类的callPhone方法 super.callPhone(); //自己的功能 System.out.println("自己的功能"); } //父类返回值是Phone,子类的show返回值是Iphone,重写时,程序允许返回值不同 //重写的注意点:父类和子类的重写方法返回值可以不同,但是方法名,参数必须相同.返回值不同时, //必须保证父子类的重写方法的返回值有继承关系,并且子类中的返回值的类型是父类的返回值类型或者子类类型 //在同一个类中不允许出现方法名,参数都相同,但是返回值不同的情况. public Iphone show(){ return null; } }
一个注解,进行重写前的检验这个方法是否是开一个重写的方法。如果不是重写的方法,会直接报错。
class Student { public void work() { System.out.println("学生在学习"); } } class Monitor extends Student { @Override public void work() { super.work(); // 调用父类的实现 System.out.println("班⻓收作业"); } }
基本使用:
ps:
super()方法是默认的,不需要显示写出来class Animal { public Animal() { System.out.println("父类中的构造方法执行"); } } class Dog extends Animal { public Dog() { //这里不显示写,也会默认有super(),调用的是父类的空参构造方法 super(); System.out.println("子类中的构造方法执行"); } }
原因:父类中也有属性要进行初始化,而对象的属性必须由自己的构造方法进行初始化,所以必须调用super(),所以每个构造方法中都默认有一个super()
(类中没有无参构造方法的情况:当我们在类中只写了有参构造方法时,系统不会再自动创建无参构造方法)
解决方案:
1.给父类添加无参构方法 2.在子类的构造方法中,使用super(参数列表),调用父类中的有参构造方法 总结:在继承体系中,作为父类最好的办法就是将无参构造方法和有参构造方法都写了
class Animal { String name; int age; public Animal(String name, int age) { this.name = name; this.age = age; } //1.给父类添加无参构造方法。 public Animal(){ } } class Dog extends Animal { public Dog(String name, int age) { super(name, age); // 2.调用父类中存在的构造方法,实例化父类部分 } }
为什么要将super放在构造方法的第一行?
在子类的构造方法中有可能用到父类的属性,而属性在使用之前必须先进行初始化,否则无法使用。super的作用是初始化父类的属性,如果在super之前调用了其他的代码,有可能造成在未对父类属性初始化时使用了属性的错误情况发生,所以系统默认super前面不能放任何代码,this()用于构造方法调用时也要放在第一行是一个道理。
class Animal{ String name; //public Animal(){} public Animal(String name){ super(); this.name = name; } } class Dog extends Animal{ public Dog(){ //super前不能写任何代码 //System.out.println(); super("bing"); } }
共三种
1.继承---描述:谁是谁 例:人是动物 2.组合---描述:谁属于谁 例:狗属于人/人拥有狗 3.传参
//创建测试类 public class Demo7 { //人有一只狗 public static void main(String[] args) { Person per = new Person(); per.name = "张三"; per.dog = new Dog("拉布拉多"); } public static void feedDog(Dog dog){//传参 dog.eat(); } } //创建的人类 class Person{ String name; Dog dog;//组合 } //创建动物类 class Animal{ String name; } //创建狗类 class Dog extends Animal{//继承 String name;//组合 public Dog(String name){ this.name = name; } public void eat(){ System.out.println("吃⻣头"); } }