2012-11-18 4 views
2

Java의 클래스 및 생성자에 대해 배우고 있습니다. 나는 예제 프로그램에서 코드를 둘러보고 정확히 무슨 일이 일어나는지 알 수 없다.Java 생성자의 최종 매개 변수

이 코드는 나에게 의미가있는 컴파일되지 않습니다 :

class Line { 
Point start; 
Point end; 

Line(final Point start, final Point end) { 

    this.start = new Point(start); 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

}... 

나는 Point 객체의 생성자를 호출하여 또 다른 포인트 객체에 대한 원래의 시작 지점 개체 참조를 할당 할 노력하고있어. 최종 키워드가이 키워드와 충돌합니다. 나는 포인트의 시작 매개 변수에서 최종 키워드를 ... 제거 할 때

그러나

class Line { 
Point start; 
Point end; 

Line(Point start, final Point end) { 

    this.start = new Point(start); 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

} 

실제로 참조, 라인 생성자에 전달되는 포인트 객체를 변경하지 않는 것은 여전히 ​​보인다 원래 객체를 가리키고 Line 생성자의 코드에 의해 바뀌지 않습니다. 그래서 무엇을 제공합니까? 이것은 'start'가 Line 생성자의 범위에서 로컬이라는 사실과 관련이 있습니까?

+0

생성자에 수정자가 없습니다. –

답변

0

실제로 참조

당신은 그 방법 자체 내부의 메소드를 호출하는 데 사용하는 매개 변수의 참조를 변경할 수를 변경하지 않는 것 같습니다. 매개 변수의 값 (객체에 대한 참조)은 method 매개 변수에 복사되므로 동일한 객체에 대한 두 번째 참조가 있습니다. 메서드 내에서 두 번째 참조 만 수정할 수 있으며 원래 참조를 변경할 수 없습니다. 당신이 할 수있는 유일한 방법은 참조 된 객체를 수정하는 것입니다.

5

Java는 참조 전달을 사용하지 않으며, 항상 값별 전달을 사용합니다. 실제로 Java에서 참조 유형은 포인터 일 뿐이며 C#의 References와 동일한 의미를 공유하지 않습니다. 당신이 당신의 생성자에서이 문을 수행 할 때

그래서 :

start = new Point(0.4, 0.4); 

인수의 원래 Point 통과는 변경되지 않습니다. 그러나 지역 변수 (매개 변수를 의미 함)는 Point 좌표로 정의 된 0,4, 0,4을 가리 킵니다. 변수는 생성자에 로컬 Java is Pass-by-Value, Dammit!

+0

내가 읽은 책에서 - "메서드에 인수로 객체를 전달하면 해당 메커니즘이 변수에 포함 된 참조 사본이 메서드로 전달되므로 참조로 전달이라고합니다. 객체 자체의 복제본이 아닙니다. " –

+0

@ user1817031 "참조"단어는 Java 세계에서 큰 명칭입니다. 변수는 인스턴스 자체를 포함하지 않고 인스턴스에 "점"을 포함하기 때문에 참조라는 용어가 사용됩니다. 왜 자바 제작자는이 "포인터"를 그렇게 부르지 않았습니까? 왜냐하면 포인터의 메모리는 C에서 특히 조작 될 수 있습니다 (이 "역 참조"라고 함). 자바에서 "포인터"(참조 ...)는 조작 된 메모리가 할당 된 것을 볼 수 없습니다. 당신이 직접 말했습니다 : "변수에 포함 된 참조의 COPY가 메서드로 전달되므로"=> 값만큼 전달됩니다;) – Mik378

0

그건 :

더 나은 이해를 위해,이 기사를 읽어 보시기 바랍니다. 따라서 새로운 참조를 생성자 외부에 존재하지 않기 때문에 생성자 외부에서 의미가 없습니다.

그런 효과를 얻는 한 가지 방법은 다른 개체로 마무리하는 것입니다. 그리고 변경 가능한 래퍼에 대한 참조를 전달하십시오.

0

"start = new Point (0.4, 0.4);"를 수행하면 생성자에서 수신 된 시작을 참조하게됩니다. 생성자가이를 최종 변수로 정의하므로 변수에 새 값을 할당하는 것은 불법입니다.

세부 사항은 Java가 패스 - 바이 - 값 방식을 사용하기 때문에 final을 사용하지 않고 생성자 내부의 값을 변경하더라도 원래 값의 값 (매개 변수로 방법)은 여전히 ​​동일합니다.

0

"이 작업을 수행하여"시작 "을 수정할 때.시작 (Line) (Point start, 최종 Point end) { "에서 초기화 한 후"start = new Point (start) "를 지정하면 힙에서 실제 오브젝트를 대체하지 않고"start " 새 포인터를 가리 키도록 기존 포인터 "시작"(STACK의 스칼라 유형)을 수정합니다.

생성자는 Java 힙에서 객체를 할당 한 후 Java의 새 연산자에 의해 호출되는 특수한 메서드 (함수)입니다. 따라서 메서드가 호출되면 스택이 할당되고 스칼라 유형 (int, double, char ...과 같은 기본 유형)과 메서드의 REFERENCE가 스택에 할당됩니다 (힙이 아님) 구문을 쓸 때 "final Object o = new Object()"로, 메모리 상에 두 가지를 할당했습니다.
먼저, Java 힙에 "new Object()"가 있습니다. (HEAP)
둘째로, "Object o"스택의 위 포인터. (STACK)
스칼라 유형이고 jvm 메모리 (STACK)에서만 읽을 수있는 "최종 객체 o"를 덮어 쓰려고했습니다.

class Line { 
Point start; 
Point end; 

// On the first line "Line(Point start, Point end) {", 
// two references and two actual Objects that references point to 
// are already allocated in memory. 
// So you've allocated four things. 
Line(Point start, final Point end) { // "start" initialized on stack as final 
    this.start = new Point(start); // tried to modify final variable on stack. 
    this.end = new Point(end); 
    start = new Point(0.4, 0.4); 

}