抽象类
抽象类的概念
这种只给出方法定义而不具体实现的方法被称为抽象方法,(抽象方法是没有方法体的)
在一个类中,如果该类中存在一个功能,仅仅方法声明,没有方法体(抽象方法),需要将该类定义为抽象类,如:动物–本身就不是具体的(抽象动物类),将动物的吃或者睡定义为抽象功能。
-
使用abstract关键字修饰的方法称之为抽象方法
-
抽象方法没有方法体
-
抽象方法必须在抽象类里
-
抽象方法必须在子类中被实现,除非子类是抽象类
-
语法:
[访问修饰符] abstract class <类名> {
}
抽象方法
抽象方法是以abstract修饰的方法,仅有声明而没有方法体。如:
abstract void A();
当一个子类继承某个抽象类时,它可以有两个选择:
-
部分实现或完全不实现父类的所有抽象方法,但此时子类必须声明为抽象类。
-
实现父类所有的抽象方法,此时之类不比声明为抽象类。
包含抽象方法的类叫做“抽象类 ”。如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的。(否则,编译器就会报错。)
抽象类不能被实例化(be instantiated),但可以实例化非抽象子类。
什么是抽象方法?
-
使用abstract关键字修饰的方法称之为抽象方法
-
抽象方法没有方法体
-
抽象方法必须在抽象类里
-
抽象方法必须在子类中被实现,除非子类是抽象类
-
结论
-
有抽象方法的类必然是抽象类。
-
但抽象类中的方法并不一定都是抽象方法。
-
抽象方法只有方法声明,无具体实现。
抽象类的优点
1.提高可重用性
-
抽象类可以看作是类的一个模版,定义了子类的行为,可以为子类提供默认实现,无需子类中重复实现这些方法
2.代码松耦合,更易于维护
-
子类可以分别实现抽象父类中定义的抽象方法,将方法定义和方法实现的分离
3.方便实现多态
-
抽象类作为继承关系下的抽象层,不能被实例化,通常定义抽象类类型变量,其具体引用是实现抽象类的子类对象
抽象类的应用场合
-
抽象类用来列举一个类所需要的共性行为
-
抽象类不明确提供具体实现方法
-
抽象类必须由其子类实现它的抽象方法(除非子类也具有抽象性)
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
-
抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
-
一个类只能继承一个抽象类,而一个类却可以实现多个接口。
抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。
抽象类和普通类最大的区别是,抽象类不能被实例化,需要继承抽象类才能实例化其子类。
public abstract class A {
protected int x;
private int y;
public abstract void func1();
public void func2() {
System.out.println("func2");
}
}
继承
public class B extends A {
@Override
public void func1() {
System.out.println("func1");
}
}
使用
A a = new B();
a.func1();
抽象类存在的意义和作用
抽象是将共性抽离出来,产生抽象性概念非具体。
抽象类和抽象方法作用: 使类的抽象性明确起来,告诉用户和编译器打算怎么使用他们。抽象类还是很有用的重构工具,因为它们使得我们可以很容易地将公共方法沿着继承层次结构向上移动。
抽象类不可实例化,抽象类包含普通方法和抽象方法。抽象方法只需声明无需方法体。
子类继承抽象类,父类的抽象方法必须被子类重写,普通方法可不需要重写。
父类
abstract class Bird {
public String fly(){
return "fly";
}
public abstract void eat();
public abstract void sleep();
}
子类
public class BlueBird extends Bird {
@Override
public void eat() {
System.err.println("eat BlueBird");
}
@Override
public void sleep() {
System.err.println("sleep BlueBird");
}
}
抽象类和接口的区别以及使用场景
1. 相同点
-
两者都是抽象类,都不能实例化。
-
interface实现类和被abstract修饰class的子类都必须要实现已经声明的抽象方法
2. 不同点
-
interface需要实现,要用implements,而abstract class需要继承,要用extends。
-
一个类可以实现多个interface,但一个类只能继承一个abstract class。
-
interface强调特定功能的实现,而abstract class强调所属关系。
抽象类与抽象方法使用总结
-
抽象方法只有方法声明,没有方法实现
-
有抽象方法的类必须声明为抽象类
-
子类必须重写所有的抽象方法才能实例化;否则,子类也必须声明成抽象类
-
抽象类中可以没有、有一个或多个抽象方法,甚至可以定义全部方法都是抽象方法
-
抽象类可以有构造方法,其构造方法可以被本类的其他构造方法调用
-
不是由private修饰构造方法,可以被其子类的构造方法调用
-
-
abstract可以用来修饰类和方法,不能用来修饰属性和构造方法
abstract关键字
-
abstract:抽象的
-
abstract可以用来修饰的结构:类、方法
-
类
public abstract class A {
}
-
方法
public abstract void print();
-
abstract修饰类:抽象类
-
abstract修饰方法:抽象方法
abstract使用上的注意点:
-
abstract不能用来修饰,属性、构造器等结构
-
abstract不能用来修饰私有方法、静态方法、final方法、final的类
final关键字
语法:
public final class Puppy extends Dog {
}
方法不希望被重写? 使用final方法
public class Student {
public final void print() {
System.out.println("我是一个学生!");
}
}
属性值不希望被修改? 使用常量
public class Dog {
final String name ="帅帅";
public void setName(String name) {
this.name=name; //编译错误,不可再赋值
}
}
常见错误:
1.使用final修饰引用型变量,变量的值是固定不变的,而变量所指向的对象的属性值是可变的
public class Student {
String name;
public Student(String name) {
this.name = name;
}
public static void main(String[] args) {
final Student stu = new Student("李明");
stu.name = "李明航";
stu = new Student("王亮");//编译错误,使用final修饰的引用型变量不可以再指向其他对象
}
2.使用final修饰的方法参数,这些参数的值是固定不变的
class Value {
int v;
}
public class Test {
public void changeValue(final int i, final Value value) {
i = 8; //编译错误:使用final修饰的方法参数,在整个方法中不能改变参数值
value.v = 8;
}
}
总结:
final可以用来修饰类、方法和属性,不能修饰构造方法
Java提供的很多类都是final类,不能重写
如:String类、Math类 Object类有一些final方法,只能被子类继承而不能被重写
如:getClass( )、notify( )、wait( ) Object类的hashCode( )、toString( )、equals(Object obj)方法不是final方法,可以被重写
经验:
abstract和static不能结合使用 abstract和private不能结合使用 abstract和final不能结合使用