새소식

JAVA

자바 기초 : 패키지와 접근 제한자

  • -

핵심개념

  • 패키지 : 프로젝트 개발 시 클래스를 체계적으로 관리하기 위해 패키지를 사용하며, 클래스와 클래스의 멤버를 사용범위에 맞게 접근 제한자를 활용해야한다. 패키지의 물리적인 형태는 파일 시스템의 폴더이고 패키지는 클래스의 일부분으로 클래스를 유일하게 만들어주는 식별자 역할을 한다. 클래스의 이름이 동일하더라도 패키지가 다르면 다른 클래스로 인식하며 클래스의 전체 이름은 패키지+클래스 이름이며 패키지의 상하위 구분은 .으로 한다.

ex) com.mycompany.A   /    com.yourcompany.B

 

  • 패키지 선언 : 클래스를 작성할 때 해당 클래스가 어떤 패키지에 속할 것인지를 선언하는 것
    ex) package 상위패키지.하위패키지;
          public class ClassName {...}

    패키지 이름 규칙
    1. 숫자로 시작x, $ 또는 _ 제외 특수문자 사용 불가
    2. java로 시작하는 패키지는 자바 표준 API에서만 사용 가능하므로 사용 불가
    3. 모두 소문자로 작성하는 것이 관례

  • import문 : 사용하고자 하는 클래스 또는 인터페이스가 다른 패키지의 소속된 경우 해당 패키지의 클래스 또는 인터페이스를 가져와 사용할 것임을 컴파일러에게 통지하는 역할을 한다.

  • import문 작성방법 : 패키지 선언과 클래스 선언 사이에 작성해야한다. 만약 사용하고자 하는 클래스들이 같은 패키지 소속이라면 *를 이용함. import문의 개수 제한은 없다.
    ex) import 상위패키지.하위패키지.클래스이름;
          import 상위패키지.하위패키지.*;

    ex) com.mycompany.Car에서 com.hankook패키지에 있는 Tire클래스를 사용해야 할 경우
       ->package com.mycompany;
             import com.hankook.Tire;
         //= import com.hankook.*;
          public class Car { 
             Tire tire = new Tire();
         }

    주의할 점은 상위패키지를 import했다고해서 하위패키지까지 import되는 것은 아니므로 하위 패키지는 별도로 import를 해야한다는 것이다.
    ex)com.hankook과 com.hankook,project는 서로 다른 패키지로 인식되므로 별도로 import문 작성
     ->import com.hankook.*;
        import com.hankook.project.*;

    만약 다른 패키지에 동일한 클래스 이름이 있을 경우 정확하게 패키지가 포함된 클래스 전체 이름을 적어야한다.
    ex)ch06.sec06.ex02.hankook.Tire tire1 = new ch06.sec06.ex02.hankook.Tire();
         ch06.sec06.ex02.canada.Tire tire2 = new ch06.sec06.ex02.canada.Tire();
package ch06.sec06.ex02.mycompany;
   //import문은 패키지 선언와 클래스 선언 사이에 작성해야한다.
   import ch06.sec06.ex02.hyundai.Engine;
   import ch06.sec06.ex02.hankook.*;
   import ch06.sec06.ex02.kumho.*;

   public class Car {
   //필드
   Engine engine = new Engine();
   SnowTire tire1 = new SnowTire();
   BigwidthTire tire2 = new BigwidthTire();

   ch06.sec06.ex02.hankook.Tire tire3 = new ch06.sec06.ex02.hankook.Tire();
   ch06.sec06.ex02.kumho.Tire tire4 = new ch06.sec06.ex02.kumho.Tire();
   //전체 클래스 이름을 적어주면 어느 패키지에 있는 클래스인지 명확해진다.
}

 

  • import문 자동 추가 기능 : ctrl + shift + o -> 기본적으로 'import 패키지.클래스;'로 추가
    'import 패키지.클래스.*;'로 추가하고 싶다면 Window - preference - 대화창의 java - Code Style - Organize imports - Number of imports needed for .*의 99를 1로 변경 - Apply - 다시 ctrl + shift + o를 누르면 된다.

  • 접근제한자(Access Modifier) : 클래스, 인터페이스, 이들 멤버의 접근을 제한하기 위해 사용.
    public 접근제한자 : 외부 클래스가 자유롭게 사용할 수 있도록 함
    protected 접근제한자 : 같은 패키지 또는 자식클래스에서 사용할 수 있도록 함
    default 접근제한자 : 같은 패키지 소속 클래스에서만 사용될 수 있도록 함.(public,protected,private가 적용되지 않을 경우 default 접근제한자를 가진다.)
    private 접근제한자 : 외부에서 사용할 수 없도록 함.(클래스 내부에서만 사용가능)

