본문 바로가기
  • soobinhand의 기술 블로그
도서/자바 프로그래밍 언어 - James Gosling

[자바 프로그래밍 언어] 2장 클래스와 객체

by soobinhand 2021. 12. 22.
728x90

2.1     단순한 클래스

  • 자바 프로그래밍의 기본 단위는 클래스이다.
  • 클래스는 메소드를 정의한다.
  • 이름을 잘 짓는 것은 클래스 설계의 핵심이다.
  • 제한자가 없는 클래스는 오직 소속된 패키지 내에서만 접근할 수 있다.
  • abstract 클래스는 불안정한 것으로 간주되므로 클래스의 인스턴스를 생성할 수 없다.
  • final 클래스는 상속할 수 없다.
  • 클래스는 동시에 final과 abstract가 될 수 없다.
  • public 클래스가 파일당 오직 한 개만 존재해야 한다.

2.2     필드

  • 클래스에 선언하는 변수를 필드라고 한다.
  • 서로 다른 인스턴스로 분리된 객체의 필드가 의미하는 것은 각 객체만의 유일한 상태를 가진다는 것이다. 이러한 필드를 인스턴스 변수라 한다.
  • 필드는 동시에 final과 volatile이 될 수 없다.
  • 가끔은 필드가 동일한 클래스로부터 생성된 모든 객체들에 의해 공유되기를 원한다. 이러한 필드를 생성하기 위해서는 필드를 static으로 선언해야 한다. 이를 정적 필드 또는 클래스 변수라 한다.
  • 정적 필드가 선언된 클래스에서는 정적 필드를 직접 참조할 수 있지만, 외부에서 접근할 때는 클래스 이름을 사용해서 접근해야 한다.
  • final 변수는 초기화된 이후에는 변경할 수 없는 변수이다.
  • 일반적으로 final 필드는 클래스나 객체의 불변 속성을 정의하기 위해 사용한다.
  • 필드를 final로 선언하기 전에 고려해볼 사항
    • 필드가 객체의 불변 속성을 나타내는가?
    • 필드의 값은 항상 객체가 생성될 때 알 수 있는가?
    • 객체를 생성할 때 필드의 값을 설정하는 것이 유용하면서 적절한가?
  • 상수 변수를 참조하는 코드가 있다면 컴파일러는 객체로부터 필드 값을 적재하기 위해서 필드 값을 바이트 코드로 변환하지 않는다. 단지 그 값을 바이트 코드에 직접 추가한다. 이는 최적화에 매우 유용하다.

2.3     접근 제어

  • private와 protected 접근 제한자는 오직 멤버에만 선언할 수 있으며 클래스와 인터페이스에는 선언할 수 없다. 단 중첩 클래스와 인터페이스는 제외.
  • public과 protected 멤버는 협약 관계로 봐야 한다. 왜냐하면 이들은 제어할 수 없는 코드가 되기 때문이다. 그래서 멤버가 public과 protected로 선언된 이후에는 변경하는 것이 불가능하다.

2.4     객체 생성

  • 선언 자체는 객체를 생성하지 못하며, 오직 객체를 참조하기 위한 변수를 정의할 뿐이다. 변수가 참조하는 객체는 명시적으로 생성해야만 한다.
  • 클래스의 객체를 새로 생성하면 객체의 변수들은 초기화된다.
  • 객체가 더 이상 필요하지 않다면 객체 참조를 중지하기만 하면 된다.

2.5     생성자와 초기화

  • 생성자는 new에 의해 객체 참조가 반환되기 전에 객체 초기화를 수행하는 문장들의 블록이다. 생성자는 클래스와 동일한 이름이어야 한다.
  • 생성자는 클래스 멤버들과 같이 접근 제한자를 가질 수 있지만 생성자는 클래스의 멤버가 아니다.
  • 기본 생성자는 클래스에 다른 생성자가 없을 때 자동으로 추가된다.
  • 클래스가 public이라면 기본 생성자도 public 접근성을 가진다.
  • 초기화 블록은 클래스 선언 내에 작성되는 문장들의 집합이며 멤버나 생성자 또는 객체의 필드를 초기화하는 선언 외부에 선언된다.
  • 초기화 블록은 생성자를 가질 수 없는 익명 내부 클래스를 작성할 때 상당히 유용하다.
  • 초기화 블록은 모든 생성자가 실행해야 하는 공통적인 코드를 정의할 때 유용하다.
  • 많은 클래스들은 객체 복사를 위한 더 일반화된 방식의 생성자를 제공하고 있다.

