[java] 자바의 최종 대 C ++의 const

튜토리얼 C ++ 프로그래머를위한 자바 그 (강조는 내 자신의) 말한다 :

final 키워드
는 C ++의 const와 거의 같습니다.

이 문맥에서 “거의”는 무엇을 의미합니까? 그들은 정확히 동일하지 않습니까?

차이점이 있다면 무엇입니까?



답변

C ++ 표시에서 멤버 함수 constconst인스턴스에서 호출 될 수 있음을 의미합니다 . Java에는 이와 동등한 것이 없습니다. 예 :

class Foo {
public:
   void bar();
   void foo() const;
};

void test(const Foo& i) {
   i.foo(); //fine
   i.bar(); //error
}

값은 나중에 Java에서만 한 번만 지정할 수 있습니다.

public class Foo {
   void bar() {
     final int a;
     a = 10;
   }
}

Java에서는 합법적이지만 C ++에서는 합법적이지 않습니다.

public class Foo {
   void bar() {
     final int a;
     a = 10;
     a = 11; // Not legal, even in Java: a has already been assigned a value.
   }
}

Java와 C ++에서 멤버 변수는 각각 final/ 일 수 있습니다 const. 클래스 인스턴스 생성이 완료 될 때까지 값을 제공해야합니다.

Java에서는 생성자가 완료되기 전에 설정해야하며, 다음 두 가지 방법 중 하나로 수행 할 수 있습니다.

public class Foo {
   private final int a;
   private final int b = 11;
   public Foo() {
      a = 10;
   }
}

C ++에서는 const멤버쉽에 값 을 제공하기 위해 초기화 목록을 사용해야 합니다.

class Foo {
   const int a;
public:
   Foo() : a(10) {
      // Assignment here with = would not be legal
   }
};

Java에서는 final을 사용하여 무시할 수없는 것으로 표시 할 수 있습니다. C ++ (pre-C ++ 11)은이 작업을 수행하지 않습니다. 예 :

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

그러나 C ++에서 :

class Bar {
public:
   virtual void foo() const {
   }
};

class Error: public Bar {
public:
   // Fine in C++
   virtual void foo() const {
   }
};

멤버 함수를 표시하는 의미가 다르기 때문에 이것은 const좋습니다. 멤버 함수 중 하나만 사용하여 오버로드 할 수도 const있습니다 (C ++ 11에서는 멤버 함수를 최종으로 표시 할 수 있습니다 (C ++ 11 업데이트 섹션 참조).)


C ++ 11 업데이트 :

C ++ 11을 사용하면 finalJava와 같은 Java의 동일한 기능에 대해 동일한 의미 로 클래스와 멤버 함수를 모두로 표시 할 수 있습니다 .

public class Bar {
   public final void foo() {
   }
}

public class Error extends Bar {
   // Error in java, can't override
   public void foo() {
   }
}

이제 C ++ 11에서 다음과 같이 정확하게 작성할 수 있습니다.

class Bar {
public:
  virtual void foo() final;
};

class Error : public Bar {
public:
  virtual void foo() final;
};

이 예제는 G ++ 4.7의 시험판으로 컴파일해야했습니다. const이것은이 경우를 대체 하는 것이 아니라 가장 근접한 C ++ 키워드로는 보이지 않는 Java와 유사한 동작을 제공하여 기능을 보강한다는 점에 유의하십시오. 따라서 멤버 함수를 모두 원한다면 다음 final과 같이 const하십시오.

class Bar {
public:
  virtual void foo() const final;
};

( constfinal여기 의 순서 가 필요합니다).

이전에는 const멤버 함수 와 직접적으로 동등한 기능이 없었지만 virtual컴파일 타임에 오류를 발생시키지 않으면 서 함수를 비 만드는 것은 잠재적 인 옵션 일 수 있습니다.

마찬가지로 자바 :

public final class Bar {
}

public class Error extends Bar {
}

C ++ 11이됩니다.

class Bar final {
};

class Error : public Bar {
};

(이전에는 private생성자가 C ++에서 가장 근접했을 것입니다)