public -> private 접근제한이 강화됨

 

  • 클래스의 접근 제한 : 클래스 선언 시 클래스를 같은 패키지 내에서만 사용할 것인지(default) 다른 패키지에서도 사용할 수 있도록 할 것인지(public)결정해야한다.

  • default 접근 제한 : 클래스 선언 시 public을 선언했을 경우 default 접근 제한을 가진다. 같은 패키지 내부에서만 제한 없이 사용 가능하며 다른 패키지에서는 사용하지 못한다.

  • public 접근 제한 : 다른패키지에서도 제한 없이 사용 가능. 
package ch06.sec06.ex03.package1;
   class A { //default 접근제한
   B field;
}

---------------------------------------------------------

package ch06.sec06.ex03.package1;
   public class B { //public 접근제한
   A field; //B클래스는 A와 같은 패키지 이므로 A클래스에 접근 가능(필드로 선언 가능)
   A a;
}

---------------------------------------------------------

package ch06.sec06.ex03.package2;
   //다른 패키지 클래스 사용
import ch06.sec06.ex03.package1.B;
   public class C {
   //A field; //컴파일 에러 발생. default는 같은패키지 내에서 사용가능
   B field2; //임포트 하여 사용가능
}

 

  • 생성자의 접근 제한 : 어떤 접근제한자인지에 따라 생성자 호출 가능 여부가 결정된다. 생성자는 public, protected, default, private 접근 제한을 가진다. 클래스에 생성자를 선언하지 않을 시 컴파일러에 의해 자동으로 기본 생성자가 작성되는데, 기본 생성자의 접근 제한은 클래스의 접근 제한과 동일하게 가지게 된다.
    public 접근 제한 : 모든 패키지에 아무런 제한 없이 생성자 호출 가능
    protected 접근 제한 : default접근 제한과 마찬가지로 같은 패키지에 속하는 클래스에서 생성자 호출 가능. default와의 차이점은 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 생성자 호출이 가능하다는 점이다.
    default 접근 제한 : 같은 패키지 내에서 생성자 호출 가능
    private 접근 제한 : 클래스 내부에서만 생성자 호출 및 객체 생성 가능
package ch06.sec06.ex04.package1;
   public class A {
   A() {}
}

------------------------------------------------------

package ch06.sec06.ex04.package1;
   public class B {
   A field = new A();
}

------------------------------------------------------

package ch06.sec06.ex04.package2;
import ch06.sec06.ex04.package1.A;
   public class C {
   //A field = new A(); //A클래스가 default이기 때문에 생성자 호출x
}
package ch06.sec06.ex04.package1;
public class A {
   //필드
   A al = new A(true);
   A a2 = new A(1);
   A a3 = new A("문자열");

   //생성자
   public A(boolean b) {} //public 접근제한
   A(int b) {} //default 접근제한
   private A(String s) {} //private 접근제한

   //A클래스 내부에서는 A의 모든 생성자 호출 가능
}

------------------------------------------------------

package ch06.sec06.ex04.package1; //A클래스와 패키지 동일
public class B {
   A a1 = new A(true); //public이므로 사용가능
   A a2 = new A(1); //default이므로 같은 패키지 내 사용가능
   //A a3 = new A("문자열"); (x) //private이므로 생성자 접근 불가능
}

------------------------------------------------------

