前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【Java编程教程】详解Java 协变返回类型

【Java编程教程】详解Java 协变返回类型

作者头像
IT咸鱼
发布于 2025-05-20 10:30:48
发布于 2025-05-20 10:30:48
4702
代码可运行
举报
运行总次数:2
代码可运行

协变返回类型指定返回类型可以在与子类相同的方向上变化。

在 Java5 之前,不可能通过改变返回类型来覆盖任何方法。但是现在,从 Java5 开始,如果子类重写任何返回类型为 Non-Primitive 的方法,但它会将其返回类型更改为子类类型,则可以通过更改返回类型来重写方法。让我们举一个简单的例子:

注意:如果您是 Java 初学者,请跳在了解 OOP 概念后再返回阅读本篇教程。

# 协变返回类型的简单示例

文件名:B1.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A{    
A get(){return this;}    
}    

class B1 extends A{    
@Override  
B1 get(){return this;}    
void message(){System.out.println("欢迎使用协变返回类型");}    

public static void main(String args[]){    
new B1().get().message();    
}    
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
欢迎使用协变返回类型

上面的例子可以看到,A类的get()方法的返回类型是A,B类的get()方法的返回类型是B。两种方法返回类型不同,但都是方法重写. 这称为协变返回类型。关注公众号鸭哥聊Java,获取651页Java面试题

# 协变返回类型的优点

以下是协变返回类型的优点。

  1. 协变返回类型有助于避免类层次结构中令人困惑的类型转换,使代码更易用、可读和可维护。
  2. 在方法覆盖中,协变返回类型提供了拥有更多指向返回类型的自由。
  3. 协变返回类型有助于防止返回时的运行时ClassCastExceptions。

让我们举个例子来理解协变返回类型的优点。

文件名:CovariantExample.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A1  
{  
    A1 foo()  
{  
        return this;  
    }  

    void print()  
{  
        System.out.println("Inside the class A1");  
    }  
}  


// A2 是 A1 的子类  
class A2 extends A1  
{  
    @Override  
    A1 foo()  
{  
        return this;  
    }  

    void print()  
{  
        System.out.println("Inside the class A2");  
    }  
}  

// A3 是 A2 的子类  
class A3 extends A2  
{  
    @Override  
    A1 foo()  
{  
        return this;  
    }  

    @Override  
    void print()  
{  
        System.out.println("Inside the class A3");  
    }  
}  

public class CovariantExample  
{  
    // main方法  
    public static void main(String argvs[])  
{  
       A1 a1 = new A1();  

       //这样写是没问题的  
       a1.foo().print();  

       A2 a2 = new A2();  

       // 我们需要进行类型转换才能实现  
             // 读者更清楚创建的对象类型    
       ((A2)a2.foo()).print();  

       A3 a3 = new A3();  

       // 进行类型转换  
       ((A3)a3.foo()).print();  
    }  
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Inside the class A1
Inside the class A2
Inside the class A3

解释:在上面的程序中,A3类继承了A2类,A2类继承了A1类。因此,A1 是类 A2 和 A3 的父类。因此,类 A2 和 A3 的任何对象也是类型 A1。由于方法foo()的返回类型在每个类中都是相同的,我们不知道该方法实际返回的对象的确切类型。我们只能推断返回的对象将是 A1 类型,这是最通用的类。

我们不能确定返回的对象是 A2 还是 A3。这是我们需要进行类型转换以找出从方法foo()返回的对象的特定类型的地方. 它不仅使代码冗长;它还需要程序员的精确度,以确保正确完成类型转换;否则,很有可能获得ClassCastException。

更糟的是,想想层次结构下降到 10 - 15 个类甚至更多的情况,并且在每个类中,方法foo()具有相同的返回类型。这足以让代码的读者和编写者陷入噩梦。关注公众号Java面试那些事儿,获取651页Java面试题

写上面的更好的方法是:

文件名:CovariantExample.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class A1  
{  
    A1 foo()  
{  
        return this;  
    }  

    void print()  
{  
        System.out.println("Inside the class A1");  
    }  
}  

// A2 是 A1 的子类  
class A2 extends A1  
{  
    @Override  
    A2 foo()  
{  
        return this;  
    }  

    void print()  
{  
        System.out.println("Inside the class A2");  
    }  
}  

// A3 是 A2 的子类  
class A3 extends A2  
{  
    @Override  
    A3 foo()  
{  
        return this;  
    }  

