1.概述:在Java中,一个没有方法体的方法应该定义为抽象方法,当类中有抽象方法的时候,该类必须定义为抽象类。
2.特点:
(1)抽象类和抽象方法必要用abstract关键字修饰
抽象类格式: abstract class 类名 { }
抽象方法格式:public abstract 返回值 方法名()
(2)抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
(3)抽象类可以有构造方法,抽象类不能进行实例构造。抽象类中的构造方法便于子类访问父类数据时的初始化
(4)抽象类的实例化:按照多态的形式,有具体的子类实例化。抽象类多态
(5)抽象类的子类要么是抽象类,要么重写抽象类中的所有抽象方法
3.抽象类的成员特点:
(1)成员变量:可以是变量,也可以是常量
(2)成员方法:抽象方法和非抽象方法都可以
(3)构造方法:抽象类中有构造方法,用于子类访问父类数据的初始化
4.抽象类的练习
public class Test01 {
public static void main(String[] args) {
//new一个子类的时候,会调用父类的构造方法
BB bb = new BB();
bb.show();
}
}
abstract class AA{
//抽象类作为父类的构造方法,用于子类访问父类的初始化
public AA(){
System.out.println("抽象方法的构造方法");
}
public abstract void show();
}
class BB extends AA{
//重写父类的show方法
@Override
public void show() {
System.out.println("继承抽象类重写的抽象方法");
}
}
运行结果:
一个类如果没有抽象方法,也可以定义为一个抽象类,这样的话这个类就不能够创建对象。
abstract关键字不能与private关键字共存:private为私有,不能被继承更谈不上重写
abstract关键字不能与final关键字共存:当final修饰成员方法是,被修饰的成员方法不能被重写
abstract关键字不能与static共存:static修饰的方法为静态方法,属于类所有。
1.接口的概述:为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现。
2.接口的特点:
(1)接口用关键字interface表示 格式: interface 接口名 { }
(2)类实现接口使用implements关键字 格式: class 类名 implements 接口名 { }
(3)接口使用多态进行实例化
(4)接口的子类
a.可以是抽象类,但是意义不大
b.可以是具体类,要重写接口中的所有抽象方法
3.接口的成员特点:
(1)成员变量:只能是常量,并且是静态的。默认修饰符:public static final
(2)构造方法:接口中不存在构造方法
(3)成员方法:只能是抽象方法,默认修饰符:public abstract
4.接口练习:
public class Test01 {
public static void main(String[] args) {
//使用多态进行实例化
MyInterface aa = new AA();
//静态 常量通过类名调用
int num = MyInterface.NUM;
System.out.println(num);//20
int a = MyInterface.a;
System.out.println(a);//15
int a1 = AA.a;
System.out.println(a1);//15
int num1 = AA.NUM;
System.out.println(num1);//20
aa.show();
aa.test();
}
}
interface MyInterface{
//接口中的成员变量全部都是公共的静态常量,public static final 可以默认不写
public static final int NUM=20;
int a=15;
public abstract void show();
public abstract void test();
}
class AA implements MyInterface{
//注意:实现类必须重写接口的所有抽象方法
@Override
public void show() {
//重写接口的show方法
System.out.println("AA方法的show方法");
}
@Override
public void test() {
//重写接口的test方法
System.out.println("AA方法的test方法");
}
}
补充: jdk1.8之后接口中可以定义一种default修饰方法修饰,default修饰方法时可以给出功能的具体实现
public class Test03 {
public static void main(String[] args) {
In in = new In();
in.show();//实现的show方法
in.test();//重写过后的test方法
in.test2();//接口中的default关键字,可以给出功能的具体实现
}
}
interface Myinterface {
public abstract void show();
//接口中的方法使用default修饰,可以给出方法的功能的具体实现
public default void test() {
System.out.println("接口中的default关键字,可以给出功能的具体实现");
}
public default void test2() {
System.out.println("接口中的default关键字,可以给出功能的具体实现");
}
}
class In implements Myinterface {
@Override
public void show() {
System.out.println("实现的show方法");
}
@Override
public void test() {
System.out.println("重写过后的test方法");
}
}
5.类与接口之间的关系:
(1)类与类:继承关系,可以单继承,可以多继承
(2)类与接口:实现关系,可以单实现,也可以多实现,并且在继承一个类的时候同时实现多个接口
(3)接口与接口:继承关系,可以单继承,也可以多继承
public class Test02 {
public static void main(String[] args) {
MyTest test1 = new MyTest();
test1.aa();//aa
test1.bb();//bb
Zi zi = new Zi();
zi.aa();//ziaa
zi.bb();//zibb
zi.cc();//zicc
}
}
interface AAA{
public abstract void aa();
}
interface BBB{
public abstract void bb();
}
//接口可以继承多个接口,并且继承接口的所有抽象方法
interface CCC extends AAA,BBB{
public abstract void cc();
}
//一个类可以实现多个接口,必须重写实现接口的所有抽象方法
//当有类实现这个接口时,必须重写本身与继承下来的所有抽象方法
class MyTest implements AAA,BBB{
@Override
public void aa() {
System.out.println("aa");
}
@Override
public void bb() {
System.out.println("bb");
}
}
class Zi implements CCC{
@Override
public void cc() {
System.out.println("zicc");
}
@Override
public void aa() {
System.out.println("ziaa");
}
@Override
public void bb() {
System.out.println("zibb");
}
}
一、成员区别:
抽象类:成员变量:可以常量,也可以变量
构造方法:有(抽象类中的构造方法便于子类访问父类数据时的初始化)
成员方法:可以抽象,也可以非抽象
接口: 成员变量:只能是常量(public static final)
成员方法:只可以抽象(public abstract)
构造方法:无
二、关系区别:
类与类:继承,单继承
类与接口:实现,单实现和多实现
接口与接口:继承,单继承与多继承
三、设计理念
抽象类:被继承体现的是“is a”的关系,抽象类中定义的是该继承体系的共性功能
接口:被实现体现的是“like a”的关系,接口中定义的是该继承体系的扩展功能
接口与类的案例:
public class Test04 {
public static void main(String[] args) {
//多态形式定义
Animals animals = new Cat.JiaYangMao();
animals.name="家养猫";
animals.age=3;
System.out.println(animals.name);//家养猫
System.out.println(animals.age);//3
animals.eat();//家养猫吃鱼干
//sleep为特有方法,必须将animals向下转型才可以调用
Cat.JiaYangMao jiaYangMao= (Cat.JiaYangMao) animals;
jiaYangMao.sleep();//睡觉
Cat.ZhaoCaiMao zhaoCaiMao = new Cat.ZhaoCaiMao();
animals=zhaoCaiMao;
animals.name="招财猫";
animals.age=5;
System.out.println(animals.name);//招财猫
System.out.println(animals.age);//5
animals.eat();//招财猫吃猫粮
//多态定义
Jump jump=zhaoCaiMao;
jump.jump();//招财猫学会了跳高
}
}
//定义一个动物类,里面具有公共的属性
class Animals{
String name;
int age;
public void eat(){
System.out.println("吃饭");
}
}
//定义一个接口
interface Jump{
public abstract void jump();
}
//Cat类继承Animals类,重写eat方法。并且实现jump接口
class Cat extends Animals{
//重写父类的eat方法
@Override
public void eat() {
System.out.println("猫能够吃鱼");
}
static class ZhaoCaiMao extends Cat implements Jump{
@Override
public void eat() {
System.out.println("招财猫吃猫粮");
}
//重写接口的jump方法
@Override
public void jump() {
System.out.println("招财猫学会了跳高");
}
}
static class JiaYangMao extends Cat{
@Override
public void eat() {
System.out.println("家养猫吃鱼干");
}
//特有方法
public void sleep(){
System.out.println("睡觉");
}
}
}
public class Test05 {
public static void main(String[] args) {
//类名作为形式参数
Student student = new Student();
test(student,200);
System.out.println(student.num);//200
student.show(new Student(),300);
//打印的依旧是第一个对象的num为200
System.out.println(student.num);//200
}
public static void test(Student student,int num){
student.num=num;
}
}
class Student{
int num=100;
public void show(Student student,int num){
student.num=num;
System.out.println("show方法");
}
}
当一个方法的参数需要一个抽象类类型时,传入这个抽象类的子类对象。
public class Test06 {
public static void main(String[] args) {
//当一个方法的参数需要一个抽象类类型时,传入这个抽象类的子类对象
//创建一个子类对象
zilei z = new zilei();
//test方法传入子类对象一个int类型的值
test(z,500);
//子类对象的num值
System.out.println(z.num);//300
}
public static void test(Chouxianglei chouxianglei,int num){
//父类的num值改变为传入的num值
chouxianglei.num=num;
chouxianglei.show(400);
}
}
abstract class Chouxianglei{
int num=200;
public abstract void show(int num);
}
class zilei extends Chouxianglei{
int num=300;
@Override
public void show(int num) {
//num为传入的参数值
System.out.println("实现抽象类的show方法"+num);//实现抽象类的show方法400
//父类的num发生了改变
System.out.println(super.num);//500
System.out.println(this.num);//300
}
}
当方法的参数是一个接口时,传入该接口的实现类
public class Test07 {
public static void main(String[] args) {
//当方法的参数是一个接口时,传入该接口的实现类
implementationClass imp1 = new implementationClass();
test(imp1,300);
//实现类的num值
System.out.println(imp1.num);//100
}
public static void test(Jiekou jiekou,int num){
jiekou.show(num);
}
}
interface Jiekou{
public static final int NUM=200;
public abstract void show(int num);
}
class implementationClass implements Jiekou{
int num=100;
@Override
public void show(int num) {
System.out.println("实现类的show方法"+num);//实现类的show方法300
System.out.println(this.num);//100
}
}
public class Test02 {
public static void main(String[] args) {
//创建一个类的对象
Student student2 = new Student();
Student test = test(student2, 200);
//新建类的对象传参
System.out.println(student2.num);//200
System.out.println(test.num);//100
//this关键字,谁调用谁改变
student2.show(student2,300);
System.out.println(student2.num);//300
}
public static Student test(Student student,int num){
student.num=num;
Student student1 = new Student();
return student1;
}
}
class Student{
int num=100;
public void show(Student student,int num){
this.num=num;
}
}
当方法的返回值为抽象类时,返回该抽象类的子类对象
public class Test03 {
public static void main(String[] args) {
Aclass aclass = test(new Bclass(), 200);
//返回的是一个抽象类的对象,该对象的num值为抽象类的num
int num = aclass.num;
System.out.println(num);//100
aclass.show(300);
}
public static Aclass test(Aclass aclass,int num){
//方法的返回值为一个抽象类,返回一个该抽象类的子类对象
aclass.num=num;
return new Bclass();
}
}
abstract class Aclass{
int num=100;
public abstract void show(int num);
}
class Bclass extends Aclass{
@Override
public void show(int num) {
System.out.println(num);//300
System.out.println(this.num);//100
System.out.println(super.num);//100
}
}
接口作为返回值类型,返回该接口的一个实现类
public class Test04 {
public static void main(String[] args) {
Myinterface myinter = test(new MyTest(), 500);
myinter.show(300);//300
}
public static Myinterface test(Myinterface myinterface,int num){
//接口作为返回值类型,返回该接口的一个实现类
System.out.println(num);//500
return new MyTest();
}
}
interface Myinterface{
public abstract void show(int num);
}
class MyTest implements Myinterface{
@Override
public void show(int num) {
System.out.println(num);
}
}