大家好,欢迎来到IT知识分享网。
文章目录
一、抽象类是什么?
1.1 概念
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
shape是图形,是个抽象的概念,以抽象类的形式存在,来规范子类。
1.2 抽象类的作用
- 代码复用
抽象类可以包含一些通用的方法实现,这些方法可以被子类直接继承和使用,避免了代码重复。
例如,一个图形绘制的抽象类可能包含一个计算图形面积的通用方法,不同的具体图形子类可以继承这个方法来计算各自的面积。 - 强制规范
强制子类实现某些特定的方法。由于抽象类中存在抽象方法,子类必须实现这些方法,否则子类也必须被声明为抽象类。
这确保了在不同的实现场景下,都有统一的接口和行为规范。 - 易于维护和扩展
当需要对一组相关类进行修改或扩展时,只需要在抽象类中进行修改,所有的子类都会自动继承这些修改。
比如,如果要在图形绘制的抽象类中添加一个新的通用方法,所有的图形子类都可以立即使用这个新方法。
二、定义抽象类
注意:抽象类的存在就是为了被继承的
2.1 abstract关键字
用abstract关键字来定义抽象类和方法
public abstract class Shape {
}
如果一个类中有抽象方法,那么这个类必须是抽象类
抽象方法只有方法签名而没有具体的实现。它的存在是为了定义一种行为规范,让子类去具体实现这种行为。如果一个非抽象类中包含抽象方法,那么当尝试创建该类的对象时,由于无法确定如何执行抽象方法,就会导致错误。
2.2 抽象类与普通类的区别
抽象方法可以没有具体实现,它的存在是为了规范子类的方法,因为子类必须重写这个方法,来实现对应子类的方法。
抽象类是无法被实例化的
但我们根据编译器的提示我们可以发现,我们可以通过下面这种方式实现实例化
但这并不是想我们想的那样直接实例化了抽象类,而是通过 new Shape() {… }创建了一个匿名内部类,这个匿名内部类继承自抽象类Shape。再在大括号内重写抽象类的所有抽象方法,然后将这个内部类实例化赋值给了shape这个引用变量。
通过这种方式,可以在不明确命名一个具体子类的情况下,快速地为抽象类创建一个具有特定实现的对象。但需要注意的是,这个对象实际上是匿名内部类的实例,而不是抽象类Shape的直接实例。
由上面的介绍我们可以得知,抽象类是为了子类的规范而存在的,而且无法被实例化,所以抽象类无法被final修饰,方法也不可以被private修饰符修饰
这里我们发现,如果我在抽象类中定义了一个静态方法,在main方法中还是可以通过抽象类来调用静态方法的,由此我们可以知道,抽象类本质还是一个类,它与普通类的区别在于,它可以拥有抽象方法,无法被实例化,但对于类本身的属性是可以拥有的(比如静态方法)。
所以我们抽象方法也是可以拥有成员变量和构造方法的,可以理解为它是一个无法实例化的父类,但父类普通类可以拥有的部分它也可以拥有,子类同样要先调用父类抽象类的构造方法。
同时我们也可以实现向上转型和向下转型
//抽象类 public abstract class Shape {
private int circumference;//周长 public Shape(int circumference) {
this.circumference = circumference; } public int getCircumference() {
return circumference; } public void setCircumference(int circumference) {
this.circumference = circumference; } public abstract void draw();//抽象方法 public abstract void area(); public static void print(){
//静态方法 System.out.println("haha"); } }
//子类——圆形 public class Circle extends Shape{
public Circle(int circumference) {
super(circumference); } @Override public void draw() {
System.out.println("画圆圈"); } @Override public void area() {
} public void circleUniqueFunction(){
System.out.println("Circle类中独有的方法被调用"); } }
//测试类 public class Test {
public static void draw1(Shape shape){
shape.draw(); } public static void main(String[] args) {
draw1(new Circle(0)); Shape shape = new Circle(0); if(shape instanceof Circle){
((Circle)shape).circleUniqueFunction(); } } }
三、有关匿名内部类和匿名对象的补充
上面我们提到了匿名对象和匿名内部类,这里可以再补充一下(AI的解释居多,确实更加全面感觉,嘻嘻~)
3.1 匿名对象
匿名对象是一种没有显式命名的对象。在 Java 中,当你创建一个对象但没有为其分配一个变量名时,就创建了一个匿名对象。
在这段代码中就使用了匿名对象:
draw1(new Circle(0));
匿名对象的作用:
- 在某些情况下,可以使代码更加简洁,特别是当只需要使用一个对象一次时,无需为其分配一个变量名。
例如,调用一个方法并传递一个对象作为参数时,如果这个对象只在这一处使用,使用匿名对象可以避免创建额外的变量。 - 临时使用:适合用于临时的操作或一次性的任务,创建后立即使用,然后被垃圾回收。
比如在进行一些临时的计算或数据处理时,创建一个匿名对象来执行特定的操作,而不需要在其他地方再次引用这个对象。
局限性:
- 无法再次引用:由于没有命名变量,所以无法在后续的代码中再次引用这个对象。一旦创建并使用后,就不能对其进行进一步的操作,除非通过其他方式(如方法的返回值或参数传递)再次获取到这个对象。
- 内存管理:匿名对象在使用后可能会被垃圾回收器回收,具体的回收时机取决于 Java 的垃圾回收机制。如果频繁创建匿名对象,可能会导致一定的内存开销和垃圾回收压力。
3.2 匿名内部类
匿名内部类是没有名称的内部类,通常在需要实现一个接口或继承一个抽象类时使用。它是在创建对象的同时定义类的实现,直接在代码中实现了接口或抽象类中的方法。(接口相关内容将在下一次的文章中介绍)
这段代码就涉及了匿名内部类:
Shape shape =new Shape() {
@Override public void draw() {
} @Override public void area() {
} };
用途:
- 实现特定接口或继承抽象类:当只需要在一个特定的地方实现一个接口或继承一个抽象类时,匿名内部类非常有用。它可以快速地为接口或抽象类提供具体的实现,而无需单独定义一个命名的类。
例如,这里通过匿名内部类快速地为抽象类Shape提供了具体的实现,而不需要单独创建一个命名的子类来继承这个抽象类。。
Shape shape =new Shape() {
@Override public void draw() {
System.out.println("内部类的draw方法"); } @Override public void area() {
System.out.println("内部类的area方法"); } };
- 局部定制:可以在创建匿名内部类的地方进行局部的定制和扩展。可以根据具体的需求重写父类或接口中的方法,实现特定的功能。
例如,这里匿名内部类快速地为抽象类Shape提供了具体的实现,同时增加了自己独有的方法,实现了特定的功能。
Shape shape =new Shape() {
@Override public void draw() {
System.out.println("内部类的draw方法"); } @Override public void area() {
System.out.println("内部类的area方法"); } public void unique(){
System.out.println("内部类中额外加的unique方法"); } };
局限性:
- 可读性:匿名内部类的代码通常比较紧凑,可能会降低代码的可读性。特别是当匿名内部类的实现比较复杂时,代码可能会变得难以理解和维护。
- 可维护性:由于没有名称,匿名内部类难以在其他地方进行复用。如果需要在多个地方使用类似的实现,最好定义一个命名的类。
调试困难:在调试时,匿名内部类可能会增加调试的难度,因为没有明确的类名来标识代码的位置。
注意我在这里使用的Shape shape =new Shape(),括号里没有加任何数字,直接复制了我上面的代码的,会报错,因为我在抽象类中还有一个周长的成员变量以及构造方法需要初始化变量,这里的两个例子中的代码我是默认没有那个成员变量和构造方法的,只是为了解释匿名内部类
总结
本篇文章介绍了有关抽象类的内容,包括什么是抽象类,如何定义抽象类,以及抽象类的相关作用和注意要点,与普通类的区别,还有什么是匿名对象和匿名内部类,如果有什么错误的地方,还望指正,我会尽快更正,谢谢大家!!!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/116521.html