2009-12-17 3 views
3

Java는 "값으로 전달"만 지원합니다. 예를 들어 콜렉션을 함수에 전달하면 해시 테이블을 함수에 전달하면이 함수 외부에서이 컬렉션에 대한 수정 사항을이 함수 외부에서 업데이트하면 안됩니다. 그러나 이것은 자바 사건? 우리가 어떻게 결론을 내릴 수 있니? 방법에 값으로 객체를 전달Java Pass by value 문제가 있습니까?

사람이 증명이 토론을 체결하시기 바랍니다 ...

+3

은 불변의 컬렉션 (및 구성 요소)입니다 도움이 될 것입니다

__________ | | | | | Orignal |<------------- Orignal Refernce | Object | | | |__________| __________ | | | | | Method |<------------- Method Refernce | Object | | | |__________| 

희망. 자동으로 스레드로부터 안전합니다. Collections.unmodifiableList는 좋은 첫 번째 단계입니다. – Thilo

+0

예제를 추가했습니다. – uriDium

답변

8

방법은 객체에 대한 참조의 사본을 제공하는 것을 의미하지만,이 액세스 할 수 여전히 가능 전달 된 참조 복사본 내에서 개체 멤버. 컬렉션의 경우에는 객체 추가 및 제거 방법을 호출하고 포함 된 객체 자체를 수정하는 과정이 포함됩니다.

2

"값으로 전달"- 프리미티브 변수의 경우 변수 값이 함수에 복사됩니다. 해시 테이블의 경우 true 인 객체 참조의 경우 참조 내의 값은 힙의 객체에 대한 주소 이외의 값으로 전달됩니다. 따라서 "해시 테이블"을 전달하는 함수에서 참조는 실제로 해시 테이블 객체의 주소 사본을 얻는 것입니다. 따라서 함수에서 변경 한 내용은 주 개체에 반영됩니다.

-1

다음은 훌륭한 예입니다. http://javadude.com/articles/passbyvalue.htm

여기 내 간단한 문제입니다. Java는 항상 가치에 의한 언어입니다. 객체에 대해 이야기 할 때 참조 언어로 간주하는 것이 도움이됩니다. 그러나 이것은 전적으로 사실이 아닙니다. 그것이하는 일은 메모리 주소의 값을 전달하는 것입니다.

편집 : 아래 표를 보내 주셔서 감사합니다. 어쩌면 먼저 기사를 읽었어야합니다. 누구도 자유를 가져서 아무에게도주지 않으려 고하기 때문에 :

public class Dog { 

    public String name; 

    public Dog(String name) { 
     this.name = name; 
    } 

    public static void main(String []args) { 

     Dog newDog = new Dog("Max"); 
     newDog.test(newDog); 
     System.out.println(newDog.name); 

    } 

    public void test(Dog dog) { 
     dog = new Dog("Gotcha"); 
    } 

} 

그래서 콘솔로 출력되는 내용은 무엇입니까? 이제 여러분이 pass-by-reference로 비명을 지르면 "Gotcha"가 인쇄되지만 "Max"는 인쇄되지 않습니다. 그러나 잠깐, 그건 정확히 가치에 의한 행동과 같습니다. 하지만 왜? 왜냐하면 Java 객체는 참조로 전달되지 않기 때문입니다. 올바른 진술은 객체 참조가 값에 의해 전달된다는 것입니다.

+0

안녕하세요 uriDium, ur 의견을 보내 주셔서 감사합니다 ...하지만 혼란 스럽습니다. 다른 모든 답변이 동기화되어 있는지 확인하십시오. 그러나 urs는 매우 다르고 혼란 스럽습니다. 분명히 설명해 주시겠습니까? – Sidharth

+2

당신의 설명은 당신의 주장의 반대를 묘사합니다, 당신이 실제로 참고로 전달하는 객체의 주소를 전달할 때 – Eli

+0

@ 엘리 - 예제를 추가했습니다. – uriDium

3

개체에 대해 "값으로 전달"동작을 사용하려면 메서드 clone을 전달하면되므로 메서드가 전달 된 개체를 변경하더라도 원본 개체는 수정되지 않은 상태로 유지됩니다.

+3

또는 Collections.unmodifiableList와 같은 Collections.unmodifiable * 메소드를 사용하십시오. http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html –

+0

을 참조하십시오. 그러나 두 경우 모두 구성 요소 객체는 여전히 참조로 전달되므로 수정할 수 있습니다. – Thilo

+1

사실, 솔루션은 복제품으로 구성 요소를 채우는 것입니다. – Sylar

4

