ToBe끝판왕

[ JAVA ] 인스턴스 멤버 , 정적 멤버 , 싱글톤 , final필드 , 패키지 , 접근제한자 , Getter & Setter 메서드 본문

■ 프로그래밍 SKILLS/JAVA

[ JAVA ] 인스턴스 멤버 , 정적 멤버 , 싱글톤 , final필드 , 패키지 , 접근제한자 , Getter & Setter 메서드

업그레이드중 2022. 5. 19. 16:33
반응형

 


 

인스턴스( instance ) 멤버

▶  정의

•  인스턴스 멤버란 객체( 인스턴스 )를 생성한 후, 사용할 수 있는 필드와 메서드를 의미

   각각 인스턴스 필드 , 인스턴스 메서드라고 불린다.

•  인스턴스 필드와 메서드는 객체에 소속된 멤버이기 때문에 객체 없이는 사용 할 수 없다.

 

▶  선언

gas와 setSpeed() 는 인스턴스 멤버이기 때문에 외부클래서 사용할 때에는
Car 객체를 생성하고 참조변수( mycar, yourcar ) 로 접근해야 한다.

ex)
public class Car {

  // 인스턴스 필드
   int gas;

  // 인스턴스 메서드
  void setSpeed( int speed ) { }

}

public class CarExample {

    public static void main( String[] args ) {
      Car mycar = new Car();
      mycar.gas = 10;
      mycar.setSpeed(60);

      Car yourcar = new Car();
      yourcar.gas = 20;
      yourcar.setSpeed(80);
   }
}

이때 인스턴스 필드 gas는 객체마다 따로 존재
인스턴스 메서드 setSpeed()는 객체마다 존재하지 않고 메서드 영역에 저장되고 공유된다.

 

※ this

•  객체 내부에서도 인스턴스 멤버에 접근하기 위해 this를 사용할수 있다.

•  this 는 주로 생성자와 메서드의 매개변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시하고자 할때 사용한다.


 

정적 멤버

▶  정의

•  정적( static )은 "고정된" 이란 의미이다.

•  정적멤버는 클래스에 고정된 멤버로서 , 객체를 생성하지 않고 사용할 수 있는

   필드와 메서드를 말한다. ( 각각 정적필드 , 정적메서드로 불린다. )

•  정적멤버는 클래스에 소속된 멤버이기 때문에 클래스멤버라고도 한다.

▶  선언

정적필드와 정적메서드 선언시 , static 키워드를 추가해주면 된다.

ex)
public class Calculator {

    // 정적 필드
    String color;
    static double pi = 3.14159;     // 계산기에서 사용하는 파이값은 모두 동일
                                    //  그러므로 정적필드를 선언

    // 정적 메서드
    void setColor( String color ) {}
    static int plus( int x, int y ) { return x+y };

}

 

 

▶  인스턴스 필드 / 정적 필드 선언 판단 기준

•  객체마다 가지고 있어야 할 데이터 : 인스턴스 필드 ( 각 개체마다 색깔 값 등... )

•  객체마다 가지고 있을 필요성 없는 공용적인 데이터 : 정적 필드

 

▶  인스턴스 메서드 / 정적 메서드 선언 판단 기준

•  인스턴스 필드를 이용해서 실행 : 인스턴스 메서드

•  인스턴스 필드를 이용하지 않음 : 정적 메서드

 

▶  정적멤버 사용

•  클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있다.

•  클래스 이름과 함께 도트 ( . ) 연산자로 접근 가능 ( 인스턴스는 객체 참조변수 이름 )

 

※ 정적 필드와 정적 메서드는 객체 참조변수 이름으로도 접근이 가능하긴 하지만 클래스 이름으로 접근하는것이 좋다.

정적필드 / 정적메서드

ex)
public class CalculatorExample {
   public static void main( String[] args ) {
      // 정적 필드 사용
      double result1 = 10 * 10 * Calculator.pi;

      // 정적 메서드 사용
      int result2 = Calculator.plust( 10, 5 );
   }
}

