Java에서 참조로 매개 변수를 전달할 수 있습니까?


답변:


225

모든 것이 value에 의해 전달 되므로 Java는 혼란스러워 합니다 . 그러나 참조 유형 의 매개 변수 (즉, 기본 유형의 매개 변수가 아닌)의 경우 값으로 전달되는 참조 자체이므로 참조 로 전달되는 것처럼 보입니다 (그리고 사람들은 종종 그것을 주장합니다). 다음과 같이 그렇지 않습니다.

Object o = "Hello";
mutate(o)
System.out.println(o);

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

Hello콘솔에 인쇄 합니다. 위 코드를 인쇄하려면 옵션 은 다음과 같이 명시 적 참조Goodbye사용하는 것입니다.

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!

private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }

48
또한 사람들을 혼란스럽게 만들고 싶다면 길이가 1 인 배열을 사용하여 참조를 만들 수 있습니다. :)
Christoffer

2
AtomicReference와 해당 클래스 (AtomicInteger)는 이러한 작업에 가장 적합합니다
Naveen

3
AtomicReference는 과잉이므로 메모리 장벽이 필요하지 않으며 비용이 발생할 수 있습니다. JRuby는 오브젝트를 구성 할 때 사용되는 휘발성 변수로 인해 성능 문제가있었습니다. 배열을 애드혹 참조로 사용하는 옵션은 나에게 충분 해 보이며, 두 번 이상 사용 된 것을 보았습니다.
Elazar Leibovich

나는 이것이 혼란스럽지 않다고 생각하지만 이것은 정상적인 동작입니다. 값 유형은 스택에 존재하고 참조 유형은 힙에 존재하지만 참조 유형에 대한 참조는 스택에도 존재합니다. 따라서 항상 스택에있는 값으로 작동합니다. 나는 여기서 질문이 있다고 믿는다 : 스택에있는 다른 값을 가리키는 스택에서 참조를 전달하는 것이 가능합니까? 아니면 힙에있는 일부 값을 가리키는 다른 참조의 참조를 전달합니까?
eomeroff

이 좋은 정보입니다. 나는 배열을 사용했지만이 작업을 위해 만들어진 것으로 보입니다. 그러나 성능이 중요한 루프 인 경우이 어레이와 어레이의 성능을
모릅니다.

65

Java에서 참조로 매개 변수를 전달할 수 있습니까?

아니.

왜 ? Java에는 값으로 메소드에 인수를 전달하는 유일한 모드가 있습니다.

노트 :

프리미티브의 경우 이해하기 쉽습니다. 값의 사본을 얻습니다.

다른 모든 경우 참조의 사본을 얻습니다.이 값을 전달하는 것도 호출됩니다.

이 사진에 모두 있습니다.

여기에 이미지 설명을 입력하십시오


25

Java에는 언어 수준에 ref 와 비슷한 것이 없습니다 . Java에서는 값 의미 만 전달합니다.

호기심을 위해 객체를 가변 클래스로 래핑하여 Java에서 ref-like semantic을 구현할 수 있습니다.

public class Ref<T> {

    private T value;

    public Ref(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

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

테스트 케이스 :

public void changeRef(Ref<String> ref) {
    ref.set("bbb");
}

// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"

java.lang.ref.Reference를 대신 사용하지 않는 이유는 무엇입니까?
하드 코드 됨

java.lang.ref.Reference는 set 메소드를 가지고 있지 않으며 변경할 수 없다
dfa

왜 기본이 아닌 제품을 사용하지 AtomicReference않습니까? 또는 프리미티브의 경우 AtomicSomething(예 AtomicBoolean:)?
Arvin

불행히도 <T>는 기본 유형을 허용하지 않습니다. 이렇게 하시겠습니까 : Ref <int>
jk7

1
@ jk7 사용해야 할 정말 중요한면 충분 int대신 Integer, bool대신 Boolean등? 즉, 래퍼 클래스 (구문이 걱정되면 자동으로 줄 바꿈되지 않음)가 작동하지 않습니까?
Paul Stelian

18

"Java Programming Language"의 James Gosling에서 :

"... Java에는 정확히 하나의 매개 변수 전달 모드가 있으며 값을 기준으로 전달됩니다. 이는 단순하게 유지합니다 .."


2
언어 신의 선언은 답으로 선언되어야한다.
ingyhere

3
@ingyhere : The pronouncement of the language god should be declared the answer: 실제로는 아닙니다. Java 작성자가 생각하거나 믿는 바에도 불구하고 절대적인 대답은 언어 사양의 인용에서 비롯됩니다.
paercebal

1
실제로 그것은 인 섹션 8.4.1에서 JLS "방법 또는 생성자가 호출되면 (§15.12을) 및 JLS 먼저 작성자 슬링를 인용 실제 인수 식의 값은 새로 매개 변수 생성 initialize가 , 각 메소드 또는 생성자의 본문을 실행하기 전에 선언 된 유형
ingyhere

바로 그거죠. 담당자 수가 적은 Sarcasm은 도움이되지 않습니다.
duffymo

11

나는 당신이 할 수 있다고 생각하지 않습니다. 가장 좋은 방법은 다른 클래스 인스턴스에 "ref로"전달하려는 것을 캡슐화하고 (외부) 클래스의 참조를 값으로 전달하는 것입니다. 무슨 말인지 알면 ...

즉, 메소드는 전달 된 오브젝트의 내부 상태를 변경 한 다음 호출자에게 표시됩니다.


7

Java는 항상 가치에 의해 전달됩니다.

프리미티브를 전달하면 값의 사본이고 객체를 전달할 때 참조 포인터의 사본입니다.


4

다른 옵션은 배열을 사용하는 것입니다. 예를 들어 void method(SomeClass[] v) { v[0] = ...; } 1) 메소드를 호출하기 전에 배열을 초기화해야합니다 java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.