package ch06.sec06.ex04.package2;
import ch06.sec06.ex04.package1.A;
public class C {
   //필드
   A a1 = new A(true); //public이므로 사용가능
   //A a2 = new A(1); (x) //default이므로 다른패키지의 생성자 접근 불가능
   //A a3 = new A("문자열"); (x) //private이므로 생성자 접근 불가능
}

 

  • 필드와 메소드의 접근 제한 : 필드와 메소드에 사용할 수 있는 접근제한자는 public, protected, default, private가 있다.
    public 접근 제한 : 모든 패키지에 아무런 제한 없이 필드와 메소드 사용 가능.
    protected 접근 제한 : default접근 제한과 마찬가지로 같은 패키지에 속하는 클래스에서 필드와 메소드 사용 가능. default와의 차이점은 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 필드와 메소드 사용 가능하다는 점이다.
    default 접근 제한 : 같은 패키지 내에서 필드와 메소드 사용 가능.
    private 접근 제한 : 클래스 내부에서만 필드와 메소드 사용 가능.

  • Getter과 Setter 메소드 : 외부에서 객체에 마음대로 접근할 경우 객체의 무결성이 깨질 수 있다. 따라서 객체의 필드를 외부에서 직접적으로 접근하는 것을 막기위해 Getter과 Setter 메소드를 사용한다.
    ex) 자전거의 속력이 음수가 될 수 없음에도 외부에서 음수로 변경할 경우 객체의 무결성이 깨진다.
          myCar.speed = -100 //Car객체의 필드값을 -100으로 변경함

  • Setter 메소드 : 필드는 외부에서 접근할 수 없도록 막고 외부에서 메소드를 통해 필드에 접근하도록 유도하는 역할.(메소드는 매개값을 검증하여 유효한 값만 필드로 저장할 수 있기 때문)
    ex) 자동차의 속도를 setSpeed로 변경할 경우 검증코드
          void setSpeed(double speed){
             if(speed < 0) {
               this,speed = 0;  //매개값이 음수일 경우 speed필드에 0으로 저장 후 메소드 종료
               return;
              } else {
                this.speed = speed
             }}

  • Getter 메소드 : 메소드로 필드값을 가공한 후 외부로 전달하는 역할.(필드값을 직접 사용하면 부적절한 경우도 있기 때문)
    ex) 자동차의 속도를 마일에서 km단위로 환산해서 외부로 리턴
          double setSpeed() {
             double km = speed*1.6;  //필드값인 마일을 km 단위로 환산 후 외부로 리턴
             return km;
          }

  • Getter과 Setter 메소드 선언법 : 클래스 선언 시 가능하면 필드를 private으로 선언하고 필드에 대한 Getter과 Setter메소드를 작성하여 필드값을 변경하거나 사용하는 것이 좋다.
    *이클립스의 [Source] - [Generate Getter and Setter] 메뉴를 선택해 자동생성 가능

    ex)
    private 타입 fieldName; //필드 접근제한자 : private
    //Getter
    public 리턴 타입 getFieldName() {  //접근제한자:public, 리턴타입:필드타입, 메소이름:get+필드이름
       return fieldName  //리턴값:필드값
    }
    //Setter
    public void setFieldName(타입 fieldName) { //접근제한자:public, 리턴타입:void, 메소드이름:set+필드이름
       this.fieldName = fieldName; //매개변수타입:필드타입
    -------------------------------------------------------------------------------------------
    ex) 필드타입이 boolean일 경우 Getter은 get대신 is로 시작하는것이 관례
    private boolean stop; //필드 접근제한자 : private
    //Getter
    public boolean isStop(){ //접근제한자:public, 리턴타입:필드타입, 메소드이름:is+필드이름
       return stop; //리턴값:필드값
    }
    //Setter
    public void setStop(boolean stop) { //접근제한자:public, 리턴타입:void, 메소드이름:set+필드이름
       this.stop = stop; //매개변수타입:필드타입
    }
public class Car {
   //필드
   private int speed;
   private boolean stop;

   //생성자
   //메소드
   public int getSpeed() {
   return speed;
   }

public void setSpeed(int speed) {
   if(speed<0) {
      this.speed = 0;
      return;
      }else {
         this.speed = speed;
      }
   }

   public boolean isStop() {
   return stop;
   }

public void setStop(boolean stop) {
   this.stop = stop;
      if(stop) { //참이면 속도는 0
         this.speed = 0;
      }
   }
}

----------------------------------------------------------------

public class CarEx {
   public static void main(String[] args) {
      Car myCar = new Car();

   //잘못된 속도 변경
   myCar.setSpeed(-100);
   System.out.println("현재속도 : " + myCar.getSpeed());

   //올바른 속도 변경
   myCar.setSpeed(50);
   System.out.println("현재속도 : " + myCar.getSpeed());

   //멈춤
   myCar.setStop(true);
   if(myCar.isStop()) {
   System.out.println("차량이 멈춘 현재속도 : " + myCar.getSpeed());
   }
 }
}
실행결과 : 
현재속도 : 0
현재속도 : 50
차량이 멈춘 현재속도 : 0

 
tip! 폴더보기 구조 변경 : Package Explorer뷰 오른쪽 view menu 클릭 - Package Presentation - Hierachical(=계층에따른) 클릭

 

 

'JAVA' 카테고리의 다른 글

자바 기초 : 타입 변환과 다형성  (0) 2023.03.12
자바 기초 : 상속  (0) 2023.03.11
자바 기초 : 인스턴스 멤버와 정적 멤버  (0) 2023.03.07
자바 기초 : 메소드  (0) 2023.03.06
자바 기초 : 생성자  (0) 2023.03.03
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.