作为后端开发,感受下接口带来的魅力!🔥🔥

简介: 在一场大厂面试中,小南被问及何时选用接口,何时采用抽象类。一位拥有24K粉丝的博主给出解答:选择取决于需求——接口定义多个类需遵守的契约,而抽象类则用于创建共享实现的基类。有时两者结合使用,通过抽象类实现接口以确保契约并提供通用功能。此外,小南还分享了关于抽象类的深入探讨,包括子类如何正确调用父类构造函数、访问父类成员以及父类不可访问的方法等细节。最后,他提出一个关于接口与抽象类差异的小测验,并邀请读者关注他的开源项目《Java学习进阶指南》,旨在帮助Java开发者更好地掌握核心知识和面试要点。

点赞再看,Java进阶一大半

在一次某大厂面试中,小南(化名)被面试官问到:写代码你什么时候选择用接口,什么时候用抽象类?

一位海外博客拥有24k粉丝的程序员博主是这么回答的,友们怎么看?

在这里插入图片描述

Java 接口和抽象类之间的选择取决于您的特定要求。如果您需要定义多个不相关的类需要遵循的契约,请使用接口。但是,如果您想创建具有共享实现细节的可重用基类,请选择抽象类。在某些情况下,您甚至可以同时使用两者,使用抽象类实现接口来执行契约并为相关类提供通用基础。请记住考虑每个选项的优缺点,为您的软件设计做出最佳选择。

大家好,我是南哥。

一个Java学习与进阶的领路人,相信对你通关面试、拿下Offer进入心心念念的公司有所帮助。

1. 抽象类

1.1 子类调用父类

现在有IDEA集成开发环境,可以给大家实时提醒哪个地方编译错误,但假如要大家用.txt文件编写程序呢。南哥问:现在这段代码错在了哪?

class Base {
   
   
    public Base(String s) {
   
   
        System.out.print("B");
    }
}

public class Derived extends Base {
   
   
    public Derived (String s) {
   
   
        System.out.print("D");
    }
    public static void main(String[] args) {
   
   
        new Derived("C");
    }
}

假如父类和子类同时拥有有参构造方法,子类的构造方法必须显性地调用父类的构造方法,否则会编译错误。所以正常的写法应该是这样。

    public Derived (String s) {
   
   
        super(s);  
        System.out.print("D");
    }

另外大家还需要注意一点,调用父类的构造方法必须在子类构造方法的第一行,调用父类的构造方法也只能出现在子类的构造方法上,否则也会是编译报错。

1.2 子类访问父类

如下代码,一共有两处编译错误。提示:错误在Child类里,能快速找出来吗?

class Parent {
   
   
    public static String staticVar = "Static Variable from Parent";
    private static String privateStaticVar = "Private Static Variable from Parent";

    public static void staticMethod() {
   
   
        System.out.println(staticVar);
    }

    private static void privateStaticMethod() {
   
   
        System.out.println(privateStaticVar);
    }
}

class Child extends Parent {
   
   
    public void staticMethod() {
   
   
        System.out.println("Static method in Child");
    }

    public void display() {
   
   
        System.out.println(staticVar);

        System.out.println(privateStaticVar);
        privateStaticMethod();

        staticMethod();
}

(1)父类的私有变量、私有方法,子类是有继承的,但是不能访问。所以Child.display()里的以下调用是编译错误的。

System.out.println(privateStaticVar);
privateStaticMethod();

(2)子类可以继承,同时也可以访问父类的static变量、方法。但父类的static方法大家需要注意,子类是不能直接覆盖的,所以以下代码会编译错误。

    public void staticMethod() {
   
   
        System.out.println("Static method in Child");
    }

正确的做法是为该方法添加一个static修饰符,代表这是子类的一个新方法。这种写法叫做方法隐藏,子类和父类中都有一个相同名称和参数的静态方法时,子类的方法将隐藏父类的方法。