흥미롭게도 C ++ 11 이전 코드와의 호환성을 유지하기 위해 일반적인 방식으로 키워드 final 가 아닙니다 . (사소하고 합법적 인 C ++ 98 예제 struct final;를 통해 키워드로 만드는 것이 코드를 깨뜨리는 이유를 확인하십시오)


답변

Java에서는 최종 키워드를 다음 네 가지 용도로 사용할 수 있습니다.

  • 그것을 봉인하는 클래스 또는 메소드 (서브 클래스 / 재정의는 허용되지 않음)
  • 멤버 변수에 선언하면 정확히 한 번만 설정할 수 있습니다 (이것이 당신이 말하는 것입니다)
  • 메소드에 선언 된 변수에서 정확히 한 번만 설정할 수 있는지 확인
  • 메소드 매개 변수에서 메소드 내에서 수정할 수 없음을 선언

한 가지 중요한 것은 : Java 최종 멤버 변수 정확히 한 번 설정 해야합니다 ! 예를 들어 생성자, 필드 선언 또는 초기화 프로그램에서. 그러나 메소드에서 최종 멤버 변수를 설정할 수는 없습니다.

멤버 변수를 final로 만드는 또 다른 결과는 메모리 모델과 관련이 있으며, 이는 스레드 환경에서 작업하는 경우 중요합니다.


답변

const객체는 호출 할 수있는 const방법을 일반적으로 불변의 것으로 간주됩니다.

const Person* person = myself;
person = otherPerson; //Valid... unless we declared it const Person* const!
person->setAge(20); //Invalid, assuming setAge isn't a const method (it shouldn't be)

final객체는 새로운 객체로 설정할 수 없습니다, 그러나 그것은 불변하지 않습니다 수 있습니다 – 모든 전화에서 누군가를 중지 아무것도 없다 set방법.

final Person person = myself;
person = otherPerson; //Invalid
person.setAge(20); //Valid!

Java는 객체를 불변으로 선언하는 고유의 방법이 없습니다. 클래스를 변경할 수없는 것으로 디자인해야합니다.

변수가 기본 유형 인 경우 final/ const동일하게 작동합니다.

const int a = 10; //C++
final int a = 10; //Java
a = 11; //Invalid in both languages


답변

Java final은 기본 값 유형의 C ++ const와 같습니다.

Java 참조 유형을 사용하면 final 키워드는 const 포인터와 같습니다. 즉

//java
final int finalInt = 5;
final MyObject finalReference = new MyObject();

//C++
const int constInt = 5;
MyObject * const constPointer = new MyObject();


답변

여기에 이미 훌륭한 답변이 있지만 추가 할 가치가있는 한 가지 점이 있습니다 const.C ++에서는 일반적으로 프로그램의 다른 부분이 객체의 상태를 변경하지 못하게합니다. 지적했듯이, final자바에서는 이것을 할 수 없습니다 (원시적 제외)- 참조 가 다른 객체로 변경되는 것을 막습니다 . 그러나 Collection를 사용하는 경우 정적 메소드를 사용하여 객체 변경을 방지 할 수 있습니다

 Collection.unmodifiableCollection( myCollection ) 

이것은 Collection요소에 대한 읽기 액세스를 제공 하는 참조를 반환 하지만 수정이 시도되면 예외를 throw하여 constC ++에서 와 비슷하게 만듭니다.


답변

Java final는 기본 유형 및 참조에서만 작동하며 const 키워드가 어떤 객체에서도 작동하는 객체 인스턴스 자체에서는 작동하지 않습니다.

첫 번째 const list<int> melist;와 비교 final List<Integer> melist;하면 목록을 수정할 수 없지만 후자는 새 목록을에 할당 할 수 없습니다 melist.


답변

특정한 미묘한 멀티 스레딩 속성 을 갖는 것 외에도 선언 된 변수는 선언시 final초기화 할 필요가 없습니다!

즉, 이것은 자바에서 유효합니다 :

// declare the variable
final int foo;

{
    // do something...

    // and then initialize the variable
    foo = ...;
}

C ++로 작성된 경우에는 유효하지 않습니다 const.