※ 정적 필드는 보통 필드 선언과 동시에 초기값을 주는것이 보통

※ 계산이 필요한 초기화 작업

•  정적필드의 복잡한 초기화 작업을 위해 정적블록( static block ) 을 제공

•  정적블록은 클래스가 메모리로 로딩될때 자동으로 실행

•  정적 블록은 클래스 내부에 여러개가 선언되어도 상관 X

•  클래스가 메모리에 로딩될 때, 선언된 순서대로 실행

 

▶  정적 메서드 / 정적 블록 선언시 주의할점 !

•  정적메서드 / 정적 블록 내부에 인스턴스 필드나 인스턴스 메서드는 사용할 수 없다.

   ( 객체가 생성되지 않않기 때문 )

•  객체 자신 참조인 this 키워드 사용 불가

 

※ 정적 메서드에서 인스턴스 멤버를 사용하고 싶다면 , 객체를 먼저 생성하고 참조변수로 접근해야 한다.

 
ex)
public class ClassName { 
   // 인스턴스 필드와 메서드
   int field1;
   void method1() { ... }

   // 정적 필드와 메서드
   static int field2;
   static void method2() { ... }

   // 인스턴스 멤버를 같이 사용하려면, 객체를 먼저 생성하고 참조변수로 접근
   static void method3() {
     ClassName obj = new ClassName();       // 객체생성
     obj.field1 = 10;                       // 인스턴스 필드 사용가능
     obj.method1();                         // 인스턴스 메서드 사용가능
   }
}

 


 

싱글톤

▶  정의

•  가끔 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다.

   이러한 단 하나만 생성되는 객체를 싱글톤( singleton) 이라고 한다.

•  싱글톤을 만드려면 외부 클래스에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다.

•  이를 위해서 생성자 앞에 private 접근제한자를 붙여준다.

•  자신의 타입인 정적필드를 하나 선언하고 , 자신의 객체를 생성해 초기화 한다.

•  이때, 정적필드도 private 접근 제한자를 붙여와 외부에서 필드값을 변경 못하도록 막는다.

   대신 외부에서 이 필드를 호출할 수 있도록 정적 메서드인 getlnstance()를 선언하고 정적 필드에서 참조하고 있는

    자신의 객체를 리턴해준다.

•  외부에서 객체를 얻는 유일한 방법은 getInstance() 메서드를 호출하는 방법밖에 없다.

•  싱글톤

ex)
public class Singleton {
   // 정적필드
   private static Singleton singleton = new Singleton();

   // 생성자
   private Singleton() {}

   // 정적 메서드
   static Singleton getInstance() {
     return singleton;
   } 
}
 

 


 

final 필드 & 상수

▶  final 필드 정의

최종적인 필드 ( 초기값이 저장되면 프로그램 실행 도중 수정 X )

▶  final 필드 선언

 
public class person {
    final String nation = "korea";   // 필드 생성시 final 필드 초기화
    final String ssn;
    String name;

   // 외부 클래스에서 객체 생성시 final 필드 생성자에서 초기화
    public Person( String ssn, String name ) {
       this.ssn = ssn;
       this.name = name;
   }
}

final 필드에 초기값을 줄수 있는 방법 2가지
1) 필드 선언시에 주는 방법
2) 생성자에서 주는 방법

※ 만일 객체 생성 시에 외부 데이터로 final 필드를 초기화해야한다면 생성자에서 
   초기값을 지정해야 한다.
public class PersonExample {

	public static void main(String[] args) {
		Person p1 = new Person("000101-1234567", "홍길동");
		
		System.out.println(p1.nation);
		System.out.println(p1.name);
		System.out.println(p1.ssn);
    }
}
결과값

Korea
홍길동
000101-1234567

 

▶  상수( constant ) 정의

•  일반적으로 불변의 값을 상수라고 한다.

   ( ex : 원주율 , 지구의 무게 및 둘레 ... )

•  불변의 값은 객체마다 저장할 필요가 없는 공용성을 띄고

   여러가지 값으로 초기화될 수 없기 때문( 오직 하나의 값을 가지므로 final 필드와 거리가 멀다. )