    @Override  
    void print()  
{  
        System.out.println("Inside the class A3");  
    }  
}  

public class CovariantExample  
{  
    // main方法  
    public static void main(String argvs[])  
{  
       A1 a1 = new A1();  
       a1.foo().print();    
       A2 a2 = new A2();     
       a2.foo().print();  
       A3 a3 = new A3();  
       a3.foo().print();   
    }  
}

输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Inside the class A1
Inside the class A2
Inside the class A3
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT咸鱼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
sql初学笔记(10-17)语句
本文中,我们使用众所周知的 Northwind 样本数据库进行举例介绍。下面是选自 "Customers" 表的数据:
TRY博客-简单的网络技术
2022/07/18
2890
SQL DELETE 语句:删除表中记录的语法和示例,以及 SQL SELECT TOP、LIMIT、FETCH FIRST 或 ROWNUM 子句的使用
注意:在删除表中的记录时要小心!请注意DELETE语句中的WHERE子句。WHERE子句指定应删除哪些记录。如果省略WHERE子句,将会删除表中的所有记录!
小万哥
2023/11/21
2.8K0
SQL DELETE 语句:删除表中记录的语法和示例,以及 SQL SELECT TOP、LIMIT、FETCH FIRST 或 ROWNUM 子句的使用
深入理解 SQL UNION 运算符及其应用场景
以下SQL语句从“Customers”和“Suppliers”表中返回城市(仅不同的值):
小万哥
2023/11/28
5960
深入理解 SQL UNION 运算符及其应用场景
SQL 算术运算符:加法、减法、乘法、除法和取模的用法
存储过程是一段预先编写好的 SQL 代码,可以保存在数据库中以供反复使用。它允许将一系列 SQL 语句组合成一个逻辑单元,并为其分配一个名称,以便在需要时调用执行。存储过程可以接受参数,使其更加灵活和通用。
小万哥
2023/12/01
1.2K0
SQL 算术运算符:加法、减法、乘法、除法和取模的用法
SQL 通配符:用于模糊搜索和匹配的 SQL 关键技巧
通配符字符用于替代字符串中的一个或多个字符。通配符字符与LIKE运算符一起使用。LIKE运算符用于在WHERE子句中搜索列中的指定模式。
小万哥
2023/11/24
5050
SQL 通配符:用于模糊搜索和匹配的 SQL 关键技巧
SQL FULL OUTER JOIN 关键字:左右表中所有记录的全连接解析
SQL RIGHT JOIN关键字返回右表(table2)中的所有记录以及左表(table1)中的匹配记录。如果没有匹配,则左侧的结果为0条记录。
小万哥
2023/11/27
4500
SQL FULL OUTER JOIN 关键字:左右表中所有记录的全连接解析
select top语句 mysql_SQL SELECT TOP 语句[通俗易懂]
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/158565.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/14
2.6K0
SQL 中的运算符与别名:使用示例和语法详解
您还可以在WHERE子句中使用带有子查询的IN。使用子查询,您可以返回主查询结果中存在于子查询结果中的所有记录。
小万哥
2023/11/25
5110
SQL 中的运算符与别名:使用示例和语法详解
SQL LIKE 运算符:用法、示例和通配符解释
SQL中的LIKE运算符用于在WHERE子句中搜索列中的指定模式。通常与LIKE运算符一起使用的有两个通配符:
小万哥
2023/11/23
6710
SQL LIKE 运算符:用法、示例和通配符解释
SQL 数据操作技巧:SELECT INTO、INSERT INTO SELECT 和 CASE 语句详解
提示: SELECT INTO 还可以用于使用另一个表的架构创建新的空表。只需添加一个导致查询不返回数据的 WHERE 子句:
小万哥
2023/11/30
1.1K0
SQL 数据操作技巧:SELECT INTO、INSERT INTO SELECT 和 CASE 语句详解
SQL HAVING 子句详解:在 GROUP BY 中更灵活的条件筛选
以下SQL语句列出了每个国家的客户数量,按高到低排序(只包括拥有超过5名客户的国家):
小万哥
2023/11/29
7320
SQL HAVING 子句详解:在 GROUP BY 中更灵活的条件筛选
SQL JOIN 子句:合并多个表中相关行的完整指南
注意,“Orders”表中的“CustomerID”列是指“Customers”表中的“CustomerID”。上述两个表之间的关系是“CustomerID”列。
小万哥
2023/11/26
1.1K0
SQL JOIN 子句:合并多个表中相关行的完整指南
AngularJS 表格
v1.5 中$http 的 success 和 error 方法已废弃。使用 then 方法替代。
陈不成i
2021/07/23
1.9K0
肝通宵写了三万字把SQL数据库的所有命令,函数,运算符讲得明明白白讲解,内容实在丰富,建议收藏+三连好评!
大家可能不习惯SQL大写的习惯,但是真正的规范就是要大写,所以大家要慢慢习惯我用大写的方式讲解。在下面所有的讲解中,我将会以基本语法,案例,联系形式讲解,从而加强对每一个语句的使用和认识。本篇文章是笔者整理了整整一个通宵才写出,希望大家三连好评,谢谢。当然,拥有本篇文章,你将会完全掌握mysql的所有命令使用,不再用去购买或者杂乱学习。本篇内容暂时讲解数据库的筛选部分,因为数据库的最初入门如创建,备份等都有讲过,魔法传送:传送门 该传送门内容有:
全栈程序员站长
2022/08/10
10.3K0
肝通宵写了三万字把SQL数据库的所有命令,函数,运算符讲得明明白白讲解,内容实在丰富,建议收藏+三连好评!
软件测试|SQL中的null值,该如何理解?
Null值在SQL中是用于表示缺失或未知数据的特殊值。本文将深入探讨Null值的概念、处理方法和注意事项,以帮助读者更好地理解和处理SQL中的缺失数据。
霍格沃兹测试开发Muller老师
2023/09/07
4750
mysql 数据_MySQL和SQL
附带国内精确到市,国外的精确到省吧。 下载这里的:https://download.csdn.net/download/luolincsdn/10675557 有的下载都没用,想一想还是放出来比较好。 这是数据表:
全栈程序员站长
2022/11/11
11.6K0
推荐阅读
相关推荐
sql初学笔记(10-17)语句
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档