在我的编程教育中可能缺少这个理论,但在面向对象的语言中,是否有可能构建一个能够return
两个或更多个变量而不是一个变量的方法。
E.g。我非常喜欢Matlab
处理此问题的方法:[var1, var2] = myFunction(input);
如果我只需要var1
,我可以这样做:
[var1, ~] = myFunction(input);
因此丢弃我不需要的变量(在该特定情况下)。
由于我实际实现中的大量数据转换,我不想全局存储返回变量,只是一遍又一遍地调用相同的函数,但是接收该实例的指定(所需)值。
我想到了以下方法,但我想知道是否有更好的方法。
public static Double myFunction(Double input, Integer method)
{
double calcOne = input*5;
double calcTwo = input*25;
double calcThree = input*300;
switch(method)
{
case 1: return calcOne;
case 2: return calcTwo;
case 3: return calcThree;
default: return calcOne;
}
}
请注意,我显然需要return
语句和计算之间的分离(实际程序中的计算涉及大for loop
和读取文件等。)
我之所以不使用3种不同的方法,是因为我在方法中使用了非常大的for loop
。我的主要方法有时需要一个return
变量来自这个方法,有时需要两个。
因此,以下可能是一个(更好的)解决方案:
public static ArrayList<Double> myFunction(double input, int[] method)
{
double calcOne = input*5;
double calcTwo = input*25;
ArrayList<Double> returnValues = new ArrayList<Double>();
if (Arrays.asList(method).contains(1))
{
returnValues.add(calcOne);
}
if (Arrays.asList(method).contains(2))
{
returnValues.add(calcTwo);
}
return returnValues;
}
其中int[] method
包含变量&#39;名称&#39;该函数应该返回。
答案 0 :(得分:2)
据我所知,不可能在一个return语句中返回多个变量。 但是,您可以定义一个调用:
public ClassA {
public String var1;
public int var2;
public char var3;
public Long var4;
}
然后填充对象并返回它。在对象内部,您可以根据需要存储尽可能多的变量,并通过一个对象返回所有变量。
答案 1 :(得分:2)
是的,这是可能的。排序。
在Java中,您可以通过返回一个对象数组,或者通过创建并返回一个轻量级类的实例来实现它,该类具有保存要返回的多个值的字段。然后调用者必须从数组或对象中提取值。
在其他OO(和非OO)语言中,有更多的直接支持;例如在某些语言(Python,Ruby,Perl等)中,您可以执行以下操作:
[a, b, c] = someMethodReturningATuple()
LHS上的语法将值分配给变量a
,b
和c
。
Java不支持这一点,但部分原因是它没有内置的元组类型或“任何类型的数组”类型。如果没有其中任何一个,就很难将这种语言用于语言。 (并且假设的“任何类型的数组”类型可能不会削减,因为这将依赖于调用者端的动态类型。)
请注意,这与OO与非OO无关,甚至与静态类型与动态类型语言无关。 (我在1980年代首次使用Mesa语言进行多重回归.Mesa是静态类型的。)它更多地与语言设计者认为需要支持的语言特征集相关。
答案 2 :(得分:2)
在Java中,return
函数只能返回一个Object。返回多个值的备用方法(除全局变量外)如下:
使用数组
Object [] myarray = new Object [length];
由于Object
是您可能想要存储的大多数变量的超类,因此对象数组可以是返回多个值并仅使用您需要的值的好方法。
使用此数组的一个缺点是它存储对象而不是更具体的数据类型(例如String
),它具有自己的特殊操作集。这需要进行类型转换或其他转换才能使用特定的String
操作。
如果所有返回值都是相同的数据类型,则创建该单一数据类型的数组并避免此限制要容易得多:
String [] mystrings = new String [length];
List
此选项与数组非常相似,但列表具有一些额外的灵活性。列表创建如下:
List<Object> mylist = new LinkedList<Object>();
添加如下项目:
mylist.add(myVar);
与数组类似,如果所有数据值都属于同一类型,则此方法可避免上述限制。
您可以声明具有多个参数的类。这些参数具有特定的数据类型,因此它们可以将所有内置Java库用于其数据类型,而无需进行类型转换或转换。这避免了Array
或List
对象的主要缺点。
public ReturnObject () {
public int param1;
public String myString;
}
由于所有这些选项都有效,因为它们返回单个Object,但在该对象中返回了几个数据值。
答案 3 :(得分:2)
我一直在使用一种非常基本的方法来处理多重回报的问题。它有助于实现目的,并避免复杂性。
我称之为字符串分隔符方法
它有效,因为它甚至可以返回多种类型的值,例如int,double,char,string等
在这种方法中,我们使用一般不太可能发生的字符串。 我们将其称为分隔符。 当在函数
中使用时,此分隔符将用于分隔各种值例如,我们将最终返回为(例如)intValue separator doubleValue separator ... 然后使用这个字符串,我们将检索所需的所有信息,也可以是不同的类型
以下代码将显示此概念的工作原理
使用的分隔符是!@#和 返回3个值intVal,doubleVal和stringVal
public class TestMultipleReturns {
public static String multipleVals() {
String result = "";
String separator = "!@#";
int intVal = 5;
// Code to process intVal
double doubleVal = 3.14;
// Code to process doubleVal
String stringVal = "hello";
// Code to process Int intVal
result = intVal + separator + doubleVal + separator + stringVal + separator;
return (result);
}
public static void main(String[] args) {
String res = multipleVals();
int intVal = Integer.parseInt(res.split("!@#")[0]);
// Code to process intVal
double doubleVal = Double.parseDouble(res.split("!@#")[1]);
// Code to process doubleVal
String stringVal = res.split("!@#")[2];
System.out.println(intVal+"\n"+doubleVal+"\n"+stringVal);
}
}
输出
5
3.14
hello
BUILD SUCCESSFUL (total time: 2 seconds)
答案 4 :(得分:1)
E.g. I really like Matlab's way of handling this: [var1, var2] = myFunction(input);
请永远不要考虑&#34; Matlab&#34;编程语言:P
您正在寻找的等价物将是:
List<Double> result = doSomething(5);
System.out.println(result.get(0)); // 25
public List<Double> doStomething(Integer input){
List<Double> result= new LinkedList<Double>();
Double calcOne = input*5;
Double calcTwo = input*25;
result.add(calcOne);
result.add(calcTwo);
return result;
}
然而,即使您只是想使用&#34;所有值都是计算的,第一个结果&#34;。如果您只需要一个结果 - 创建3个方法并调用,您需要的内容,如:
public Double calcOne(Integer input){
...
}
public Double calcTwo(Integer input){
...
}
public Double calcThree(Integer input){
...
}
答案 5 :(得分:1)
另一个想法是创建一个使用&#34; hashmap&#34;的类。用于存储参数值的类型。这个类公开方法,例如添加参数和值,查找参数值,删除参数,获取参数个数等。重要的是隐藏使用数据类型来存储信息。如果您想要更改&#34; hashmap&#34;通过其他方式输入,当您不更改班级的公共界面时,班级的客户不会受到影响
的为例强> 的
public class Context {
private HashMap<String, Object> attributes = new HashMap<String, Object>();
// Get value for parameter name
public Object getAttribute(String name) {
return attributes.get(name);
}
// Set value for parameter name
public void setAttributes(String name, Object value) {
removeAttributes(name);
attributes.put(name, value);
}
// Returns the number of values
public int getSize() {
return this.attributes.size();
}
// remove parameter
public void removeAttributes(String name) {
Iterator<Map.Entry<String, Object>> iter = this.attributes.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Object> entry = iter.next();
if (name.equalsIgnoreCase(entry.getKey())) {
iter.remove();
}
}
}
}
此解决方案的缺点是您必须转换(强制转换)对象以获取原始值。如果你只有一种类型的数据也不是那么糟糕。通过利弊,如果你想存储几种不同的类型,它可能会变得复杂。但是,这是一个想法!!!!
@Test
public void testContext() {
// Le context
Context context = new Context();
Integer param1 = new Integer(1);
BigDecimal param2 = new BigDecimal(19700101);
String param3 = new String("hello world");
// Add 3 parameters (key, value)
context.setAttributes("param_1", param1);
context.setAttributes("param_2", param2);
context.setAttributes("param_3", param3);
Assert.assertEquals(3, context.getSize()); // test the number of key-value mappings in this map.
Integer resultParam1 = (Integer) context.getAttribute("param_1");
BigDecimal resultParam2 = (BigDecimal) context.getAttribute("param_2");
String resultParam3 = (String) context.getAttribute("param_3");
Assert.assertEquals(param1, resultParam1);
Assert.assertEquals(param2, resultParam2);
Assert.assertEquals(param3, resultParam3);
// remove parameter
context.removeAttributes("param_1");
Assert.assertEquals(2, context.getSize()); // 3add - 1remove = 2 parameters
// Replace value parameter by another value
Long value = new Long(1976);
context.setAttributes("param_2", value);
// and so on ...
}