    public static void staticMethod() {
   
   
        System.out.println("Static method in Child");
    }

另外如果父类的方法使用final修饰,子类也是不能覆盖的。

1.3 父类不可访问的方法

紧跟着上文代码的例子,父类的方法同样使用static修饰,子类的privateStaticMethod方法算不算覆盖父类的方法呢?有没有编译报错?

class Parent {
   
   
    public static String staticVar = "Static Variable from Parent";
    private static String privateStaticVar = "Private Static Variable from Parent";

    private static void privateStaticMethod() {
   
   
        System.out.println(privateStaticVar);
    }
}

class Child extends Parent {
   
   
    public void privateStaticMethod() {
   
   
        System.out.println(staticVar);
    }
}

答案是编译正常。

父类中不可访问的方法,子类编写相同名称和参数的方法并不算覆盖。父类的方法都不能访问了,也就没有覆盖这一说法了。。。

2. 接口

2.1 访问修饰符的区别

接口和抽象类有三个方面的区别,分布是类的修饰、方法的修饰、变量的修饰。我们往下看看。

(1)类

接口使用interface修饰,而抽象类使用abstract修饰。当它们作为外部类时,只能使用public、default修饰,不能使用private修饰。

(2)方法

普通接口方法只能由public abstractdefaultstatic修饰。

抽象接口方法可以由所有修饰符修饰,除了final。

总结下,它们两者也有共同点,就是都不能使用final修饰。

(3)变量

普通接口变量只能由public static final修饰。

抽象接口变量可以由所有修饰符修饰。

2.2 静态分派

这算是一个很偏的知识点了,如下代码有三个名为getType的重载方法,它们的返回类型相同、方法名也相同,只有入参类型不同。

南哥问:程序执行结果是什么?

public class Test {
   
   
    public static void main(String[] args) {
   
   
        for(Collection<?> collection: collections) {
   
   
            System.out.println(getType(collection));
        }
    }

    public static final Collection<?>[] collections = {
   
   new HashSet<String>(), new ArrayList<String>()};

