2016年12月02日 16:05:07 FXBStudy 阅读数:10045
 

前言:虽然对于这种需求不常用,且比较冷门,但是还是有其存在的价值,再次做一下整理。我们常用的return语句只允许返回单个对象,相对的解决办法就是创建一个对象,用它来持有想要返回的多个对象。

  实现这种功能,还要归功于Java1.5的新特性-泛型,我们利用泛型,可以一次性地解决该问题,以后再也不用在这个问题上浪费时间了,并且,我们可以再编译期就能够确保类型安全。

  你也许已经想到使用集合可以实现我们的需求,但是虽然一次可以返回多个值,但是其类型都是相同的,并不完全符合我们的需求。

  我们需要引入一个概念:元组(tuple),元组也称为数据传送对象或信使。元组是将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取其中元素,但是不允许向其中存放新的对象。

  通常,元组可以具有任意长度,同时元组中的对象可以是任意不同的类型。我们能够为每一个对象指明其类型,并且可以正确读取到数据,这就是元组可以提供的功能。我们要处理不同长度的问题,需要创建多个不同的元组。

首先我们创建一个2维元组:

  1.  
    //: net/mindview/util/TwoTuple.java(Java编程思想_代码_目录)
  2.  
    package net.mindview.util;
  3.  
     
  4.  
    public class TwoTuple<A, B> {
  5.  
    public final A first;
  6.  
    public final B second;
  7.  
    public TwoTuple(A a, B b) {
  8.  
    first = a;
  9.  
    second = b;
  10.  
    }
  11.  
    public String toString() {
  12.  
    return "(" + first + ", " + second + ")";
  13.  
    }
  14.  
    }

构造器捕获了要存储的对象,而toString()方法是一个便利函数,用来显示列表中的值。

注意:元组隐含地保持了其中元素的次序。

  阅读上面的代码,以及根据元组的定义,你一定会感到诧异,设计思路不是应该将first和second声明为private,然后生成这两个变量的get方法吗?
  以上是我们大多数人的思维,但是我们仔细分析上面的代码,可以发现完全符合我们的要求。首先我们可以读取first和second,并且因为使用了final声明,我们就无法在修改其值。我们对比这两种写法,很显然,上面给出的代码更加合理,更加简洁明了。

  还有另一种设计考虑,即你确实希望允许客户端程序员改变first或second所引用的对象。然而,采用上面的形式无疑是更安全的做法,这样的话,如果程序员想要使用具有不同元素的元组,就强制要求他们另外创建一个新的TwoTuple对象。

我们可以利用继承机制实现长度更长的元组:

  1.  
    //: net/mindview/util/ThreeTuple.java
  2.  
    package net.mindview.util;
  3.  
     
  4.  
    public class ThreeTuple<A,B,C> extends TwoTuple<A,B> {
  5.  
    public final C third;
  6.  
    public ThreeTuple(A a, B b, C c) {
  7.  
    super(a, b);
  8.  
    third = c;
  9.  
    }
  10.  
    public String toString() {
  11.  
    return "(" + first + ", " + second + ", " + third +")";
  12.  
    }
  13.  
    }
  1.  
    //: net/mindview/util/FourTuple.java
  2.  
    package net.mindview.util;
  3.  
     
  4.  
    public class FourTuple<A,B,C,D> extends ThreeTuple<A,B,C> {
  5.  
    public final D fourth;
  6.  
    public FourTuple(A a, B b, C c, D d) {
  7.  
    super(a, b, c);
  8.  
    fourth = d;
  9.  
    }
  10.  
    public String toString() {
  11.  
    return "(" + first + ", " + second + ", " +
  12.  
    third + ", " + fourth + ")";
  13.  
    }
  14.  
    }
  1.  
    //: net/mindview/util/FiveTuple.java
  2.  
    package net.mindview.util;
  3.  
     
  4.  
    public class FiveTuple<A,B,C,D,E>
  5.  
    extends FourTuple<A,B,C,D> {
  6.  
    public final E fifth;
  7.  
    public FiveTuple(A a, B b, C c, D d, E e) {
  8.  
    super(a, b, c, d);
  9.  
    fifth = e;
  10.  
    }
  11.  
    public String toString() {
  12.  
    return "(" + first + ", " + second + ", " +
  13.  
    third + ", " + fourth + ", " + fifth + ")";
  14.  
    }
  15.  
    }

为了使用元组,你只需定义一个长度适合的元组,将其作为方法的返回值,然后在return语句中创建该元组,并返回即可。

实例:

  1.  
    //: generics/TupleTest.java
  2.  
    import net.mindview.util.*;
  3.  
     
  4.  
    class Amphibian {
  5.  
    }
  6.  
    class Vehicle {
  7.  
    }
  8.  
     
  9.  
    public class TupleTest {
  10.  
    static TwoTuple<String, Integer> f() {
  11.  
    // Autoboxing converts the int to Integer:
  12.  
    return new TwoTuple<String, Integer>("hi", 47);
  13.  
    }
  14.  
    static ThreeTuple<Amphibian, String, Integer> g() {
  15.  
    return new ThreeTuple<Amphibian, String, Integer>(new Amphibian(), "hi",
  16.  
    47);
  17.  
    }
  18.  
    static FourTuple<Vehicle, Amphibian, String, Integer> h() {
  19.  
    return new FourTuple<Vehicle, Amphibian, String, Integer>(new Vehicle(),
  20.  
    new Amphibian(), "hi", 47);
  21.  
    }
  22.  
    static FiveTuple<Vehicle, Amphibian, String, Integer, Double> k() {
  23.  
    return new FiveTuple<Vehicle, Amphibian, String, Integer, Double>(
  24.  
    new Vehicle(), new Amphibian(), "hi", 47, 11.1);
  25.  
    }
  26.  
    public static void main(String[] args) {
  27.  
    TwoTuple<String, Integer> ttsi = f();
  28.  
    System.out.println(ttsi);
  29.  
    // ttsi.first = "there"; // Compile error: final
  30.  
    System.out.println(g());
  31.  
    System.out.println(h());
  32.  
    System.out.println(k());
  33.  
    }
  34.  
    }

