[英]When you need pass by reference in Java to assign values to multiple parameters, how do you do it?
為了將一些方法重構為較小的方法,我需要通過引用傳遞,因為我只能有一個返回類型。 每當我需要這樣做時,我都可以創建一個不同的返回或參數類型,但后來我最終得到了一堆臃腫的,看似不必要的類。
除了重新設計程序之外,這里最好的選擇是什么呢?
編輯:其中一些可以重新設計,這就是我正在做的事情,但是,例如,它在一個點上找到一個巨大的集合中的最小和第二最小值,然后操縱它們。 我想把它分成兩個方法 - 一個發現,另一個操縱 - 但我似乎不太可能干凈地做到這一點。
您正在談論通過所謂的out參數“返回”多個值,就像您有時在C中找到的那樣,它們是通過引用傳遞的?
你想要一個返回單個值類的替代方法,但這確實是正確的。
但是,既然你問,是的,你是正確的,你需要更多的工作來獲得Java中的pass-by-reference語義。 Java總是按值傳遞(是的,我的意思是 - 它是傳遞給方法的對象引用 ,並且它們是通過值傳遞的)。 因此,如果你想以這種方式傳回一個新的引用,你可以做一些像傳遞一個Object的數組,並更改它包含的引用。
但是,我稱之為高度非常規,並不會推薦它。 通過重構獲得的任何改進都會被破壞。
我需要通過引用傳遞
嚴格來說,Java沒有通過引用傳遞。 Java中只有一種傳遞機制,它是通過值傳遞的。
在對象的情況下,傳遞的東西不是生成在堆上的對象本身。 它是對值傳遞的對象的引用。
這可能聽起來像一個挑剔,但它是一個重要的。
我不知道這與重構有什么關系。 如果您需要創建新類型以便返回,請務必執行此操作。 我敢打賭,你真的沒有反映手頭問題的對象模型,這就是你有這個重構問題的原因。
對我來說聽起來不太面向對象,特別是在閱讀你的編輯之后。
你可以做一些事情,比如創建一個可以處理函數值的泛型類。
private static class OutValue<T> {
public T value;
static <X> OutValue<X> makeOutValue(X value) {
OutValue<X> outValue = new OutValue<X>();
outValue.value = value;
return outValue;
}
}
下面是一個如何使用類從函數中獲取整數的示例。
void getInteger(OutValue<Integer> x)
{
x.value = 1;
}
OutValue<Integer> outValue = OutValue.makeOutValue(0);
getInteger(outValue);
System.out.println("value = " + outValue.value);
它可能不是最優雅的整體解決方案,但如果你不想做一個更復雜的重構,它將使你不必編寫大量的類。
一堆臃腫,看似不必要的課程。
嗯,要么數據屬於一個,這就是為什么你決定從單一方法返回它們,或者他們沒有。 如果他們這樣做,是不是新班級合適? 作為最后一個溝,你可以返回一個Vector。
或者如果你總是有一個有限數量的返回項,你可以使用像Pair<T1,T2>
(或定義一些這樣的通用元組類型)
將變量提升為實例變量,這兩種方法都可以看到它們(畢竟你可以在對象中擁有狀態)。 如果他們看起來不應該屬於你的對象,那么我認為你無法繞過重新設計。
因為在一個方法中,對象引用的參數是按值傳遞的,所以你不能按照以下方式做一些事情:
import java.awt.Point;
public class Example {
public static void main(String args[]) {
Point pnt1 = new Point(0, 0);
Point pnt2 = new Point(0, 0);
System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
System.out.println(" ");
sillyMethod(pnt1, pnt2);
System.out.println("X: " + pnt1.x + " Y: " + pnt1.y);
System.out.println("X: " + pnt2.x + " Y: " + pnt2.y);
}
public static void sillyMethod(Point arg1, Point arg2) {
arg1.x = 100;
arg1.y = 100;
arg2.x = 200;
arg2.y = 200;
}
}
這樣,您將更改對象的值,而不返回分歧類型。
沒有更多細節,很難給出具體的建議。 但可能性包括:
將相關函數放入單個類中並生成數據成員變量。 喜歡把你的“發現和微小的兩個最小”:
class ManipulateLeast2
{
List<int> list;
int firstSmallest;
int secondSmallest;
public ManipulateLeast2(List<int> list)
{
this.list=list;
}
public void findTwoSmallest()
{
.. scan list and populate firstSmallest and secondSmallest ...
}
public void processTwoSmallest()
{
... process firstSmallest and secondSmallest and do whatever ...
}
}
如果這很尷尬,另一種可能性就是創建一個類來保存你需要的值並返回它。 喜歡:
public class Smallest
{
int first;
int second;
public Smallest(int first, int second)
{
this.first=first;
this.second=second;
}
}
...
public Smallest findSmallest(List list)
{
... find two smallest and put in first and second ...
// Create the object and return it
return new Smallest(first, second);
}
我認為這比偽造傳遞參考要好得多。 但如果你真的堅持,可以通過將值放在包裝器中來完成,如下所示:
public StringWrapper
{
public String s;
}
...
// callee
void getTwoStrings(StringWrapper sw1, StringWrapper sw2)
{
sw1.s="Hello";
sw2.s="Goodbye";
}
// caller
StringWrapper sw1=new StringWrapper();
StringWrapper sw2=new StringWrapper();
getTwoStrings(sw1, sw2);
System.out.println("First is "+sw1.s);
System.out.println("Second is "+sw2.s);
為了使其清潔,您需要為每個類單獨包裝。 我想你可以制作一個ObjectWrapper來使它成為通用的,然后再投射東西,但這變得非常混亂。
我認為你最好考慮一下你的數據如何相關並將其轉化為邏輯類。
僅僅因為一個方法只能有一個返回類型並不意味着該類型不能包含多個信息。 您似乎遇到的問題類型的解決方案是聲明包含多條信息的數據類型。
按照問題中的示例(“在一個巨大的集合中找到最小值和第二個最小值,然后操縱它們”):
public class MinimumHolder {
private int min;
private int secondMin;
public MinimumHolder(int min, int secondMin) {
this.min = min;
this.secondMin = secondMin;
}
//getters...
}
public MinimumHolder findTwoMinimums(Set<Integer> numbers) {
// ...
return new MinimumHolder(...);
}
public MinimumHolder manipulateData(MinimumHolder mins) {
// do stuff with the data, this method could also be
// declared as void if MinimumHolder was mutable
}
您還可以非常輕松地重構MinimumHolder
以便它可以保存一個“最小值”的變量列表,如果您想要找到兩個以上的最小值,則使用getMinimum(int position)
公開。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.