    public static String getType(Collection<?> collection) {
   
   
        return "Super:collection";
    }
    public static String getType(List<?> list) {
   
   
        return "Super:list";
    }
    public String getType(ArrayList<?> list) {
   
   
        return "Super:arrayList";
    }
}

南哥给大家这么一行代码:Collection<?> collection = new ArrayList<Integer>()左边Collection<?>其实是静态类型,右边的new ArrayList<Integer>()其实是动态类型。

编译器在处理重载方法时,是根据参数的静态类型作为判断依据,而不是根据动态类型。collections数组里面的所有实例的静态类型都是Collection<?>getType方法也都是执行上文的第一个重载方法。

# 程序员执行结果
Super:collection
Super:collection

你学会(fei)了吗?

最后

在某网站上看到22届Java校招一片红海?24届今年的行情呢?

在这里插入图片描述

本文收录在我开源的《Java学习进阶指南》中,涵盖了在大厂工作的Javaer都不会不懂的核心知识、面试重点。相信能帮助到大家在Java成长路上不迷茫,南哥希望收到大家的 ⭐ Star ⭐支持我完善下去。GitHub地址:https://github.com/hdgaadd/JavaProGuide

在这里插入图片描述

欢迎关注南哥的公众号:Java进阶指南针。公众号里有南哥珍藏整理的大量优秀pdf书籍!

我是南哥,南就南在Get到你的有趣评论➕点赞➕关注。

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关文章
|
5天前
|
安全 前端开发 关系型数据库
深入理解后端开发:从基础到高级实践
本文将带你走进后端开发的奇妙世界,从最基础的概念开始,逐步深入到高级实践。无论你是初学者还是有一定经验的开发者,都能在这篇文章中找到有价值的信息。我们将一起探讨后端开发的核心概念、常用技术栈、以及如何在实际项目中应用这些知识。准备好了吗?让我们一起开启这场后端开发的探索之旅吧!
|
3天前
|
存储 JavaScript Java
深入浅出后端开发:从零到一的旅程
【9月更文挑战第10天】本文将带领读者走进后端开发的神秘世界,从基本概念到实战应用,一步步揭开后端技术的面纱。通过浅显易懂的语言和实际代码示例,我们将探索如何搭建一个简单的后端服务,理解数据库交互,并实现API的基本功能。无论你是编程新手还是希望扩展知识的开发者,这篇文章都将为你提供一条清晰的学习路径。
|
3天前
|
存储 前端开发 Java
探索后端开发:从新手到专家的旅程
在这篇文章中,我们将一起踏上一段奇妙的旅程,探索后端开发的奥秘。无论你是刚刚踏入编程世界的新手,还是已经在这条路上走了一段时间的开发者,这篇文章都将为你提供有价值的见解和建议。我们将从基础概念开始,逐步深入到高级主题,包括框架选择、数据库设计、API开发等。让我们一起开启这段旅程吧!
|
2天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第11天】本文将带你走进Node.js的世界,了解其背后的运行机制和实际应用。我们将从基础概念出发,逐步深入到实战应用,最后通过代码示例巩固学习成果。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供新的视角和思考。
|
3天前
|
JavaScript 关系型数据库 数据库
探索后端开发:从新手到专家的旅程
本文将带领读者踏上一场激动人心的旅程,从零基础开始,逐步深入后端开发的奥秘。我们将一起揭开后端世界的面纱,探索其核心概念、关键技术和实用工具。无论你是编程新手还是有一定经验的开发者,这篇文章都将为你提供宝贵的知识和启发,帮助你在后端开发的道路上更进一步。准备好迎接挑战,让我们启程吧!
23 8
|
3天前
|
前端开发 API 数据处理
探索后端开发中的API设计哲学
【9月更文挑战第10天】在数字化时代的浪潮下,后端开发作为连接数据与前端界面的桥梁,其重要性不言而喻。本文将深入探讨如何通过精心设计的API来提升后端服务的可维护性、扩展性和用户体验。我们将从API设计的基本原则出发,逐步展开对RESTful API和GraphQL两种流行风格的比较分析,并结合具体场景讨论最佳实践。文章旨在为开发者提供一套实用的API设计指南,助力打造高效、稳定且易于协作的软件架构。
16 6
|
3天前
|
关系型数据库 API 数据库
探索后端开发:从基础到进阶的实用指南
在数字化时代的浪潮中,后端开发作为支撑整个互联网世界的根基,其重要性不言而喻。本文旨在为初学者和有一定经验的开发者提供一个深入浅出的后端开发指南,涵盖从基础概念到高级实践的各个阶段。我们将一起探讨如何选择合适的编程语言,理解数据库的重要性,学习API的设计,以及掌握容器化部署等关键技能。无论你是初出茅庐的新手,还是希望提升自己技能的老手,这篇文章都将是你的宝贵财富。
|
4天前
|
JavaScript 测试技术 API
探索后端开发:构建高效API的艺术
【9月更文挑战第8天】本文旨在揭示后端开发中一个经常被忽视的领域——API设计。通过深入浅出的方式,我们将探讨如何构建一个既高效又易于维护的API。文章将涵盖设计原则、最佳实践以及一些常见的陷阱和解决方案。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用的技巧,帮助你在后端开发的道路上更进一步。
|
2天前
|
Java 关系型数据库 API
后端开发之道:从新手到专家的蜕变之旅
在数字化时代的浪潮中,后端开发如同一座桥梁,连接着数据世界的每一个角落。本文将带领读者踏上一段从零基础到精通后端开发的旅程,探索编程语言的选择、框架的应用、数据库的设计以及API的开发等关键知识点。我们将以通俗易懂的语言,结合条理清晰的结构,逐步揭开后端开发的神秘面纱,让每一位读者都能在这段旅途中找到属于自己的位置和方向。
|
2天前
|
缓存 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第11天】本文将带你进入Node.js的世界,探索其背后的哲学、核心概念以及如何利用它来构建高效、可扩展的后端服务。无论你是前端开发者寻求全栈技能,还是后端开发者希望拓宽技术栈,这篇文章都将为你提供价值。我们将从基础讲起,逐步深入到实战应用,让你对Node.js有一个全面而深刻的理解。
10 2