输出结果:

  1.  
    (hi, 47)
  2.  
    (Amphibian@15db9742, hi, 47)
  3.  
    (Vehicle@6d06d69c, Amphibian@7852e922, hi, 47)
  4.  
    (Vehicle@4e25154f, Amphibian@70dea4e, hi, 47, 11.1)

  由于有了泛型,你可以很容易地创建元组,令其返回一组任意类型的对象。而你所要做的,只是编写表达式而已。

  通过ttsi.first = "there";语句的错误,我们可以看出,final声明确实能够保护public元素,在对象被构造出来之后,声明为final的元素便不能被再赋予其他值了。

参考资料:

  • 《Java编程思想》

Java 同时返回多个不同类型的方法的更多相关文章

  1. Java连载76-基础数据类型包装类型及其方法简介

    一.java中八种基本数据类型对应的包装类型 基本数据类型      包装类型 byte                    java.lang.Byte short                ...

  2. java将long数据转为int类型的方法

    二.调用intValue()方法 [java] long ll = 300000; int ii= new Long(ll).intValue(); 三.先把long转换成字符串String,然后在转 ...

  3. java反射三种获得类类型的方法

    public class Test { public static void main(String[] args) { Test t=new Test();//所有的类都是Class类的实例(类类型 ...

  4. Java中返回参数值的几种状态

    Java 中无参无返回值方法的使用 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 " welcome to imooc. & ...

  5. Java协变返回类型

    今天看到句话:“支持重写方法时返回协变类型”. 那么什么事协变类型?在网上找了找资料,大体上明白了. Java 5.0添加了对协变返回类型的支持,即子类覆盖(即重写)基类方法时,返回的类型可以是基类方 ...

  6. “全栈2019”Java第五十八章:多态中方法返回类型可以是子类类型

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  7. Java中返回值定义为int类型的 方法return 1返回的是int还是Integer&&finally中return问题

    在Java中返回值定义为int类型的 方法return 1:中返回的是Integer值,在返回的时候基本类型值1被封装为Integer类型. 定义一个Test类,在异常处理try中和finally中分 ...

  8. Java常见面试题02-方法重写和方法重载的区别?方法重载能改变返回值类型吗?

    方法重写和方法重载的区别?方法重载能改变返回值类型吗?       A:Override方法重写和Overload方法重载的区别? Overload是否可以改变返回值类型?可以 方法重写 •  子类中 ...

  9. java统一返回标准类型

    一.前言.背景 在如今前后端分离的时代,后端已经由传统的返回view视图转变为返回json数据,此json数据可能包括返回状态.数据.信息等......因为程序猿的习惯不同所以返回json数据的格式也 ...

随机推荐

  1. Android入门笔记

    Android项目的目录结构(Eclipse版) src:项目源代码文件夹 R.java:存放项目中所有资源文件的资源id,永远不要修改 Android.jar:Android的jar包,导入此包方可 ...

  2. C# 创建多级文件夹示例

    string str = ""; ; i < j; i++) { str = str + "\\新建文件夹" ; } System.IO.Director ...

  3. Linux服务器下Nginx与Apache共存

    解决思路: 将nginx作为代理服务器和web服务器使用,nginx监听80端口,Apache监听除80以外的端口,我这暂时使用8080端口. nginx.conf 位置:/etc/nginx/ngi ...

  4. [HDU5963]朋友

    [HDU5963]朋友 题目大意: 给定一棵\(n(n\le40000)\)个点的树,边权只能是\(0\)或\(1\).一局游戏开始时,会确定一个结点作为根.AB轮流操作.当一方操作时,他们需要先选择 ...

  5. 前端框架React Js入门教程【精】

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...

  6. makefile中的shell编程注意点

    参考:http://blog.csdn.net/wanglang3081/article/details/49423105 (1)Makefile本质上来讲也是shell脚本,即每条command都是 ...

  7. C#编程(七十五)----------C#使用指针

    原文链接: http://blog.csdn.net/shanyongxu/article/details/47321441 在C#中使用指针的语法 如果想在C#中使用指针,首先对项目进行过配置: 看 ...

  8. Neo4j(一)

    01-windows下载与安装neo4j https://blog.csdn.net/qq_21383435/article/details/78807024 neo4j的配置文件(图文详解) htt ...

  9. Visual Studio 2015 与 .NET 4.6 RTM 正式发布

    原文地址 微软终于正式发布了Visual Studio 2015产品家族的RTM版本,此次发布体现了微软在开发工具发展方向上的转变迈出了重要的一步,他们致力于提供一种支持在所有主流应用平台上进行应用开 ...

  10. 微软BI 之SSIS 系列 - 在 SSIS 中使用 Web Service 以及 XML 解析

    开篇介绍 Web Service 的用途非常广几乎无处不在,像各大门户网站上的天气预报使用到的第三方 Web Service API,像手机客户端和服务器端的交互等都可以通过事先设计好的 Web Se ...