在现实生活中,说到继承,多会想到子女继承父辈的财产、事业等。在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关联体系。
在Java中,类的继承是指在一个现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类或基类,子类会自动拥有父类所有可继承的属性和方法。
- 使用extends关键字来表示继承关系
- 相当于子类把父类的功能复制了一份
- Java只支持单继承
- 继承可以传递(爷爷/儿子/孙子这样的关系)
- 父类的私有成员也会被继承,但由于私有限制访问,所以子类不能使用父类的私有资源
- 继承多用于功能的修改,子类可以在拥有父类功能的同时,进行功能拓展
- 像是is a的关系
public class ExtendsDemo {
public static void main(String[] args) {
Animal a = new Animal();
Cat c = new Cat();
MiaoMiao m = new MiaoMiao();
// 利用对象调用方法
a.eat();
c.eat();
m.eat();
}
}
// 创建爷爷类
class Animal {
public void eat() {
System.out.println("小动物Animal吃啥都行~");
}
}
// 创建爸爸类,并与Animal类建立继承关系
class Cat extends Animal {
int a = 10;
private int b = 100;
}
// 创建孙子类,并与Cat类建立继承关系
class MiaoMiao extends Cat {
public void studyjava() {
System.out.println("这是一只会编程的猫");
System.out.println(a);
//System.out.println(b);
}
}
2 super关键字
我们可以把super看作是父类的对象:Father super = new Father();
- 当父类的成员变量与子类的变量同名时,使用super指定父类的成员变量
- 使用super在子类构造方法的第一行调用父类构造方法的功能
super();–调用的是父类的无参构造
super(参数);–调用的是父类对应参数的构造方法
注意:在构造方法里,出现的调用位置必须是第一行
public class TestExtends1 {
public static void main(String[] args) {
Father f = new Father();
Son s = new Son();
s.eat();
}
}
// 创建父类
class Father {
int count = 1;
int sum = 2;
}
// 创建子类
class Son extends Father {
int sum = 100;
public void eat() {
int sum = 10;
System.out.println(sum);// 打印局部变量sum
System.out.println(this.sum); // 打印成变量sum
System.out.println(count);
System.out.println(super.sum);// 使用父类重名的成员变量
}
}
2.2.2 super之继承中构造方法的使用
public class TestExtends2 {
public static void main(String[] args) {
Father2 f2 = new Father2("红烧肉");
Son2 s2 = new Son2();
}
}
class Father2 {
// public Father2() {
// System.out.println("我是Father2无参构造");
// }
public Father2(String s) {
System.out.println("爸爸爱吃" + s);
}
}
class Son2 extends Father2 {
public Son2() {
super("狮子头");
System.out.println("我是Son2的无参构造");
}
}
3 方法重写Override
- 继承以后,子类就拥有了父类的功能
- 在子类中,可以添加子类特有的功能,也可以修改父类的原有功能
- 子类中方法的签名与父类完全一样时,会发生覆盖/复写的现象
- 注意: 父类的私有方法不能被重写
- 重写的要求:两同两小一大
两同:方法名 参数列表 要完全一致
两小:
子类返回值类型小于等于父类的返回值类型(注意此处说的是继承关系,不是值大小)
子类抛出异常小于等于父类方法抛出异常
一大:子类方法的修饰符权限要大于等于父类被重写方法的修饰符权限
public class TestExtends3 {
public static void main(String[] args) {
Father3 f3 = new Father3();
Son3 s3 = new Son3();
f3.eat();
s3.eat();
}
}
class Father3 {
public void eat() {
System.out.println("爸爸爱吃肉");
}
public void play() {
System.out.println("吕布爱貂蝉");
}
}
class Son3 extends Father3 {
public void studyJava() {
System.out.println("拓展学习Java的功能");
}
@Override
public void eat() {
System.out.println("儿子爱吃蔬菜");
}
}
4 static关键字
4.1 概念
是java中的一个关键字
用于修饰成员(成员变量和成员方法)
- static可以修饰成员变量和方法
- 被static修饰的资源称为静态资源
- 静态资源随着类的加载而加载,最先加载,优先于对象进行加载
- 静态资源可以通过类名直接调用,也被称作类资源
- 静态被全局所有对象共享,值只有一份
- 静态资源只能调用静态资源
- 静态区域内不允许使用this与super关键字
public class TestStatic1 {
public static void main(String[] args) {
System.out.println(Student.name);
Student.study();
Student s = new Student();
System.out.println(s.sno);
System.out.println(s.name);
s.study();
s.name = "鹌鹑蛋罐头";
System.out.println(s.name);
System.out.println(Student.name);
Student s2 = new Student();
System.out.println(s2.name);
System.out.println(Student.name);
s2.name = "牛肉罐头";
System.out.println(s.name);
System.out.println(s2.name);
System.out.println(Student.name);
}
}
class Student {
int sno;
static String name;
public static void study() {
System.out.println("别闹?学Java呢~");
}
public void speak() {
System.out.println("会要大声说出来");
}
}
4.2.2 static静态调用关系
public class TeatStatic2 {
}
class Teacher {
String name;
public void teach() {
System.out.println("正在授课ing....");
System.out.println(age);
ready();
}
static int age;
public static void ready() {
System.out.println("正在备课ing...");
//System.out.println(name);
//teach();
}
public static void eat() {
System.out.println("正在吃饭中ing...");
System.out.println(age);
ready();
}
}
5 静态代码块、构造代码块、局部代码块
5.1 静态代码块格式
静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
特点: 被static修饰,位置在类里方法外
- 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
- 构造代码块:在创建对象时会自动调用,每次创建对象都会被调用,提取构造共性
- 局部代码块:方法里的代码块,限制局部变量的范围
public class TestStaticBlock {
// 6、创建对象
public static void main(String[] args) {
Person p = new Person();
// 7、触发局部代码块
p.play();
}
}
// 1、创建Person类
class Person {
// 8、创建静态代码块
static {
System.out.println("我是静态代码块");
}
// 2、创建构造代码块
{
System.out.println("我是构造代码块");
}
// 5、创建构造方法
public Person() {
System.out.println("我是无参构造");
}
// 3、创建普通方法
public void play() {
System.out.println("我是一个普通方法");
// 4、创建局部代码块
{
System.out.println("我是局部代码块");
}
}
}
总结:
执行顺序:静态代码块——>构造代码块——>构造方法【对象创建成功】——>局部代码块
- 是java提供的一个关键字
- final是最终的意思
- final可以修饰类,方法,字段(属性)
初衷:java出现继承后,子类可以更改父类的功能,当父类功能不许子类改变时,可以利用final关键字修饰父类。
- 被final修饰的类,不能被继承
- 被final修饰的方法,不能被重写
- 被final修饰的字段是个常量,值不能被修改
- 常量的定义形式:final 数据类型 常量名 = 值
public class TestFinal {
public static void main(String[] args) {
Son s = new Son();
//s.name = "干饭人"; // 会报错,因为常量的值不能被修改
}
}
//final class Father {
class Father {
// 定义父类的普通方法
// final public void work() {
// System.out.println("在车间上班");
// }
public void work() {
System.out.println("在车间上班");
}
}
class Son extends Father {
final String name = "打工人";
final int a = 0;
@Override
public void work() {
System.out.println("在格子间上班");
}
}
7 拓展
7.1 his与super的区别
this代表的是本类对象的引用,我们可以把this看作是Cat this = new Cat();
super代表的是父类对象的引用,我们可以把super看作是Father super = new Father();
当本类的成员变量与局部变量同名时,需要使用this.变量名指定本类的成员变量
当本类的成员变量与父类的成员变量同名时,需要使用super.变量名指定父类的成员变量
this可以实现调用本类构造方法的功能,不能互相调用,需要写在构造方法首行
this();表示调用本类的无参构造 this(参数);表示调用本类的对应参数的构造
super也可以实现调用父类构造方法的功能
super();表示调用父类的无参构造 super(参数);表示调用父类的对应参数的构造
注意:super的使用前提是继承,没有父子类关系,就没有super
注意:this调用构造方法或者super调用构造方法,都必须出现在构造方法的第一行
注意:如果父类没有无参构造,需要手动在子类构造方法的第一行调用其他的含参构造
拓展:如果子类重写了父类的方法以后,可以使用super.方法名(参数列表)来调用
重载:在一个类中的现象:同一个类中,存在方法名相同,参数列表不同的方法
重写:是指建立了继承关系以后,子类对父类的方法不满意,可以重写,遵循两同两小一大原则
重载的意义:是为了外界调用方法时方便,不管传入什么样的参数,都可以匹配到对应的同名方法
重写的意义:在不修改源码的情况下,进行功能的修改与拓展(OCP原则:面向修改关闭,面向拓展开放)