2.6     메소드

  • 추상 메소드는 클래스 내에서 몸체를 정의하지 않은 메소드를 말한다.
  • 추상 메소드의 몸체는 서브 클래스에서 정의해야 한다.
  • final 메소드는 서브 클래스에서 오버라이드할 수 없다.
  • 메소드는 점 .  연산자를 사용한 객체 참조를 통해 호출할 수 있다.
  • 모든 객체는 클래스에 명시적으로 정의하든 정의하지 않든 toString 메소드를 가진다.
  • 매개변수를 시퀀스로 선언하는 것은 배열을 생성하고 전달된 인자들이 배열의 요소가 되도록 컴파일러에게 요청하는 것일 뿐이다.
  • 메소드에 전달되는 모든 매개변수는 '값으로(by value)' 전달된다. 이 말은 메소드의 매개변수 값은 호출자가 인자로 지정한 겂으 복사본이라는 것을 의미한다.
  • 매개변수의 값을 변경하더라도 원래 값은 변경되지 않는다.
  • 객체의 필드를 변경하거나 객체의 상태를 변경하는 메소드를 호출하면 그 객체를 참조하는 프로그램의 모든 영역이 영향을 받는다.
  • '참조로 전달(pass by reference)'이라는 용어는 인자가 함수에 의해 전달되었을 때, 호출된 함수는 원래의 값에 대한 복사본이 아닌 실제 참조를 얻는다는 것을 의미한다.
  • 자바는 객체를 참조로 전달하지 않고 객체 참조를 값으로 전달한다.
  • 자바는 정확히 한 개의 매개변수 전달 방식인 '값으로(by value)' 방식만을 사용하므로 프로그램을 단순하게 만들어 준다.
  • 읽기 전용으로 만들기 위해서는 필드를 final로 선언해 객체가 존재하는 동안 읽기 전용이 되게 하거나 필드를 외부로부터 숨겨야 한다.
  • 필드를 private으로 선언하고 이 필드의 값을 설정하고 얻을 수 있는 메소드를 추가해두면 나중에 필요한 기능을 쉽게 추가할 수 있다.
  • 필드가 불변성을 가져야 한다면 접근성에 상관없이 final로 선언해야 한다. 반대로 필드가 클래스의 협약의 일부가 아니라면 필드가 읽기 전용인지 수정가능한지에 상관없이 필드를 메소드 뒤에 숨겨야 한다.

2.7     this

  • 비정적 메소드에서는 특수한 객체 참조인 this를 사용할 수 있으며, this는 메소드가 포함된 현재 객체를 가리킨다. 정적 메소드는 객체에 존재하는 것이 아니기 때문에 this 참조를 사용할 수 없다.
  • this 참조는 현재 객체의 참조를 다른 메소드의 인자로 넘기기 위해 사용하는 가장 일반적인 방법이다.
  • 지역 변수나 매개변수가 사용할 필드의 이름을 가리키는 경우에만 this를 사용해야 한다.

2.8     메소드 오버로드

  • 두 개의 메소드가 매개변수의 개수와 타입이 다르다면 동일한 이름을 가질 수 있다. 이를 오버로드라고 한다.

2.9     정적 멤버 임포트

  • import static java.lang.Math.exp; 를 예시로 듬.
  • 정적 임포트 문은 클래스나 인터페이스를 선언하기 전인 소스 파일 상단에 선언해야 한다.
  • 정적 임포트 문을 선언하면 소스 파일 어디서나 exp 메소드 호출을 자동으로 Math.exp 메소드 호출로 전환해준다.
  • 정적 임포트를 사용하면 코드의 가독성은 높일 수 있지만 잘못 사용하면 코드를 이해하기 어렵게 만들 수 있다.
  • 일반적으로 정적 임포트는 약간의 타이핑을 줄이기 위해서보다는 코드의 가독성과 명확성을 향상시키는 용도로 사용해야 한다.

2.10     main 메소드

  • 프로그램을 실행하면 시스템은 지정된 클래스의 main 메소드의 위치를 찾아내서 실행한다. main 메소드는 public static, void로 선언해야 하며 String[] 타입의 단일 인자를 받을 수 있어야 한다.
  • main 메소드에 전달된 String 배열은 프로그램 인자를 포함한다.
  • java Echo in here 라고 cmd에 치면 Echo.main을 호출하고 args에 in here이 들어간다.
  • 출력 결과는 in here다.

2.11     네이티브 메소드

  • 자바로 작성되지 않은 코드를 자바 프로그램에서 사용할 필요가 있다면 또는 하드웨어를 직접 조작할 필요가 있다면 네이티브 메소드를 작성해야 한다.
  • 네이티브 메소드는 C나 C++같은 네이티브 언어로 작성된 메소드를 자바에서 호출해 사용하려고 할 때 유용하다.
  •  
  • // 호스트 머신의 CPU 식별자를 운영 체제에 요청하는 네이티브 메소드 public native int getCPUID();
  • 네이티브 메소드를 사용하면 코드의 이식성과 안정성이 보장되지 않는다.
  • 네이티브 메소드는 가상 머신을 제작한 사람들이 제공한 API를 사용하여 구현할 수 있다.
728x90

댓글