如下所示:
ref example:
void changeString(ref String str) {
str = "def";
}
void main() {
String abc = "abc";
changeString(ref abc);
System.out.println(abc); //prints "def"
}
示例:
void changeString(out String str) {
str = "def";
}
void main() {
String abc;
changeString(out abc);
System.out.println(abc); //prints "def"
}
答案 0 :(得分:86)
不,Java没有像C#的ref
和out
关键字那样通过引用传递。
您只能通过Java传递值。甚至引用都是按值传递的。有关详细信息,请参阅Jon Skeet有关parameter passing in Java的页面。
要执行与ref
或out
类似的操作,您必须将参数包装在另一个对象中,并将该对象引用作为参数传递。
答案 1 :(得分:24)
直接回答:否
但你可以模拟reference with wrappers。
并执行以下操作:
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
}
基本上任何其他类型如:
_<Integer> one = new <Integer>(1);
addOneTo( one );
out.println( one ); // May print 2
答案 2 :(得分:7)
Java按值传递参数,并且没有任何允许传递引用的机制。这意味着无论何时传递参数,其值都会被复制到处理调用的堆栈帧中。
我在这里使用的术语值需要一点澄清。在Java中,我们有两种变量 - 基元和对象。基元的值是基元本身,对象的值是其引用(而不是被引用对象的状态)。因此,对方法内部值的任何更改都只会更改堆栈中值的副本,并且调用者不会看到它。例如,没有任何方法可以实现真正的交换方法,它接收两个引用并交换它们(而不是它们的内容!)。
答案 3 :(得分:6)
与许多其他人一样,我需要将C#项目转换为Java。我没有在网上找到关于 out 和 ref 修饰符的完整解决方案。但是,我能够获取我发现的信息,并扩展它以创建我自己的类来满足要求。为了清晰代码,我想区分 ref 和 out 参数。通过以下课程,这是可能的。愿这些信息能为他人节省时间和精力。
下面的代码中包含一个示例。
//*******************************************************************************************
//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();
}
}
答案 4 :(得分:6)
据我所知,实际上 Java 语言中没有 ref 或 out 关键字。但是,我刚刚将 C#代码转换为使用 out 参数的 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;
}
}
这是测试代码;
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!";
}
}
此处有 C#.NET 方法,该方法使用 out 关键字;
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 等价如下:
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;
}
}
答案 5 :(得分:1)
未正式提及的三种解决方案:
ArrayList<String> doThings() {
//
}
void doThings(ArrayList<String> list) {
//
}
Pair<String, String> doThings() {
//
}
对于结对,我建议:https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
答案 6 :(得分:-1)
java没有标准的方法。大多数交换将在该类包装的列表上进行。但是有一种非正式的方法:
package Example;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Test{
private static <T> void SetValue(T obj,T value){
try {
Field f = obj.getClass().getDeclaredField("value");
f.setAccessible(true);
f.set(obj,value);
} catch (IllegalAccessException | IllegalArgumentException |
NoSuchFieldException | SecurityException ex) {
Logger.getLogger(CautrucjavaCanBan.class.getName()).log(Level.SEVERE,
null, ex);
}
}
private static void permutation(Integer a,Integer b){
Integer tmp = new Integer(a);
SetValue(a, b);
SetValue(b, tmp);
}
private static void permutation(String a,String b){
char[] tmp = a.toCharArray();
SetValue(a, b.toCharArray());
SetValue(b, tmp);
}
public static void main(String[] args) {
{
Integer d = 9;
Integer e = 8;
HoanVi(d, e);
System.out.println(d+" "+ e);
}
{
String d = "tai nguyen";
String e = "Thai nguyen";
permutation(d, e);
System.out.println(d+" "+ e);
}
}
}