• Java 同时返回多个不同类型的方法


    Java 同时返回多个不同类型的方法

    前言:虽然对于这种需求不常用,且比较冷门,但是还是有其存在的价值,再次做一下整理。我们常用的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编程思想》
  • 相关阅读:
    Python基础语法 第2节课(数据类型转换、运算符、字符串)
    python基础语法 第5节课 ( if 、 for )
    python基础语法 第4节课 (字典 元组 集合)
    Python基础语法 第3节课 (列表)
    A. Peter and Snow Blower 解析(思維、幾何)
    C. Dima and Salad 解析(思維、DP)
    D. Serval and Rooted Tree (樹狀DP)
    C2. Balanced Removals (Harder) (幾何、思維)
    B. Two Fairs 解析(思維、DFS、組合)
    D. Bash and a Tough Math Puzzle 解析(線段樹、數論)
  • 原文地址:https://www.cnblogs.com/hfultrastrong/p/10018683.html
Copyright © 2020-2023  润新知