Java有类似C#的ref和out关键字吗?

像下面这样:

参考例子:

void changeString(ref String str) { str = "def"; } void main() { String abc = "abc"; changeString(ref abc); System.out.println(abc); //prints "def" } 

例如:

 void setString(out String str) { str = "def"; } void main() { String abc; changeString(out abc); System.out.println(abc); //prints "def" } 

不,Java没有类似于C#的refout关键字来传递引用。

您只能通过Java传递值。 即使引用是通过值传递。 有关更多详细信息,请参阅Jon Skeet有关Java中parameter passing的页面。

要做类似于refout事情out你必须把你的参数包装到另一个对象中,并把这个对象引用作为参数传入。

直接回答:不

但是你可以用包装器来模拟引用 。

并执行以下操作:

 void changeString( _<String> str ) { str.s("def"); } void testRef() { _<String> abc = new _<String>("abc"); changeString( abc ); out.println( abc ); // prints def } 

退房

 void setString( _<String> ref ) { str.s( "def" ); } void testOut(){ _<String> abc = _<String>(); setString( abc ); out.println(abc); // prints def } 

基本上任何其他types,如:

 _<Integer> one = new <Integer>(1); addOneTo( one ); out.println( one ); // May print 2 

Java通过值传递参数,并没有任何机制允许通过引用。 这意味着只要传递参数,它的值就被复制到处理调用的堆栈帧中。

我在这里使用的术语价值需要一点澄清。 在Java中,我们有两种variables – 基元和对象。 基元的值是基元本身,而对象的值是其引用(而不是被引用的对象的状态)。 因此,对方法内的值的任何改变将只改变堆栈中的值的副本,并且不会被调用者看到。 例如,没有办法实现一个真正的交换方法,接收两个引用并交换它们(而不是它们的内容!)。

像其他许多人一样,我需要将C#项目转换为Java。 我没有在网上find关于outref修饰符的完整解决scheme。 但是,我能够把我发现的信息,并扩大到创build自己的class级,以满足要求。 为了清晰起见,我想区分refout参数。 通过下面的课程,这是可能的。 愿这信息节省别人的时间和精力。

下面的代码中包含一个示例。

 //******************************************************************************************* //XOUT CLASS //******************************************************************************************* public class XOUT<T> { public XOBJ<T> Obj = null; public XOUT(T value) { Obj = new XOBJ<T>(value); } public XOUT() { Obj = new XOBJ<T>(); } public XOUT<T> Out() { return(this); } public XREF<T> Ref() { return(Obj.Ref()); } }; //******************************************************************************************* //XREF CLASS //******************************************************************************************* public class XREF<T> { public XOBJ<T> Obj = null; public XREF(T value) { Obj = new XOBJ<T>(value); } public XREF() { Obj = new XOBJ<T>(); } public XOUT<T> Out() { return(Obj.Out()); } public XREF<T> Ref() { return(this); } }; //******************************************************************************************* //XOBJ CLASS //******************************************************************************************* /** * * @author jsimms */ /* XOBJ is the base object that houses the value. XREF and XOUT are classes that internally use XOBJ. The classes XOBJ, XREF, and XOUT have methods that allow the object to be used as XREF or XOUT parameter; This is important, because objects of these types are interchangeable. See Method: XXX.Ref() XXX.Out() The below example shows how to use XOBJ, XREF, and XOUT; // // Reference parameter example // void AddToTotal(int a, XREF<Integer> Total) { Total.Obj.Value += a; } // // out parameter example // void Add(int a, int b, XOUT<Integer> ParmOut) { ParmOut.Obj.Value = a+b; } // // XOBJ example // int XObjTest() { XOBJ<Integer> Total = new XOBJ<>(0); Add(1, 2, Total.Out()); // Example of using out parameter AddToTotal(1,Total.Ref()); // Example of using ref parameter return(Total.Value); } */ public class XOBJ<T> { public T Value; public XOBJ() { } public XOBJ(T value) { this.Value = value; } // // Method: Ref() // Purpose: returns a Reference Parameter object using the XOBJ value // public XREF<T> Ref() { XREF<T> ref = new XREF<T>(); ref.Obj = this; return(ref); } // // Method: Out() // Purpose: returns an Out Parameter Object using the XOBJ value // public XOUT<T> Out() { XOUT<T> out = new XOUT<T>(); out.Obj = this; return(out); } // // Method get() // Purpose: returns the value // Note: Because this is combersome to edit in the code, // the Value object has been made public // public T get() { return Value; } // // Method get() // Purpose: sets the value // Note: Because this is combersome to edit in the code, // the Value object has been made public // public void set(T anotherValue) { Value = anotherValue; } @Override public String toString() { return Value.toString(); } @Override public boolean equals(Object obj) { return Value.equals(obj); } @Override public int hashCode() { return Value.hashCode(); } } 

事实上,据我所知, Java语言中既没有关键字也没有关键字。 不过,我只是将一个C#代码转换成了Java ,它使用参数,并会告诉我刚刚做了什么。 您应该将任何对象包装到包装类中,并传递包装对象实例中包装的值,如下所示:

一个简单的例子使用包装

这是包装类 ;

 public class Wrapper { public Object ref1; // use this as ref public Object ref2; // use this as out public Wrapper(Object ref1) { this.ref1 = ref1; } } 

这里是testing代码;

 public class Test { public static void main(String[] args) { String abc = "abc"; changeString(abc); System.out.println("Initial object: " + abc); //wont print "def" Wrapper w = new Wrapper(abc); changeStringWithWrapper(w); System.out.println("Updated object: " + w.ref1); System.out.println("Out object: " + w.ref2); } // This won't work public static void changeString(String str) { str = "def"; } // This will work public static void changeStringWithWrapper(Wrapper w) { w.ref1 = "def"; w.ref2 = "And this should be used as out!"; } } 

一个真实世界的例子

使用out参数的AC#.NET方法

这里有一个使用out关键字的C#.NET方法。

 public bool Contains(T value) { BinaryTreeNode<T> parent; return FindWithParent(value, out parent) != null; } private BinaryTreeNode<T> FindWithParent(T value, out BinaryTreeNode<T> parent) { BinaryTreeNode<T> current = _head; parent = null; while(current != null) { int result = current.CompareTo(value); if (result > 0) { parent = current; current = current.Left; } else if (result < 0) { parent = current; current = current.Right; } else { break; } } return current; } 

Java等同于使用out参数的C#代码

而这个方法的Java等价物在包装类的帮助下如下;

 public boolean contains(T value) { BinaryTreeNodeGeneration<T> result = findWithParent(value); return (result != null); } private BinaryTreeNodeGeneration<T> findWithParent(T value) { BinaryTreeNode<T> current = head; BinaryTreeNode<T> parent = null; BinaryTreeNodeGeneration<T> resultGeneration = new BinaryTreeNodeGeneration<T>(); resultGeneration.setParentNode(null); while(current != null) { int result = current.compareTo(value); if(result >0) { parent = current; current = current.left; } else if(result < 0) { parent = current; current = current.right; } else { break; } } resultGeneration.setChildNode(current); resultGeneration.setParentNode(parent); return resultGeneration; } 

包装类

此Java代码中使用的包装类如下所示;

 public class BinaryTreeNodeGeneration<TNode extends Comparable<TNode>> { private BinaryTreeNode<TNode> parentNode; private BinaryTreeNode<TNode> childNode; public BinaryTreeNodeGeneration() { this.parentNode = null; this.childNode = null; } public BinaryTreeNode<TNode> getParentNode() { return parentNode; } public void setParentNode(BinaryTreeNode<TNode> parentNode) { this.parentNode = parentNode; } public BinaryTreeNode<TNode> getChildNode() { return childNode; } public void setChildNode(BinaryTreeNode<TNode> childNode) { this.childNode = childNode; } }