•  상수는 static ( 공용성 ) 이면서 final ( 수정불가 )이어야 한다.

•  static final 필드는 객체마다 저장되지 않고 , 클래스에만 포함되며, 한번 초기화되면 변경 불가능

▶  상수( constant ) 선언

public class Earth {
        //상수선언
	static final double EARTH_RADIUS = 6400;
	static final double EARTH_AREA = 4 * Math.PI * EARTH_RADIUS * EARTH_RADIUS;
}

※ Math.PI 는 자바에서 제공하는 상수이다.
public class EarthExample {

	public static void main( String[] args ) {
		System.out.println( "지구의 반지름: " + Earth.EARTH_RADIUS );
		System.out.println( "지구의 표면적: " + Earth.EARTH_AREA );
	}
}

 


 

패키지( package )

▶  정의

•  패키지는 물리적으로 폴더와 같다.

   뿐만 아니라 클래스를 유일하게 만들어주는 식별자 역할도 한다.

•  JAVA에서는 클래스 이름이 동일하더라도 패키지가 다르면 다른클래스로 인식

•  패키지는 도트(.)를 이용해서 표현

상위패키지.하위패키지.클래스

ex) com.mycompany.Car

 

 

▶  패키지( package ) 중요성

•  클래스만 따로 복사해서 다른곳으로 이동하면, 클래스는 사용할수 없다.

   ( 이동시 패키지 전체를 이동시켜야 한다. )

▶  패키지( package ) 선언

•  해당 클래스가 어떤 패키지에 속할것인지를 선언 하는 것

•  패키지( package )는 클래스를 컴파일 하는 과정에서 자동적으로 생성되는 폴더이다.

•  컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고, 파일 시스템의 폴더로 자동생성 시킨다.

package 상위패키지.하위패키지;

public class CalssName { ... }

 

※ 참고사항

회사들간에 협업해서 JAVA로 프로그램을 만들면 패키지명은 회사이름으로 하는것이 관례

▶  import문

•  사용하고자 하는 클래스 or 인터페이스가 다른 패키지에 소속되어 있다면

import문으로 해당 패키지의 클래스 or 인터페이스를 가져와서 사용해야 한다.

•  상의 패키지를 import 했다고 하위 패키지까지 import 되는 것은 아니다.

import 상위패키지.하위패키지.클래스이름;

import 상위패키지.하위패키지.*;    // 패키지의 모든 클래스를 가져오는 명령어
 
 

 
접근제한자

▶  정의

main() 메서드를 가지지 않은 외부클래스에서 이용할 목적으로 설계된 라이브러리 클래스를 설계할 때에는

외부클래스에서 접근할 수 있는 멤버와 없는 멤버로 구분하여  필드, 생성자, 메서드를 설계한다.

( 이때, 접근을 제한하기 위해 사용된다. )

 

▶  종류

•  public : 외부 클래스가 자유롭게 사용할 수 있다.

•  protected : 같은 패키지 or 자식 클래스에서만 사용할 수 있다.

•  private : 개인적인 것이라 외부에서 사용될 수 없다.

•  default : 위 3가지 접근제한자가 적용이 안되면 적용되며, 같은 패키지 안 클래스에서만 사용 가능

▶  클래스의 접근 제한

클래스 선언시, 같은 패키지내에서만 사용할 것인지 다른 패키지에서도 사용할 수 있도록 할것인지 결정한다.

 

▶  default 접근 제한

•  클래스 선언시, 접근제한자가 생략되면 default가 자동적으로 적용

•  같은 패키지 내에서 아무런 제한 없이 사용가능 , 다른패키지내에서는 사용할 수 없도록 제한

package sec06.exam03.package1;

    class A { }  //default 접근 제한


package sec06.exam03.package1;   //같은패키지

    public class B {
        A a;   // 사용가능, A클래스 접근가능
    }

 

 

▶  public 접근 제한

