Does Java have something like C#'s ref and out keywords?

后端 未结 7 1481
陌清茗
陌清茗 2020-11-27 03:31

Something like the following:

ref example:

void changeString(ref String str) {
    str = \"def\";
}

void main() {
    String abc = \"abc\";
    chan         


        
相关标签:
7条回答
  • 2020-11-27 03:49

    java has no standard way of doing it. Most swaps will be made on the list that is packaged in the class. but there is an unofficial way to do it:

    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);
        }
    }
    
    }
    
    0 讨论(0)
  • 2020-11-27 03:51

    No, Java doesn't have something like C#'s ref and out keywords for passing by reference.

    You can only pass by value in Java. Even references are passed by value. See Jon Skeet's page about parameter passing in Java for more details.

    To do something similar to ref or out you would have to wrap your parameters inside another object and pass that object reference in as a parameter.

    0 讨论(0)
  • 2020-11-27 03:55

    Java passes parameters by value and doesn't have any mechanism to allow pass-by-reference. That means that whenever a parameter is passed, its value is copied into the stack frame handling the call.

    The term value as I use it here needs a little clarification. In Java we have two kinds of variables - primitives and objects. A value of a primitive is the primitive itself, and the value of an object is its reference (and not the state of the object being referenced). Therefore, any change to the value inside the method will only change the copy of the value in the stack, and will not be seen by the caller. For example, there isn't any way to implement a real swap method, that receives two references and swaps them (not their content!).

    0 讨论(0)
  • 2020-11-27 03:56

    Direct answer: No

    But you can simulate reference with wrappers.

    And do the following:

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

    Out

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

    And basically any other type such as:

    _<Integer> one = new <Integer>(1);
    addOneTo( one );
    
    out.println( one ); // May print 2
    
    0 讨论(0)
  • 2020-11-27 04:00

    Like many others, I needed to convert a C# project to Java. I did not find a complete solution on the web regarding out and ref modifiers. But, I was able to take the information I found, and expand upon it to create my own classes to fulfill the requirements. I wanted to make a distinction between ref and out parameters for code clarity. With the below classes, it is possible. May this information save others time and effort.

    An example is included in the code below.

    //*******************************************************************************************
    //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();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 04:01

    Actually there is neither ref nor out keyword equivalent in Java language as far as I know. However I've just transformed a C# code into Java that uses out parameter and will advise what I've just done. You should wrap whatever object into a wrapper class and pass the values wrapped in wrapper object instance as follows;

    A Simple Example For Using Wrapper

    Here is the Wrapper Class;

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

    And here is the test code;

    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!";
        }
    
    }
    

    A Real World Example

    A C#.NET method using out parameter

    Here there is a C#.NET method that is using out keyword;

    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 Equivalent of the C# code that is using the out parameter

    And the Java equivalent of this method with the help of wrapper class is as follows;

    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;
    }
    

    Wrapper Class

    And the wrapper class used in this Java code is as below;

    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;
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题