17.12继承
1.java三大特性之一:继承
继承是类和类之间的关系,至少需要两个类
格式:
class B extends A { }
B继承于A,A是B的父类(超类,基类),B是A的子类
package com.qfedu.b_extends;
class Father {
String name;
int age;
//行为
public void eat () {
System.out.println("吃大盘鸡拌面");
}
}
//使用了extends以后 Son 类就继承了Father这个类
//就意味着我Son类可以使用Father类下面某些属性和某些方法
class Son extends Father{
}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
//发现继承以后,可以使用父类一些属性
son.name = "小骚磊";
son.age = 1;
System.out.println(son.name);
System.out.println(son.age);
son.eat();
}
}
2.继承的内容
1.成员变量(属性)
公开的和默认的属性,子类可以继承使用
私有的成员变量,子类无法使用
2.成员方法
公开的和默认的,子类可以继承使用,私有的子类无法使用
即:凡是私有的都无法继承
3.构造方法
先执行父类的构造方法,在执行子类的构造方法
注意:
子类和父类的构造方法形式要保持一致。即父类子类都有或没有无参构造,或者都是有参构造,子类可以通过在内部首行使用super(形参)的形式将参数传给父类。
java中的继承是单继承,只有一个父类,可以多层继承,但不能多重继承
package com.qfedu.c_extends; class A { } class B extends A{ } class C extends B { } public class Demo4 { public static void main(String[] args) { } }
3.继承中父子类的内存分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tdEa56zm-1658908421037)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20220725171735679.png)]
4.重写【重点】
Override
目的:
子类可以继承父类非私有化的方法,有时候父类的方法无法满足子类的需求,就需要重写父类非私有的方法
要求:
1.必须有继承关系
- 父类方法必须是非私有化的
- 子类中重写父类方法除了方法体不一样,其他都一样
- 重写必须写在子类中
package com.qfedu.d_override;
class Father {
public void eat () {
System.out.println("吃粗粮。。。。。。");
}
public void driver () {
System.out.println("开拖拉机。。。。。");
}
}
//当父类不能满足子类的需求的话可以在子类中重写父类的方法
class Son extends Father {
//重写的时候在子类中 只需要打上方法的名字一敲回车即可
//重写的方法 和父类 的 返回值 参数 方法名字 一模一样,但是方法体不一样的
@Override//是重写的严格限定,只要有这个,就证明咱们下面的这个方法
//就是重写的方法,告知程序员 此时eat方法是重写的不是自己独有的
public void eat() {
System.out.println("吃白面馒头......");
}
@Override
public void driver() {
System.out.println("开小汽车");
}
}
public class Demo1 {
public static void main(String[] args) {
Son son = new Son();
son.eat();
son.driver();
//重写的话,是不影响父类的方法的
Father father = new Father();
father.eat();
father.driver();
}
}
5.重载【overload】
在同一个类中存在的名字相同,但参数列表不一样的方法,这叫重载
总结:
1.方法的重载必须在同一个类中
2.方法名要一样
3.方法的参数类型必须不一样
4.方法返回值可以不一样
5.无参构造和有参构造也是一种重载
6.super关键字(不重要)
只能用于继承,并在子类中使用,代表父类对象
this:
代表当前类对象
可以调用当前类的属性和方法
可以调用构造方法
super:
1.代表的是当前类的父类
2.可以调用父类中非私有的属性和方法(实际在内存中还是在子类对象内,即super和this差不多)
3.父子类有同名属性或父类方法被重写后,要想调用原父类属性或方法,可以用super.属性/方法名() 调用
4.在子类构造器中使用super(参数)指定调用父类有参构造器,不指定默认调用父类无参构造
package com.qfedu.b_super; class Father1 { String name; public Father1 () { System.out.println("Father1的无参构造"); } public Father1 (String name) { System.out.println("Father1有参构造"); } } class Son1 extends Father1 { //在子类中无论你写了有参构造和无参构造,都要去执行父类的无参构造 //除非你自己调用父类有参构造方法 public Son1(String name) { //在调用父类的无参构造方法 //super(); super("狗蛋"); } } public class Demo2 { public static void main(String[] args) { Son1 son1 = new Son1("狗蛋"); } }
17.13抽象类【重要】
所有对象都可以通过类创建,但不是所有类都可以创建对象。
一个类中没有足够完整的信息来描述具体对象
在java中用关键字abstract修饰的类,这个类叫抽象类
1.abstract关键字
abstract修饰的类叫做抽象类,修饰的方法叫做抽象方法
注:abstract只能修饰类和方法
格式:
abstract class 类名 { //普通方法; public void eat() { ... } //抽象方法 public abstract void sleep(); }
抽象类中可以有普通方法和抽象方法,抽象方法用abstract修饰,不是完整的方法,没有大括号和方法体
注意事项:
一个类如果用abstract修饰,就是一个抽象类
抽象类中可以有普通成员方法和抽象方法
抽象方法没有方法体,是不完整的方法
抽象类不能被实例化
可以写一个普通的类去继承抽象类
在子类中必须要实现(重写)抽象类中所有的抽象方法
非抽象方法可以不重写
一个抽象类可以继承另一个抽象类
一个抽象类可以继承一个非抽象类
package com.qfedu.c_abstract;
class Cell {
public void add () {
System.out.println("分裂");
}
}
abstract class Animal extends Cell{
public abstract void run();
}
abstract class Monkey extends Animal{//抽象类
public void call () {//普通的成员方法
System.out.println("咿咿呀呀.......");
}
public abstract void eat();
public abstract void sleep();
}
class People extends Monkey {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃肉!!!");
}
@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("躺着睡。。。");
}
@Override
public void call() {
System.out.println("嘻嘻哈哈说话");
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("人站立奔跑。。。");
}
}
public class Demo2 {
public static void main(String[] args) {
People people = new People();
people.add();
}
}
17.14final关键字
final:最终的,
用法:
1.修饰成员变量
使用final修饰的成员变量一定要赋值(初始化),而且不能 修改
2.修饰局部变量
使用final修饰局部变量的时候,可以先对变量不赋值,使 用前赋值,但是一旦赋值后就无法更改
3.修饰成员方法
final修饰的成员方法不能被重写,牵涉到继承
4.修饰一个类
final修饰的类不能被继承
5.修饰对象的引用
final Person person = new Person();
一旦使用final修饰person 对象引用是一个固定的内存地 址,无法改变
package com.qfedu.d_final;
class Person {
final String name = "狗蛋";
public void test () {
final int i;
i = 30;
//i = 80;//一旦被赋值,就无法改变了
System.out.println(i);
}
public final void eat () {
System.out.println("吃饭");
}
}
//class Man extends Person {
// @Override
// public void eat() {
// System.out.println("吃的多");
// }
//}
public class Demo1 {
public static void main(String[] args) {
final Person person = new Person();
System.out.println("Person:" + person);
//一旦使用final修饰person 对象引用 是一个固定的内存地址
Person person1 = new Person();
System.out.println("Person1:"+ person1);
//person.name = "嘻嘻";
//person = person1;//将person1赋值给了person对象
System.out.println(person);
}
}
17.15接口【重要】
意义:自身不具备的一些扩展的功能
1.语法格式:
interface 接口名字 { 成员变量 成员方法 }
如何实现?使用关键字implements实现接口
package com.qfedu.e_interface;
interface A {
//接口下面的属性都是常量 常量是使用static 和final修饰的
//只不过在接口中把 static和fianl省去了 常量的名字都要大写
String NAME = "狗蛋";
//在接口一般不写属性的!!!
//成员方法 在接口中全部是抽象的方法 省略abstract
public void eat ();
public void sleep();
}
//无法实例化接口A ,咋办?新建一个类去实现(implements)接口
class TestA implements A {
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃好饭");
}
@Override
public void sleep() {
// TODO Auto-generated method stub
System.out.println("睡好觉");
}
}
public class Demo1 {
public static void main(String[] args) {
TestA testA = new TestA();
testA.eat();
testA.sleep();
System.out.println(testA.NAME);
}
}
注意事项:
1.使用关键字interface声明一个接口
2.接口中可以有属性,但是默认使用static和final修饰,被称为常量,名字大写(几乎不用)
3.接口下面全部都是抽象的方法,都没有方法体,默认省略了abstract,public修饰符也是默认的,也可以不写
4.jdk1.8后接口中是可以有默认(default)方法的,这个默认方法有方法体**【重点!!!】**
5.接口下没有构造方法,不能被实例化
6.可以用一个普通类去实现接口(implements),类似于继承,但有不同
7.必须在实现类中实现所有的抽象方法
8.一个普通类可以实现多个接口,使用逗号隔开,弥补了单继承的局限性
9.一个接口可以继承另一个接口(使用extends)
package com.qfedu.e_interface;
interface B2 {
public void work();
}
interface B1 extends B2{
public void smoking();
}
interface A1 {
String NAME = "狗蛋";
public void test();
public void eat();
public default void sleep () {
System.out.println("睡觉睡得啥也不知道");
}
}
class TestA1 implements A1, B1{
@Override
public void test() {
// TODO Auto-generated method stub
System.out.println("测试");
}
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃东西");
}
@Override
public void sleep() {
System.out.println("睡得什么都不会了");
}
@Override
public void smoking() {
// TODO Auto-generated method stub
System.out.println("不要在整栋楼抽烟!!!");
}
@Override
public void work() {
// TODO Auto-generated method stub
}
}
public class Demo2 {
public static void main(String[] args) {
TestA1 testA1 = new TestA1();
testA1.eat();
testA1.test();
testA1.sleep();
}
}