•  클래스를 선언할 때, public 접근제한자를 붙이면 같은 패키지 뿐만 아니라 다른 패키지내에서도

아무런 제한 없이 사용가능

•  라이브러리 클래스로 개발한다면, 반드시 public 접근제한을 갖도록 해야한다.

package sec06.exam03.package1;

    class A { }  //default 접근 제한

package sec06.exam03.package1;   

    public class B {
        A a;   
    }
    
package sec06.exam03.package2;   //패키지가 위와 다름

    public class C {
        A a;   // 사용불가, A클래스는 default
        B b;   // 사용가능, B클래스는 public
    }

 

▶  생성자 접근 제한

•  객체를 생성하기 위해 new 연산자로 생성자를 호출해야 한다.

•  생성자가 어떤 접근 제한을 갖느냐에 따라, 호출 가능 여부가 달라진다.

•  생성자에 적용할 수 있는 접근제한자 : public , protected , default, private

 

•  생성자의 접근제한 예시

 
package sec01.exam01.package1;

public class A {
   // 필드
   A a1 = 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 접근제한
}
package sec01.exam01.package1; // A와 동일한 패키지

public class B {
   // 필드
   A a1 = new A( true );       // 가능 ( A 클래스의 public 생성자 )
   A a2 = new A(1);            // 가능 ( A 클래스의 default 생성자 )
   A a3 = new A( "문자열" );   // 불가능: 컴파일에러 ( A 클래스의 private 생성자 )

}
package sec01.exam01.package2;   // 다른 패키지

import sec01.exam01.package1;    // package1 import

public class C {
   // 필드
   A a1 = new A( true );       // 가능 ( A 클래스의 public 생성자 )
   A a2 = new A(1);            // 불가능: 컴파일에러 ( A 클래스의 default 생성자 )
   A a3 = new A( "문자열" );   // 불가능: 컴파일에러 ( A 클래스의 private 생성자 )

}

 

▶  필드 & 메서드 접근 제한

•  필드와 메서든 선언시, 클래스 내부에서만 사용할지 패키지 내에서만 사용할 것인지 아니면

    다른 패키지에서도 사용할 것인지를 결정해야 한다.

•  필드 & 메서드에 적용할 수 있는 접근제한 : public , protected, default, private

 

•  필드 & 메서드 접근제한 예시

pacakge sec01.exam01.package1;

public class A {
   // 필드
   public int field1;    // public 접근제한 필드
   int field2;           // default 접근제한 필드
   private int field;    // private 접근제한 필드

   // 생성자
   public A() {
      field1 = 1;     // 가능( 클래스 내부 필드 )
      field2 = 2;     // 가능( 클래스 내부 필드 )
      field3 = 3;     // 가능( 클래스 내부 필드 )

      method1();      // 가능( 클래스 내부 메서드 )
      method2();      // 가능( 클래스 내부 메서드 )
      method3();      // 가능( 클래스 내부 메서드 )
   }

   // 메서드
   public void meethod1() {}   // public 접근 제한 메서드
   void method2() {}           // default 접근 제한 메서드
   private void method3() P{   // private 접근 제한 메서드
}
pacakge sec01.exam01.package1;    // A클래스와 같은 패키지

public class B {
   // 생성자
   public B() {
      A a = new A();    // A 클래스 접근 가능 ( public )

      a.field1 = 1;     // 가능( A 클래스의 public 필드 접근 가능 )
      a.field2 = 2;     // 가능( A 클래스의 default 필드 접근 가능 )
      a.field3 = 3;     // 불가능:컴파일에러( A 클래스의 private 필드 접근 불가 )

      a.method1();      // 가능( A 클래스의 public 메서드 접근 가능 )
      a.method2();      // 가능( A 클래스의 default 메서드 접근 가능 )
      a.method3();      // 불가능:컴파일에러( A 클래스의 private 메서드 접근 불가 )
}
pacakge sec01.exam01.package2;    // A, B 클래스와 다른 패키지

import sec01.exam01.package1.A    // A클래스 import

public class C {
   // 생성자
   public C() {
      A a = new A();    // a 객체 생성, A 클래스 접근 가능

      a.field1 = 1;     // 가능( A 클래스의 public 필드 접근 가능 )
      a.field2 = 2;     // 불가능:컴파일에러( A 클래스의 default 필드 접근 불가 )
      a.field3 = 3;     // 불가능:컴파일에러( A 클래스의 private 필드 접근 불가 )

      a.method1();      // 가능( A 클래스의 public 메서드 접근 가능 )
      a.method2();      // 불가능:컴파일에러( A 클래스의 default 메서드 접근 불가 )
      a.method3();      // 불가능:컴파일에러( A 클래스의 private 메서드 접근 불가 )
}

 

 


 

Getter & Setter 메서드

▶  정의

•  객체지향프로그래밍( OOP )에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는것을 막는다.

