欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > java面向对象编程【高级篇】之特殊类

java面向对象编程【高级篇】之特殊类

2025/5/4 5:59:19 来源:https://blog.csdn.net/2402_88461821/article/details/147595970  浏览:    关键词:java面向对象编程【高级篇】之特殊类

目录

  • 🚀前言
  • 🌟final关键字
    • 💯常量
  • 🦜单例类
    • 💯饿汉式单例类
    • 💯懒汉式单例类
  • ✍️枚举类
  • 🐍抽象类
    • 💯应用场景
    • 💯模版方法设计模式
  • ⚙️接口
    • 💯实现类
    • 💯接口的好处
    • 💯新增方法形式
    • 💯注意事项
    • 💯接口与抽象类的区别

🚀前言

在这里插入图片描述

大家好!我是 EnigmaCoder
本文介绍java面向对象编程中的一些特殊类,如单例类、枚举类、抽象类、接口等。

🌟final关键字

final在java表示的意思是最终的意思,也可以称为完结器,可以用final关键字声明类、方法、变量。

  • final声明的类为最终类,无法被继承。
  • final声明的方法无法被重写。
  • final声明的变量无法被再次赋值。
public class FinalDemo {public static  String NAME = "wang"; //  final变量private final int AGE = 18;//一般没有意义public static void main(String[] args) {final int a = 10;//a=1;  // 错误,final变量不能被修改final int [] b={1,2,3};//final修饰引用类型的变量b[0]=3;}}final class A {}// class B extends A {}// 错误,不能继承final类class C {public final void print(){System.out.println("Hello World");}
}class D extends C {//  @Override//  public void print(){//     System.out.println("Hello World");//   }//  错误,不能覆盖final方法}

final修饰变量的注意事项:

  • final修饰基础类型的变量,变量存储的数据不能被改变。
  • final修饰引用类型的变量,变量存储的地址不能被改变,但地址所指向对象的内容是可以被改变的。

💯常量

使用了static final修饰的成员变量就被称为常量。

  • 作用:常用于记录系统的配置信息。
  • 命名规范:要求所有字母大写,多个单词之间用下划线隔开。
public static final int MAX_SCORE=100;

🦜单例类

作用:确保某个类只能创建一个对象。

💯饿汉式单例类

饿汉式单例类是单例模式的一种实现方式,其核心思想是:在类加载时立即创建唯一的实例对象

实现步骤

  • 第一步:将类的构造器私有,确保单例类对外不能创建太多对象。
  • 第二步:定义一个类变量记住类的一个对象。
  • 第三步:定义一个类方法,返回对象。
public class A{//定义一个类变量记住类的一个对象private static A a =new A();//类的构造器私有private A(){}//定义一个类方法,返回对象public static A getObject(){return a;}
}

饿汉式单例是单例模式中最基础、最安全的实现方式之一,适合需要 “立即加载实例” 且对内存占用不敏感的场景。其核心优势是通过类加载机制天然保证线程安全,代码简洁可靠,是初学者学习单例模式的入门选择。

💯懒汉式单例类

懒汉式单例类是单例模式的另一种实现方式,其核心思想是:仅在第一次使用单例实例时才创建对象

实现步骤

  • 第一步:私有构造器
  • 第二步:定义一个静态的类变量用于存储对象
  • 第三步:提供一个类方法返回类的一个对象
public class B{//定义一个静态的类变量用于存储对象private static B b;//单例必须私有构造器private B(){}//提供一个类方法返回类的一个对象public static B getObject(){if(b==NULL){b=new B();}return b;}
}
  • 懒汉式单例的本质是 “用时间换空间”—— 通过延迟实例创建来节省资源,但需通过额外逻辑解决多线程安全问题。其核心思想可概括为:“不急着创建实例,直到真正需要时再创建,同时确保多线程环境下只有一个实例被创建。”
  • 实际开发中,推荐使用 静态内部类懒汉式 或 枚举式 实现,兼顾延迟加载与线程安全,代码简洁且高效。

✍️枚举类

枚举类是一种特殊的类。

  • 书写格式如下:
修饰符 enum 枚举类名{名称1,名称2 ...其他成员 ...

特点

  • 枚举类的第一行,只能写枚举类的对象名称,且要用逗号隔开。
  • 这些名称,本质是常量,每个常量都记住了枚举类的一个对象。
  • 枚举类都是最终类,不能被继承,枚举类都继承的是java.lang.Enum类。
  • 枚举类的构造器都是私有的(可以省略不写),因此,枚举类对外不能创建对象。
public enum A{X,Y,Z;
}public class Test{public static void main(String[] args){A a1=A.X;System.out.println(a1);A a2=A.Y;System.out.println(a2);A a3=A.Z;System.out.println(a3);System.out.println("--------------------------------");System.out.println(a1.name());System.out.println(a2.name());System.out.println(a3.name());System.out.println("--------------------------------");System.out.println(a1.ordinal());System.out.println(a2.ordinal());System.out.println(a3.ordinal()); }
}

运行结果:

X
Y
Z
--------------------------------
X
Y
Z
--------------------------------
0
1
2

由于枚举类都继承了java.lang.Enum类,所以枚举类可以使用父类的方法,例如,name()方法获取常量名、ordinal()方法获取索引。而且从运行结果的第一部分可知,父类重写了Object类的toString方法。

🐍抽象类

在java中有一个关键字叫:abstract,即抽象的意思,可以用它修饰类、成员方法。

  • abstract修饰类,这个类就是抽象类。
  • abstract修饰方法,这个方法就是抽象方法。

格式如下:

修饰符 abstract class 类名{修饰符 abstract 返回值类型 方法名称(形参列表);
}

特点:

  • 抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。
  • 抽象类中不一定要有抽象方法,有抽象方法的类必须是抽象类。
  • 抽象类也有成员变量、方法、构造器。
  • 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
public abstract class  A { public String name;public int age;public A() {System.out.println("A的无参构造器");}public A(String name, int age) {this.name = name;this.age = age;}public abstract void show();public void eat() {System.out.println("A类中的eat方法");}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;}
}public class B extends A {@Overridepublic void show() {System.out.println("B show");}}public class Test {public static void main(String[] args) {B b = new B();b.setName("wang");b.setAge(18);b.show();b.eat();System.out.println(b.getName());System.out.println(b.getAge());}
}

运行结果:

A的无参构造器
B show
A类中的eat方法
wang
18

💯应用场景

当父类知道每个子类都要做某个行为,但每个子类要做的事情不一样,父类就定义成抽象方法,交给子类去重写实现,这样去设计抽象类,可以更好的支持多态。

// 定义抽象类 Animal
abstract class Animal {// 抽象方法,用于发出叫声public abstract void makeSound();
}// 定义 Dog 类,继承自 Animal
class Dog extends Animal {@Overridepublic void makeSound() {System.out.println("汪汪汪");}
}// 定义 Cat 类,继承自 Animal
class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵喵");}
}public class AnimalSoundDemo {public static void main(String[] args) {// 创建 Dog 对象Animal dog = new Dog();// 创建 Cat 对象Animal cat = new Cat();// 调用不同动物的叫声方法dog.makeSound();cat.makeSound();}
}    

抽象类 Animal 定义抽象方法 makeSound(),表明父类知晓子类需实现该行为。DogCat 子类继承后重写方法,输出不同叫声。抽象类提供统一规范,让子类按需实现,利于代码扩展,完美诠释多态,增强程序灵活性与可维护性。

💯模版方法设计模式

模板方法设计模式是一种行为设计模式,它在一个抽象类中定义一个操作的算法骨架,而将一些步骤延迟到子类中实现。这样,子类可以在不改变算法整体结构的情况下,重新定义该算法的某些特定步骤,从而实现代码复用和行为的灵活定制。

// 抽象类,定义写作模板的骨架
abstract class WritingTemplate {// 模板方法,定义写作的整体流程public final void writeArticle() {System.out.println("以下是一篇精彩的文章开始:");introduceTopic();System.out.println("让我们进入正文部分,详细内容如下:");writeContent();System.out.println("接下来,为大家带来文章的总结:");concludeArticle();System.out.println("文章结束,感谢阅读。");}// 抽象方法,引入主题abstract void introduceTopic();// 抽象方法,撰写正文内容abstract void writeContent();// 抽象方法,总结文章abstract void concludeArticle();
}// 新闻稿写作类,继承自 WritingTemplate
class NewsArticleWriter extends WritingTemplate {@Overridevoid introduceTopic() {System.out.println("今日,一则重大消息在社会上引起了广泛关注。");}@Overridevoid writeContent() {System.out.println("据悉,该事件发生在城市的核心区域,影响范围涉及多个领域。相关部门迅速响应,展开了全面的调查和处理工作。");}@Overridevoid concludeArticle() {System.out.println("目前,事件仍在进一步发展中,我们将持续为您跟踪报道。");}
}// 散文写作类,继承自 WritingTemplate
class ProseWriter extends WritingTemplate {@Overridevoid introduceTopic() {System.out.println("在时光的长河中,有一片宁静的角落,那是心灵的港湾。");}@Overridevoid writeContent() {System.out.println("我在这静谧的世界里徘徊,聆听着微风的低语,感受着阳光的轻抚。每一朵花、每一片叶,都诉说着生命的故事。");}@Overridevoid concludeArticle() {System.out.println("这片宁静的角落,将永远珍藏在我的心中,成为我灵魂深处最温暖的回忆。");}
}// 主类,用于测试
public class WritingTemplateDemo {public static void main(String[] args) {// 创建新闻稿写作对象WritingTemplate newsWriter = new NewsArticleWriter();// 撰写新闻稿newsWriter.writeArticle();System.out.println();// 创建散文写作对象WritingTemplate proseWriter = new ProseWriter();// 撰写散文proseWriter.writeArticle();}
}    
以下是一篇精彩的文章开始:
今日,一则重大消息在社会上引起了广泛关注。
让我们进入正文部分,详细内容如下:
据悉,该事件发生在城市的核心区域,影响范围涉及多个领域。相关部门迅速响应,展开了全面的调查和处理工作。
接下来,为大家带来文章的总结:
目前,事件仍在进一步发展中,我们将持续为您跟踪报道。
文章结束,感谢阅读。以下是一篇精彩的文章开始:
在时光的长河中,有一片宁静的角落,那是心灵的港湾。
让我们进入正文部分,详细内容如下:
我在这静谧的世界里徘徊,聆听着微风的低语,感受着阳光的轻抚。每一朵花、每一片叶,都诉说着生命的故事。
接下来,为大家带来文章的总结:
这片宁静的角落,将永远珍藏在我的心中,成为我灵魂深处最温暖的回忆。
文章结束,感谢阅读。
  • 抽象类 WritingTemplate 定义了 writeArticle 模板方法,包含通用写作流程文本,将引入主题、撰写正文、总结文章设为抽象方法。
  • NewsArticleWriterProseWriter 子类继承该抽象类,各自实现抽象方法,输出新闻稿与散文对应内容。主类创建子类对象并调用 writeArticle 方法,展示不同类型文章写作。此设计实现代码复用,增强扩展性,利于维护和扩展新文章类型。

⚙️接口

java提供了一个关键字interface定义出接口。

格式如下

public interface 接口名{//成员变量(常量)//成员方法(抽象方法)
}

案例

public interface A {//1. 常量:接口中的常量,默认是public static finalint NUM= 1;//2. 抽象方法:接口中的方法,默认是public abstractvoid run();
}

注意:接口同样不能创建对象。

💯实现类

接口是用来被类实现(implements)的,实现接口的类称为实现类,一个类可以同时实现多个接口。

格式如下

修饰符 class 实现类类名 implements 接口1,接口2,接口3 ...{//实现类实现多个接口,必须重写完全部抽象方法,否则实现类需要定义成抽象类。
}
public class C implements A, B {@Overridepublic void run() {}@Overridepublic void eat() {}
}

💯接口的好处

  • 弥补了类单继承的不足,一个类同时可以实现多个接口,使类的角色更多,功能更强大。
// 定义绘画接口
interface Paintable {void paint();
}// 定义歌唱接口
interface Singable {void sing();
}// 定义教学接口
interface Teachable {void teach();
}// 定义一个人,他可以绘画、唱歌和教学
class Person implements Paintable, Singable, Teachable {@Overridepublic void paint() {System.out.println("这个人正在绘画,画出了美丽的风景。");}@Overridepublic void sing() {System.out.println("这个人正在唱歌,歌声很动听。");}@Overridepublic void teach() {System.out.println("这个人正在教学,传授知识。");}
}public class InterfaceBenefitDemo {public static void main(String[] args) {Person person = new Person();person.paint();person.sing();person.teach();}
}    

Person 类同时实现了这三个接口,意味着一个人可以同时具备绘画、唱歌和教学的能力。在 Java 里,类只能有一个直接父类,但通过实现多个接口,就能让类拥有更多角色和功能,弥补了单继承的不足。

  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(更有利于程序的解耦合)
// 定义消息发送接口
interface MessageSender {void sendMessage(String message);
}// 邮件消息发送实现类
class EmailSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("通过邮件发送消息: " + message);}
}// 短信消息发送实现类
class SMSSender implements MessageSender {@Overridepublic void sendMessage(String message) {System.out.println("通过短信发送消息: " + message);}
}// 消息服务类,依赖于消息发送接口
class MessageService {private MessageSender sender;public MessageService(MessageSender sender) {this.sender = sender;}public void processMessage(String message) {sender.sendMessage(message);}
}public class MessageSendingSystem {public static void main(String[] args) {// 使用邮件发送消息MessageSender emailSender = new EmailSender();MessageService emailService = new MessageService(emailSender);emailService.processMessage("这是一封重要邮件通知。");// 切换到短信发送消息MessageSender smsSender = new SMSSender();MessageService smsService = new MessageService(smsSender);smsService.processMessage("这是一条紧急短信提醒。");}
}    

main 方法中,我们可以轻松地切换不同的消息发送方式,只需要创建不同的消息发送实现类对象,并将其传递给 MessageService 类即可。这体现了面向接口编程的灵活性,同时也实现了程序的解耦合。如果需要添加新的消息发送方式,只需要创建一个新的类实现 MessageSender 接口,而不需要修改 MessageService 类的代码。

💯新增方法形式

JDK8开始,接口新增了三种形式的方法:

public interface A{//1.默认方法(实例方法):使用default修饰,默认会加上public修饰。//注意:只能使用接口的实现类对象调用。default void test1(){}//2.私有方法:必须用private修饰(JDK9开始才支持)private void test2(){}//3.类方法(静态方法):使用static修饰,默认会被加上public修饰//注意:只能用接口名调用static void test3(){}
}

💯注意事项

  • 接口与接口可以多继承:一个接口可以同时继承多个接口。
  • 类与类:单继承 一个类只能继承一个直接父类。
  • 类与接口:多实现 一个类可以同时实现多个接口。
  • 接口与接口:多继承 一个接口可以同时继承多个接口。
interface A{
}
interface B{
}
interface C extends A,B{
}
  • 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承也不支持多实现。
interface A{void show();
}
interface B{
String show();
}
interface C extends A,B{
}
class D implements A,B{
}

此时会报错。将String改为void后,就不会报错。

  • 一个类继承的父类又同时实现了接口,如果父类中和接口中有相同的方法,实现类会优先用父类的。
interface A{void show();
}
interface B{void show();
}
class C extends A implements B{
}

此时实现类会使用父类中的show方法。

  • 一个类实现了多个接口,如果多个接口中存在同名的方法,可以不冲突,这个类重写该方法即可。
interface A{void show();
}
interface B{void show();
}
class C implements A,B{@Overridepublic void show(){A.super.show();B.super.show();}

💯接口与抽象类的区别

对比维度抽象类接口
实例化能力不能直接实例化,需由具体子类继承并实现抽象方法后,才可创建子类对象。不能直接实例化,需由类实现接口的所有抽象方法后,创建该类的对象。
成员变量可以有普通成员变量,成员变量的访问修饰符可以是 privateprotectedpublic 等。只能有常量,成员变量默认且必须是 public static final 修饰。
构造方法可以有构造方法,用于初始化抽象类的成员变量,子类实例化时会调用抽象类的构造方法。没有构造方法,因为接口不存在需要初始化的成员变量。
方法类型可以包含普通方法、抽象方法。普通方法有具体的实现逻辑,抽象方法只有方法声明。Java 8 之前只有抽象方法;Java 8 引入默认方法和静态方法,Java 9 引入私有方法。默认方法有默认实现,静态方法属于接口本身。
继承/实现规则一个类只能继承一个抽象类,遵循单继承原则。一个类可以实现多个接口,实现了多继承的功能。
关系体现体现“is - a”关系,即子类是抽象类的一种具体类型,强调类的从属关系。体现“can - do”关系,即类具备接口所定义的能力,强调功能的实现。
访问修饰符抽象方法的访问修饰符可以是 protectedpublic;普通方法可以是各种合法的访问修饰符。接口中的方法默认是 public abstract,不允许使用其他访问修饰符;常量默认是 public static final
设计目的用于对一组具有相似特征和行为的类进行抽象,提取共性,方便代码复用和扩展。用于定义一组行为规范,使得不同的类可以实现相同的行为,提高代码的可扩展性和可维护性。
代码维护复杂度当抽象类需要修改时,可能会影响到所有继承它的子类,维护复杂度相对较高。接口修改时,如果只添加默认方法或静态方法,不会影响实现类;但如果修改抽象方法,会影响所有实现类。
使用频率场景适用于具有共同属性和行为,且部分行为实现逻辑相同的一组类。适用于不同类之间需要实现相同的功能,但这些类在本质上没有继承关系的场景。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词