"가치"의 의미를 혼란스럽게합니다. 객체를 다루는 경우 이는 참조의 의 변경 사항이 외부에 반영되지 않음을 의미합니다.

public void foo() { 
    String s = "example"; 
    String param = s; 
    bar(param); 
    assert s == param : "The value of parameter reference was not modified"; 
    assert param.equals("example"); 
} 

public void bar(String param) { 
    param = "something different"; 
} 

은, 그러나, 당신은 객체의 내부 상태를 변경할 수 없습니다 것을 의미하지 않는다 값에 의한 전달 :이 동작을 표시하는 간단한 예는 다음과 같이 될 것입니다. 이 완벽하게 가능하며 외부로 결과가 : 물론

public void foo() { 
    List<String> l = Arrays.asList("example"); 
    List<String> param = l; 
    bar(param); 
    assert s == param : "The value of parameter reference was not modified"; 
    assert !param.get(0).equals("example") : "bar changed the internal state of the parameter"; 
    assert !l.get(0).equals("example") : "bar changed the internal state of the list that is reference equal to the parameter"; 
} 

public void bar(List<String> param) { 
    param.set(0, "something different"); 
} 

는 객체의 내부 상태의 이러한 변화는 예상치 못한 부작용을 초래할 수있는 호출 스택에있는 모든 방법을 최대 반영됩니다. 이것이 immutable object pattern이 도입 된 이유입니다. Java 표준 라이브러리에서 java.lang.Objectjava.lang.String은이 패턴을 구현하는 클래스의 예입니다.그러나 자바는 클래스가이 패턴을 구현한다고 말할 수있는 곳에서 언어 기능을 제공하지 않으므로 객체가 변경되지 않도록 JavaDoc 및/또는 클래스의 소스 코드에 의존해야합니다.

-1

이 토론의 요점은 무엇입니까? 당신이

1

자바에서는이 객체를 통과하지 틸로의 의견과 먹으 렴에 따라 juz 다른 방법으로 전달하여 인수를 보호 싶다면

, 당신은 단지 객체에 대한 참조/포인터를 전달합니다. 그래서 전화

Object x = new Object(); 
int y = 42; 

foo(x,y) 

x의 값, Y의 (참조) 개체, 전달 즉,뿐만 아니라 값 "참조로 패스"정수 (42)에 당신이 할 수있는 것을 의미 foo()를 사용하여 x와 y 변수의 값을 변경하십시오.

1

전체 사진 : 당신이 변수 값에 의해 전달되는, 즉, 변경되지 않는 main의 변수를 볼 수

public static void main(String[] args) { 
    int i = 1; 
    addOne(i); 
    System.out.println("after addOne: " + i); 

    // now for Objects 
    String text = "a text"; 
    addText(text); 
    System.out.println("after addText: " + text); 
} 


private static void addOne(int i) { 
    i += 1; 
    System.out.println("in addOne: " + i); 
} 

private static void addText(String text) { 
    text += ", more text"; 
    System.out.println("in addText: " + text); 
} 

in addOne: 2 
after addOne: 1 
in addText: a text, more text 
after addText: a text 

발생한다 .

+0

왜 downvote? 별로 코멘트없이 downvoting ... –

0

Java는 값으로 전달됩니다하지만 객체 참조를 전달할 때 참조 값은 메소드로 전달되고 거기에서 메소드는 객체 구성원의 값을 변경할 수 있습니다.

개 고양이

출력 코드를

공용 클래스 Passbyvalue {

public static void main(String[] args) { 
    // TODO code application logic here 
    Animal animal=new Animal(); 
    animal.name="Dog"; 
    System.out.println(animal.name); 
    testIt(animal); 
    System.out.println(animal.name); 
} 


public static void testIt(Animal animal){ 
    animal.name="Cat"; 
} 

을} 다음에

봐는

이 때문에 두 참조 (원본 및 방법) 같은 대상에 poiting.

__________ 
    |   |     
    |   |<------------- Orignal Refernce 
    | Object | 
    |   |<------------- Method Refernce 
    |   | 
    |__________| 

당신은

공용 클래스 Passbyvalue {

public static void main(String[] args) { 
    Animal animal=new Animal(); 
    animal.name="Dog"; 
    System.out.println(animal.name); 
    testIt(animal); 
    System.out.println(animal.name); 
} 


public static void testIt(Animal animal){ 
    animal=new Animal(); 
    animal.name="Cat"; 
} 

}

출력 개 개

을 더 명확하게이 효과를 볼 방법에 새로운 객체를 만들려면 이제 메소드 참조 i 힙의 다른 Object 에의 poting. 이 당신이 원하는 무엇

관련 문제