    이유는 외부에서 마음대로 변경할 경우, 객체의 무결성( 결점이 없는 성질 )이 깨질수 있기 때문이다.

    이를 해결하기 위해서, 객체지향프로그래밍에서는 메서드를 통해서 필드를 변경하는 방법을 선호한다.

    필드는 외부에서 접근할 수 없도록 막고 메서드는 공개해서 외부에서 메서드를 통해서 필드에 접근한다.

   이유는 메서드는 매개값을 검증해서 유효한 값만 객체의 필드로 저장할 수 있기 때문이다.

   이러한 메서드가 Setter 이다.

•  외부에서 객체의 데이터를 읽을 때도 메소드를 사용하는 것이 좋다. 왜냐하면 필드값을 직접 사용하면

    부적절한 경우도 있기 때문이다. 이런 경우 메소드로 필드값을 가공한 후 외부로 전달하는데 이런 메서드가 Getter 이다.

•  클래스를 선언할 때 가능하다면 필드를 private로 선언해서 외부로부터 보호하고, 필드에 대한 Setter와 Getter 메서드를

    작성해서 필드값을 안전하게 변경/사용하는 것이 좋다.

 

•  만약 외부에서 필드값을 읽을 수만 있고 변경하지 못하도록 하려면(읽기전용) Getter 메서드만 선언하거나 Setter 메서드를       

    private 접근 제한을 갖도록 선언한다.

 

※ 참고

•  이클립스에서 Getter/Setter 자동생성하기

필드 선언한 후 [Source] - [Generate Getter and Setter] 메뉴 선택 - 선언된 필드에 대한 자동 생성  대화상자 실행

Getter & Setter 메서드 예시

 
public class Car {
   // 필드
   private int speed;
   private boolean stop;

   // 생성자

   // 메서드
   public int getSpeed() {   // Getter
      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;
         this.speed = 0;
}
public class CarExample {
   public static void main( String[] args ) {
      Car myCar = new Car();       // 객체생성

      // 잘못된 속도 변경
      myCar.setSpeed( -50 );

      System.out.println( "현재 속도 : " + myCar.getSpeed() );   // 0 출력

      // 올바른 속도 변경
      myCar.setSpeed( 60 );

      // 멈춤
      if( !myCar.isStop() ) {
          myCar.setStop( true );
      }

      System.out.println( "현재 속도 : " + myCar.getSpeed() );    // 0 출력
  }
}


//speed 필드값을 음수로 변경하려 하면, Setter인 setSpped에서 매개값 겁사 후
//0으로 변경하기 때문에 0이 출력

//Stop 필드의 Getter 인 isStop() 리턴값이 fasle일 경우,
//Setter인 setStop( true )를 호출해서 stop필드를 true로, speed 필드를 0으로 변경

 

 

 

 

반응형

'■ 프로그래밍 SKILLS > JAVA' 카테고리의 다른 글

[ JAVA ] 타입변환과 다형성  (0) 2022.05.23
[ JAVA ] 상속  (0) 2022.05.23
[ JAVA ] 생성자  (0) 2022.05.17
[ JAVA ] 메서드  (0) 2022.05.17
[ JAVA ] 클래스와 객체  (0) 2022.05.16
Comments