当我们在做子类共性功能抽取时,有些方法在父类中并没有具体的体现,这个时候就需要抽象类了!
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类!
1.2抽象类的特点(记忆)-
抽象类和抽象方法必须使用 abstract 关键字修饰
//抽象类的定义 public abstract class 类名 {} //抽象方法的定义 public abstract void eat(); -
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
抽象类不能实例化
抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态
-
抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类
成员变量
- 可以是变量
- 也可以是常量
构造方法
- 有构造方法,但是不能实例化
- 那么,构造方法的作用是什么呢?用于子类访问父类数据的初始化
·
成员方法
- 可以有抽象方法:限定子类必须完成某些动作
- 也可以有非抽象方法:提高代码复用性
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
2.2接口的特点(记忆)-
接口用关键字interface修饰
public interface 接口名 {} -
类实现接口用implements表示
public class 类名 implements 接口名 {} -
接口不能实例化
接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态。
多态的形式:具体类多态,抽象类多态,接口多态。 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
-
接口的子类
要么重写接口中的所有抽象方法
要么子类也是抽象类
-
成员特点
-
成员变量
只能是常量 默认修饰符:public static final
-
构造方法
没有,因为接口主要是扩展功能的,而没有具体存在 接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在一个类如果没有父类,默认继承自Object类 类object是类层次结构的根。每个类都有object作为超类。 所有对象 (包括数组)都实现了这个类的方法。
-
成员方法
只能是抽象方法
默认修饰符:public abstract
关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解
-
-
代码演示
-
接口
-
package com.hulu_02;
public interface Inter {
public int num = 10;//变量
public final int num2 = 20;//常量
//public static final int num3 = 30;//等价于下一句
int num3 = 30;
//public Inter(){}//报错,不允许有构造方法
//public void show(){}//报错,接口里的方法默认为抽象方法,不能有方法体
public abstract void method();
void show();//默认修饰符public abstract 可以不写
}
-
实现类
public class InterImpl extends Object implements Inter {
public InterImpl() {
super();//默认继承自Object类
}
@Override//重写
public void method() {
System.out.println("method");
}
@Override
public void show() {
System.out.println("show");
}
}
-
测试类
public class InterfaceDemo {
public static void main(String[] args) {
Inter i = new InterImpl();//参照多态的方式,通过实现类对象实例化
// i.num = 20;//默认被final修饰,变常量
System.out.println(i.num);
// i.num2 = 40;
System.out.println(i.num2);
//通过接口名直接访问,说明num是静态修饰的
System.out.println(Inter.num);
}
}
猫接口案例:
package com.hulu_03;
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,调用方法
Jumpping j = new Cat();
j.jump();
System.out.println("---------------------");
Animal a = new Cat();
a.eat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName()+a.getAge());
a.eat();
//a.jump();//报错,接口多态(或抽象多态)只能调用自己有的方法
a = new Cat("加菲",5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
System.out.println("--------");
//一般使用具体的类,因为它具有最多的方法
Cat c = new Cat();
c.setName("加菲");
c.setAge(6);
System.out.println(c.getName()+c.getAge());
c.eat();
c.jump();
}
}
2.5类和接口的关系(记忆)
-
类与类的关系
继承关系,只能单继承,但是可以多层继承
-
类与接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
-
接口与接口的关系
继承关系,可以单继承,也可以多继承
-
成员区别(语法上)
-
抽象类
变量,常量;有构造方法;有抽象方法,也有非抽象方法
-
接口
常量;抽象方法
-
-
关系区别(语法上)
-
类与类
继承,单继承
-
类与接口
实现,可以单实现,也可以多实现
-
接口与接口
继承,单继承,多继承
-
-
设计理念区别
-
抽象类
对类抽象,包括属性、行为
-
接口
对行为抽象,主要是行为
-
-
1、类名作为方法的形参
方法的形参是类名,其实需要的是该类的对象
实际传递的是该对象的【地址值】
-
2、类名作为方法的返回值
方法的返回值是类名,其实返回的是该类的对象
实际传递的,也是该对象的【地址值】
-
示例代码:
class Cat {
public void eat() {
System.out.println("猫吃鱼");
}
}
class CatOperator {
//类名作为方法的形参
public void useCat(Cat c) { //Cat c = new Cat();
c.eat();
}
//类名作为方法的返回值
public Cat getCat() {
Cat c = new Cat();
return c;
}
}
public class CatDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
CatOperator co = new CatOperator();
Cat c = new Cat();
co.useCat(c);
Cat c2 = co.getCat(); //new Cat()
c2.eat();
}
}
4.2 抽象类作为形参和返回值(理解)
-
抽象类作为形参和返回值
-
方法的形参是抽象类名,其实需要的是该抽象类的子类对象
-
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
-
-
示例代码:
abstract class Animal {
public abstract void eat();
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
class AnimalOperator {
public void useAnimal(Animal a) { //Animal a = new Cat();
a.eat();
}
public Animal getAnimal() {
Animal a = new Cat();
return a;
}
}
public class AnimalDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
AnimalOperator ao = new AnimalOperator();
Animal a = new Cat();
ao.useAnimal(a);
Animal a2 = ao.getAnimal(); //new Cat()
a2.eat();
}
}
4.3 接口名作为形参和返回值(理解)
-
接口作为形参和返回值
-
方法的形参是接口名,其实需要的是该接口的实现类对象
-
方法的返回值是接口名,其实返回的是该接口的实现类对象
-
-
示例代码:
interface Jumpping {
void jump();
}
class JumppingOperator {
public void useJumpping(Jumpping j) { //Jumpping j = new Cat();
j.jump();
}
public Jumpping getJumpping() {
Jumpping j = new Cat();
return j;
}
}
class Cat implements Jumpping {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
public class JumppingDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.useJumpping(j);
Jumpping j2 = jo.getJumpping(); //new Cat()
j2.jump();
}
}
作业重要知识点
-
static 修饰的属性,相较于实例变量,有哪些特别之处(>=3点)
随着类的加载而加载;早于对象的创建;只要权限允许,可以通过”对象.static属性”的方式进行调用;存在于方法区的静态域 1、static修饰的变量和方法,在类加载时即被初始化,可直接通过类名.变量名和类型.方法名进行调用。 2、static修饰的变量,在类加载时会被分配到数据区的方法区。类的实例可共享方法区中的变量。如果static修饰的变量发生改变,那么所有类实例引用的变量都会一起发生改变。 3、static修饰的方法中不能使用this或super,static修饰的方法属于类的方法,而this或super只是对象的方法。 4、static修饰的方法不能引用非static 修饰的变量, 在类加载过程中,当static修饰的方法加载完成时,非static修饰的变量还未加载,所以无法引用非static修饰的变量。 5、非static修饰的方法可以引用static 修饰的变量,在类加载过程中,static修饰的变量优先完成加载,所以当非static修饰的方法完成加载后可以引用static 修饰的变量。 -
final 可以用来修饰哪些结构,分别表示什么意思?
final可以用来修饰的结构:类、方法、变量。 * 1.final 用来修饰一个类:此类不能被其他类所继承。 * 比如:String类、System类、StringBuffer类 * * 2. final 用来修饰方法:表明此方法不可以被重写 * 比如:Object类中getClass(); * * 3. final 用来修饰变量:此时的"变量"就称为是一个常量 * 3.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中 初始化、构造器中初始化 * 3.2 final修饰局部变量: * 尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值 以后,就只能在方法体内使用此形参,但不能进行重新赋值。 * static final 用来修饰属性:全局常量
-
类的属性赋值的位置有哪些?先后顺序为何?
类中属性赋值方式: 1、默认初始化 2、显示初始化/ 代码块中赋值 3、构造器中赋值 4、通过对象调方法或属性赋值 赋值先后顺序:1-2-3-4 ;显示初始化、代码块中赋值写在前面的先赋值
-
abstract 能修饰哪些结构? 修饰以后,有什么特点?
1、可以修饰类 修饰后的类不能实例化,需要我们提供一个子类进行继承,如果这个子类是一个普通的类(非抽象类)的话就必须覆写抽象类中的所有抽象方法。 2、可以修饰方法 抽象方法只定义了一种功能的标准,具体的执行和实现需要子类去实现,接口的方法就是抽象方法。定义了方法而不实现,正因为这样,其子类可以有更多的展现空间和实现能力。 3、抽象类可以粗略的理解为可以写抽象方法的普通类,但是这个抽象类中也可以没有抽象方法,就好比只是给了一个普通类有了写抽象方法的资格但是不能实例化而已,下面是几个常见的问题 接口可以继承接口 抽象类能实现接口 抽象类能继承非抽象类 一个普通的类可以实现接口的同时并继承抽象类 4、不能修饰的有 不能修饰属性和构造器。 不能修饰私有方法、静态方法、final修饰的方法和final修饰的类
-
接口是否能继承接口? 抽象类是否能实现(implements)接口? 抽象类是否能继承非抽象的类?
能。能。能。
-
抽象类和接口有哪些共同点和区别?
共同点:都不能被实例化、都能包含抽象方法。 区别: 1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。(参照多态方式) 2、在成员上,抽象类有变量和常量,接口只有常量;抽象类有构造方法,接口没有;抽象类由抽象方法也有非抽象方法,而接口只能是抽象方法。 3、抽象类要被子类继承,并且是单继承;接口要被类实现,可以单实现,也可以是多实现。 4、在设计理念上:抽象类是对类抽象,包括属性、行为;接口是对行为抽象,主要是行为。



