学习目标
能够写出类的继承格式
public class 子类 extends 父类{}
public class Cat extends Animal{}
能够说出继承的特点
子类继承父类,就会自动拥有父类非私有的成员
能够说出子类调用父类的成员特点
1.子类有使用子类自己的
2.子类没有使用,继承自父类的
3.子类父类都没有编译报错
能够说出方法重写的概念
发生在两个类之间
子类出现了和父类一模一样(返回值类型,方法名,参数列表,修饰符子类大于等于父类)的方法,叫方法重写(Override)
能够说出this可以解决的问题
1.this.变量名:代表本类的成员变量
2.this.方法名称():代表本类的成员方法
3.this(),this(参数):代表调用本类其他的构造方法
能够说出super可以解决的问题
1.super.变量名:代表父类的成员变量
2.super.方法名称():代表父类的成员方法
3.super(),super(参数):代表调用父类的构造方法
描述抽象方法的概念
没有方法体,被abstract修饰的方法
写出抽象类的格式
public abstract class 类名{};
写出抽象方法的格式
权限修饰符 abstract 返回值类型 方法名(参数);
public abstract void aaa();
public abstract int bbb();
public abstract int ccc(String s);
能够说出父类抽象方法的存在意义
在抽象类中定义类抽象方法,那么子类就必须重写这个抽象方法
公司中所有的员工都必须工作
作为模版:让子类强制重写抽象方法,不同的子类添加不同的方法体
一.面向对象回顾
1.面向对象的概念
package com.itheima.demo01Object;
/*
面向对象:学习的重点记住概念,根据概念写出代码
面向对象:基于面向过程
面向过程:当我们遇到一件事情的时候,我们自己分析事情的解决步骤,按照步骤一步一步完成,重视的是解决事情的过程
面向对象:当我们遇到一件事情的时候,我们不自己完成,找一个能够帮我们完成事情的对象,调用对象的功能完成.重视的是对象
现实生活中的事物:属性,行为(功能)
我们可以把现实生活中的事物抽象为java中的类(类是java的基本单位)
把事物的属性抽象为类中的成员变量(定义在成员位置的变量:类中,方法外)
把事物的行为抽象为类中的成员方法(定义在成员位置的方法,去掉static关键字)
封装:私有成员变量,对外提供公共的get/set方法
构造方法:创建对象就是调用类中的构造方法
定义格式:
修饰符 构造方法名-类名(参数){
为成员变量赋值
}
特点:
1.没有返回值类型,不是void,是根本就没有
2.没有返回值
3.必须和类名相同
构造方法的注意事项:
1.类中没有定义构造方法,JVM会为类添加一个 默认的空参数的构造方法
格式: public Student(){ }
2.类中已经定义了构造方法(空参,带参),那么JVM就不会给类添加默认的构造方法了
所以我们要使用空参数的构造方法,必须自己手动写出
3.构造方法是可以重载(在一个类中方法名称相同,但是参数列表不同(个数,顺序,数据类型)的方法)
*/
public class Student {
//私有成员变量
private String name;
private int age;
public Student() {
System.out.println("Student类的空参数构造方法!");
}
public Student(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Student类的满参数构造方法!");
}
//对外提供公共的get/set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.itheima.demo01Object;
/*
测试类:包含main方法的类
*/
public class Demo01Student {
public static void main(String[] args) {
//使用Student类的空参数构造方法创建对象
Student s1 = new Student();
//使用set方法给成员变量赋值
s1.setName("迪丽热巴");
s1.setAge(18);
//使用get方法,获取成员变量的值
System.out.println(s1.getName()+"\t"+s1.getAge());
//使用Student类的满参数构造方法创建对象
Student s2 = new Student("古力娜扎",18);
//使用set方法,修改成员变量的值
s2.setAge(20);
//使用get方法,获取成员变量的值
System.out.println(s2.getName()+"\t"+s2.getAge());
}
}
2.this关键字
package com.itheima.demo02this;
/*
this关键字:
代表本类对象的引用==>根据类创建的对象
哪个对象调用的方法,方法中的this就是哪个对象
this关键字作用:当局部变量和成员变量重名时,使用this关键字可以区分局部变量和成员变量
this.变量名==>成员变量
*/
public class Person {
private String name;
//定义成员方法
public void show(){
System.out.println("this:"+this);//this:com.itheima.demo02this.Person@4554617c
String name = "小强";
System.out.println("name:"+name);//name:小强 变量的就近访问原则
System.out.println("this.name:"+this.name);//this.name:旺财 this.变量名代表成员变量
}
public Person() {
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.itheima.demo02this;
public class Demo01This {
public static void main(String[] args) {
//创建Person对象
Person p = new Person("旺财");
System.out.println("p:"+p);//p:com.itheima.demo02this.Person@4554617c
p.show();
}
}
3.对象的内存图
4.匿名对象
package com.itheima.demo03Object;
import java.util.ArrayList;
/*
匿名对象:
创建对象时,只有创建对象的语句,没有把对象赋值给某个变量,这个对象叫匿名对象
没有名字的对象
特点:
只能使用一次,使用完毕会被JVM在空闲的时候进行垃圾回收
好处:
可以节约内存,可以提高程序的效率
作用:
一般可以作为方法的参数和返回值使用
*/
public class Demo01Animal {
public static void main(String[] args) {
//创建一个有名字的对象:可以重复使用
Animal a1 = new Animal("Tom");
a1.eat();
a1.eat();
//创建一个匿名对象:只能使用一次
new Animal("Jerry").eat();
//如果想要在使用匿名对象,需要重新创建
new Animal("熊大").eat();
System.out.println("---------------------------");
//调用show方法,创建Animal对象为变量a2赋值
show(a1);
//如果方法的参数传递的对象只使用一次,就可以使用匿名对象
show(new Animal("熊二"));
System.out.println("----------------------------");
//调用getAnimal方法
//Animal a4 = getAnimal();==> new Animal("光头强");
Animal a4 = getAnimal();
a4.eat();
System.out.println("----------------------------");
ArrayList<Animal> list = new ArrayList<>();
list.add(a1);
//对象只使用一次,就可以使用匿名对象
list.add(new Animal("加菲猫"));
}
/*
定义一个方法,方法的参数使用Animal类型
Animal a2 = a1 = new Animal("Tom");
Animal a2 = new Animal("熊二")
*/
public static void show(Animal a2){
a2.eat();
}
/*
定义一个方法,方法的返回值类型使用Animal
方法的返回值类型是Animal,就必须在方法中创建一个Animal对象返回
方法的返回值类型是int,就必须在方法中返回一个整数
...
*/
public static Animal getAnimal(){
//Animal a3 = new Animal("光头强");
//return a3;
//对象只使用一次,就可以使用匿名对象
return new Animal("光头强");
}
}
package com.itheima.demo03Object;
public class Animal {
private String name;
public void eat(){
System.out.println(name+"在吃饭!");
}
public Animal() {
}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
二.继承
1.继承的概念
子类继承父类,子类就会自动拥有父类非私有的成员变量和成员方法
2.继承的定义格式
package com.itheima.demo04extends;
/*
定义父类员工类
属性:姓名,年龄
方法:工作
*/
public class Employee {
//属性:姓名,年龄
String name;
int age;
//方法:工作
public void work(){
System.out.println(name+"在呕心沥血的工作!");
}
}
package com.itheima.demo04extends;
/*
定义讲师类:讲师是公司员工的一种,所以可以继承员工类
什么时候使用继承:我是你的一种的使用(is...a)
继承的格式:
public class 子类 extends 父类{ }
子类:Teacher
父类:Employee
继承的特点:
子类继承父类,子类就会自动拥有父类非私有的成员变量和成员方法
在子类中可以定义子类特有的成员
*/
public class Teacher extends Employee{
//定义子类特有的打印姓名和年龄的方法
public void print(){
System.out.println(name+"\t"+age);
}
}
package com.itheima.demo04extends;
/*
定义班主任类:班主任是公司员工的一种,所以可以继承员工类
*/
public class BanZhuRen extends Employee {
}
package com.itheima.demo04extends;
/*
测试继承:
测试子类继承父类之后,是否会自动拥有父类非私有的成员
继承的好处:
1.可以提高代码的复用性(重复使用)
2.继承使类与类之间产生了关系,是多态的前提
*/
public class Demo01Extends {
public static void main(String[] args) {
//创建子类Teacher对象
Teacher t = new Teacher();
//使用子类继承自父类的成员变量
t.name = "老白";
t.age = 18;
//使用子类继承自父类的成员方法
t.work();
//使用子类特有的成员
t.print();
//定义子类BanZhuRen对象
BanZhuRen bzr = new BanZhuRen();
//使用子类继承自父类的成员变量
bzr.name = "美女";
bzr.age = 18;
//使用子类继承自父类的成员方法
bzr.work();
}
}
3.继承的注意事项
package com.itheima.demo05extends;
public class Fu {
private String name;
private int age;
//定义一个私有的成员方法
private void siFangQian(){
System.out.println("父亲老王的私房钱!");
}
public Fu() {
}
public Fu(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.itheima.demo05extends;
public class Zi extends Fu {
}
package com.itheima.demo05extends;
/*
继承的注意事项:
1.构造方法是不能继承的,构造方法是本类创建对象使用的
2.父类私有成员子类是不能继承的
*/
public class Demo01 {
public static void main(String[] args) {
Zi zi = new Zi();
//私有的成员变量子类是不能继承使用
//System.out.println(zi.name);//'name' has private access in 'com.itheima.demo05extends.Fu'
//子类可以使用继承自父类公共的get/set方法,通过方法来操作变量
zi.setName("小王");
zi.setAge(10);
//私有的成员方法子类是不能继承使用
//zi.siFangQian();//'siFangQian()' has private access in 'com.itheima.demo05extends.Fu'
}
}
4.继承后的特点—成员变量
package com.itheima.demo06Variable;
public class Fu {
int a = 10;
}
package com.itheima.demo06Variable;
public class Zi1 extends Fu{
int b = 20;
}
package com.itheima.demo06Variable;
public class Zi2 extends Fu{
int a = 100;
int b = 200;
}
package com.itheima.demo06Variable;
/*
继承后的特点—成员变量
1.子类有使用子类自己的成员变量
2.子类没有使用子类继承自父类的成员变量
3.子类和父类都没有,编译报错
*/
public class Demo01Variable {
public static void main(String[] args) {
//创建子类对象
Zi1 zi1 = new Zi1();
System.out.println(zi1.a);//10 子类继承父类的
System.out.println(zi1.b);//20 使用子类自己的
//创建子类对象
Zi2 zi2 = new Zi2();
System.out.println(zi2.a);//100 使用子类自己的
System.out.println(zi2.b);//200 使用子类自己的
//System.out.println(zi2.c);//Cannot resolve symbol 'c' 子类和父类都没有,编译报错
}
}
5.继承后的特点—成员方法
package com.itheima.demo07Method;
public class Fu {
public void show01(){
System.out.println("Fu类的show01方法!");
}
}
package com.itheima.demo07Method;
public class Zi1 extends Fu{
public void show02(){
System.out.println("Zi1类的show02方法!");
}
}
package com.itheima.demo07Method;
public class Zi2 extends Fu{
public void show01(){
System.out.println("Zi2类的show01方法!");
}
public void show02(){
System.out.println("Zi2类的show02方法!");
}
}
package com.itheima.demo07Method;
/*
继承后的特点—成员方法
1.子类有使用子类自己的成员方法
2.子类没有使用子类继承自父类的成员方法
3.子类和父类都没有,编译报错
*/
public class Demo01Method {
public static void main(String[] args) {
//创建子类对象
Zi1 zi1 = new Zi1();
//使用子类继承自父类的成员方法show01
zi1.show01();
//使用子类自己的成员方法show02
zi1.show02();
//创建子类对象
Zi2 zi2 = new Zi2();
//使用子类自己的成员方法show01,show02
zi2.show01();
zi2.show02();
//zi2.show03();//Cannot resolve method 'show03()' 子类和父类都没有,编译报错
}
}
6.方法重写(Override)
package com.itheima.demo08Override;
public class Fu {
public void show01(){
System.out.println("Fu类的show01方法!");
}
}
package com.itheima.demo08Override;
/*
方法重写:发生在两个类之间,在子类中出现了和父类一模一样的方法,叫方法重写(Override)
一模一样:
方法名一样
参数列表一样
返回值类型一样
修饰符一样(子类的修饰符权限大于等于父类的修饰符)
注解:
@Override:检查方法是否为重写的方法
------------------------------------------------------------
方法重载:发生在一个类中,在一个类中出现了方法名相同,但是参数列表不同的方法,叫方法重载(Overload)
*/
public class Zi extends Fu{
@Override
public void show01(){
System.out.println("Zi类重写父类的show01方法!");
}
public void show01(int a){
System.out.println("Zi类特有的show01方法!"+a);
}
//@Override//Method does not override method from its superclass
public void show02(){
System.out.println("Zi类的show02方法!");
}
}
package com.itheima.demo08Override;
public class Demo01Override {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
zi.show01();//调用的是子类重写父类的show01方法
}
}
7.方法重写的注意事项(了解)
package com.itheima.demo09Override;
public class Fu {
public void show01(){
System.out.println("Fu类的show01方法");
}
void show02(){
System.out.println("Fu类的show02方法");
}
public void show03(){
System.out.println("Fu类的show03方法");
}
public void show04(){
System.out.println("Fu类的show04方法");
}
private void show05(){
System.out.println("Fu类的show05方法");
}
}
package com.itheima.demo09Override;
/*
方法重写的注意事项:
1. 方法重写是发生在子父类之间的关系。
2. 子类方法重写父类方法,必须要保证权限大于等于父类权限。
java中四大权限修饰符
public:公共的
protected:受保护的
:默认的,不写就是默认的
private:私有的
3. 子类方法重写父类方法,返回值类型、方法名和参数列表都要和父类方法一模一样
4. 私有方法不能被重写(父类的私有方法子类是不能继承)
*/
public class Zi extends Fu{
//2. 子类方法重写父类方法,必须要保证权限大于等于父类权限。
/*void show01(){
System.out.println("Fu类的show01方法");
}*/
public void show02(){
System.out.println("Fu类的show02方法");
}
//3. 子类方法重写父类方法,返回值类型、方法名和参数列表都要和父类方法一模一样
//@Override//Method does not override method from its superclass
public void show03(int a){
System.out.println("Zi类的show03方法");
}
/*public int show04(){
System.out.println("Fu类的show03方法");
return 1;
}*/
//@Override//Method does not override method from its superclass
public void show08(){
System.out.println("Fu类的show03方法");
}
//@Override//Method does not override method from its superclass
//就相当于在子类中定义了一个自己特有的私有方法,恰好名字和父类方法一样
private void show05(){
System.out.println("Zi类的show05方法");
}
}
8.继承后的特点—构造方法
package com.itheima.demo10Constructor;
public class Fu {
int a = 10;
public Fu() {
System.out.println("Fu类的空参数构造方法!"+a);
}
}
package com.itheima.demo10Constructor;
public class Zi extends Fu{
//int a = 1;
//int b = 2;
/*
继承后的特点—构造方法
在子类构造方法的第一行,有一个默认的super();
super();作用就是调用父类的空参数构造方法
子类继承父类,子类想要使用继承自父类的成员,就必须把父类加载到内存中,调用父类的构造方法创建父类对象
父类进入到内存中,子类才可以使用父类的成员
*/
public Zi() {
super();
System.out.println("Zi类的空参数构造方法!"+a);
}
}
package com.itheima.demo10Constructor;
public class Demo01Constructor {
public static void main(String[] args) {
//创建子类对象
Zi zi = new Zi();
}
}
9.子父类的内存图解
10.使用this关键字和super关键字访问成员
package com.itheima.demo11ThisAndSuper;
public class Animal {
String name = "猫科动物";
public void eat(){
System.out.println("动物在吃饭!");
}
}
package com.itheima.demo11ThisAndSuper;
/*
this关键字:本类对象的引用(根据Cat创建的对象)
this.成员变量:本类的成员变量
this.成员方法(参数):本类的成员方法
super关键字:父类对象的引用(根据Animal创建的对象)
super.成员变量:父类的成员变量
super.成员方法(参数):父类的成员方法
*/
public class Cat extends Animal {
String name = "加菲猫";
public void eat(){
System.out.println("加菲猫在吃饭!");
}
public void show(){
System.out.println(name);//加菲猫 变量的就近访问原则
System.out.println("this.name:"+this.name);//加菲猫
System.out.println("super.name:"+super.name);//猫科动物
eat();//加菲猫在吃饭!
this.eat();//加菲猫在吃饭!
super.eat();//动物在吃饭!
}
}
package com.itheima.demo11ThisAndSuper;
public class Demo01ThisAndSuper {
public static void main(String[] args) {
//创建子类Cat对象
Cat cat = new Cat();
cat.show();
}
}
11.this关键字:调用本类其他的构造方法
package com.itheima.demo12this;
/*
this关键字:可以调用本类其他的构造方法
格式:
this();调用空参数构造方法
this(参数);调用带参数构造方法
注意:
1.this();|this(参数);调用构造方法必须写在构造方法中的第一行,创建对象必须优先执行
2.构造方法不能相互调用(不能你调用我,我在调用你-->死循环)
*/
public class Animal {
private String name;
private int age;
public Animal() {
//this("tom",10);//调用带参数构造方法
System.out.println("Animal类的空参数构造方法!");
}
public Animal(String name, int age) {
this();//调用空参数构造方法
this.name = name;
this.age = age;
System.out.println("Animal类的带参数构造方法!");
}
public String getName() {
//this();//Call to 'this()' must be first statement in constructor body
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.itheima.demo12this;
public class Demo01This {
public static void main(String[] args) {
//使用空参数构造方法创建Animal对象
Animal a1 = new Animal();
System.out.println(a1.getName()+"\t"+a1.getAge());
/*
执行结果:
Animal类的带参数构造方法!
Animal类的空参数构造方法!
tom 10
*/
//使用带参数的构造方法创建Animal对象
Animal a2 = new Animal("jerry",5);
System.out.println(a2.getName()+"\t"+a2.getAge());
/*
执行结果:
Animal类的空参数构造方法!
Animal类的带参数构造方法!
jerry 5
*/
}
}
12.super关键字:调用父类的构造方法
package com.itheima.demo13super;
public class Fu {
public Fu() {
System.out.println("Fu类的空参数构造方法!");
}
public Fu(int a) {
System.out.println("Fu类的带参数构造方法!"+a);
}
}
package com.itheima.demo13super;
/*
super关键字:调用父类的构造方法
格式:
super();调用父类的空参数构造方法
super(参数);调用父类带参数构造方法
注意:
1.在子类的构造方法中没有写super();有一个默认的super();用于调用父类的空参数构造方法
2.super();|super(参数);必须写在子类构造方法有效代码的第一行,构造方法必须优先执行
3.在子类的构造方法中this和super不能同时出现,都必须写在有效代码第一行
*/
public class Zi extends Fu {
public Zi() {
super();//调用父类的空参数构造方法,不写默认
System.out.println("Zi类的空参数构造方法!");
}
public Zi(int a){
super(a);//调用父类的带参数构造方法
System.out.println("Zi类的带参数构造方法"+a);
}
}
package com.itheima.demo13super;
public class Demo01Super {
public static void main(String[] args) {
//使用Zi类空参数构造方法创建对象
Zi zi = new Zi();
//使用Zi类带参数构造方法创建对象
Zi zi2 = new Zi(100);
}
}
13.继承的特点
三.抽象类
1.抽象类&抽象方法概述
2.抽象类&抽象方法使用
package com.itheima.demo14abstractClass;
/*
定义父类员工类:是根据子类共性抽取形成
定义成员变量:
姓名,年龄
定义成员方法:
工作的方法
每个子类方法的方法体不同,但是方法的声明相同(public void work())
只抽取方法的声明,不抽取方法体
抽取出来的方法声明添加一个关键字abstract,这个方法叫抽象方法
定义格式:
修饰符 abstract 返回值类型 方法名(参数);
public abstract void work();
public abstract void work(String a);
public abstract int work(String a);
包含抽象方法的类,也必须被abstract修饰,叫抽象类
定义格式:
public abstract class 类名{}
----------------------------------------------------------
注意:
1.抽象类是无法直接创建对象使用的
a.有一些类就是为了不让别人创建对象使用,可以定义为抽象类
b.抽象类中一般都包含抽象方法,抽象方法没有方法体,创建对象调用抽象方法没有意义
2.需要创建子类继续抽象父类,重写抽象类中的抽象方法,创建子类对象使用
------------------------------------------------------------------------
好处:
在抽象类中定义抽象方法,那么子类就必须重写这个抽象方法
公司中所有的员工都必须工作==>定义了一个模版==>子类都必须根据模版重写抽象方法
*/
public abstract class Employee {
private String name;
private int age;
//定义抽象的工作方法
public abstract void work();
public Employee() {
}
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.itheima.demo14abstractClass;
/*
讲师类是一个员工类的一种,所以可以继承员工类
讲师类已经能明确自己的工作内容了
所以需要重写工作的方法,添加方法体
注意:
子类继承抽象类有两种处理方式 alt+回车
1.子类也声明为抽象类(子类包含继承自父类的抽象方法)
2.子类重写抽象方法,添加方法体
*/
public class Teacher extends Employee{
@Override
public void work() {
System.out.println("正在给大家讲解java!");
}
}
package com.itheima.demo14abstractClass;
/*
班主任类是一个员工类的一种,所以可以继承员工类
班主任类已经能明确自己的工作内容了
所以需要重写工作的方法,添加方法体
*/
public class BanZhuRen extends Employee{
@Override
public void work() {
System.out.println("正在监督大家学习!");
}
}
package com.itheima.demo14abstractClass;
//抽象类是无法创建对象使用的
public abstract class JiuYeZhiDao extends Employee{
}
package com.itheima.demo14abstractClass;
public class Demo01AbstractClass {
public static void main(String[] args) {
//Employee ee = new Employee();//'Employee' is abstract; cannot be instantiated 抽象类是无法直接创建对象使用的
//创建子类对象
Teacher t = new Teacher();
t.work();
BanZhuRen bzr = new BanZhuRen();
bzr.work();
//JiuYeZhiDao jyzd = new JiuYeZhiDao();//'JiuYeZhiDao' is abstract; cannot be instantiated
}
}
3.模版设计模式
package com.itheima.demo15driver;
/*
定义开车类的模版:在父类中调用子类重写后的方法
定义一些固定的内容(开门,点火,刹车,熄火)
不同的内容定义为抽象方法(开车姿势不同)
*/
public abstract class Driver {
//定义开车的方法
public void driver(){
System.out.println("开门..............");
System.out.println("点火..............");
ziShi();
System.out.println("刹车..............");
System.out.println("熄火..............");
}
//新司机和老司机开车的姿势不同,定义为抽象方法
public abstract void ziShi();
}
package com.itheima.demo15driver;
//定义新司机类,是司机类的一种,所以继承司机类
public class NewDriver extends Driver{
@Override
public void ziShi() {
System.out.println("新司机开车的姿势:双手紧握方向盘!");
}
}
package com.itheima.demo15driver;
//定义老司机类,是司机类的一种,所以继承司机类
public class OldDriver extends Driver{
@Override
public void ziShi() {
System.out.println("老司机开车姿势:右手握方向盘左手抽烟");
}
}
package com.itheima.demo15driver;
public class Demo01Driver {
public static void main(String[] args) {
//创建新司机对象
NewDriver nd = new NewDriver();
nd.driver();
//创建老司机对象
OldDriver od = new OldDriver();
od.driver();
}
}