인스턴스 멤버와 정적 멤버

인스턴스 멤버와 this

인스턴스 멤버는 객체마다 가지고 있는 멤버를 말하고

정적 멤버는 클래스에 위치시키고 객체들이 공유하는 멤버를 말함

인스턴스 멤버란 객체(인스턴스)를 생성한 후 사용할 수 있는 필드와 메소드를 말함

이들은 각각 인스턴스필드, 인스턴스 메소드라고 부름

 

인스턴스 멤버 선언

 

this

객체 외부에서 인스턴스 멤버에 접근하기 위해 참조 변수를 사용하는 것과 마찬가지로 객체 내부에

서도 인스턴스 멤버에 접근하기 위해 this를 사용할 수 있음

 

실습 예제( 선언, 호출 ) 

package sec05.exam01;

public class Car {
	//인스턴스 멤버, this
	// 최고 시속 지정
	
	private int gas;
	private int speed;
	
	void keyTurnOn() {
		System.out.println("키를 돌립니다.");
	}
	
	// 남은 가스를 체크
	boolean isLeftGas() {
		if(gas > 0) {
			return true;
		}else {
			return false;
		}
	}
	
	//달린다
	void run() {
		while (isLeftGas()) { // 참일경우 계속 반복 
			System.out.println("달립니다. (gas 잔량:" + 
								gas + "시속:" + speed + "km/h");
			if (speed <= 100) { // 최고 시속은 110이 됩니다.
				speed += 10;
			}
		 gas -= 1;
		}
		System.out.println("멈춥니다 gas 잔량: " + gas);
	}

	public int getGas() {
		return gas;
	}


	public void setGas(int gas) {
		this.gas = gas;
	//  this.인스턴스변수 = 참조변수
	}


	public int getSpeed() {
		return speed;
	}


	public void setSpeed(int speed) {
		this.speed = speed;
	//  this.인스턴스변수 = 참조변수
	}


	public static void main(String[] args) {
		// 1. 차를 만든다.( 생성 )
		Car myCar = new Car();
		
		// 2. 주유한다. ( 연료 잔량 )
		myCar.setGas(10); // 메소드 
		
		// 3. 차키를 돌린다 ( 시동 )
		myCar.keyTurnOn();
		
		// 4. 달린다.( 주유, 속도 정보 출력 )
		myCar.run();
		

	}

}

 

결과

 

 

 

 

정적 멤버와 static

정적(static)은 고정된이란 의미, 정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고

사용할 수 있는 필드와 메서드를 말함, 이들을 각각 정적필드, 정적 메소드라고 부름

 

정적 멤버 선언

정적 필드와 정적 메소드를 선언하려면 필드와 메소드 선언 시 static 키워드를 추가적으로 붙이면 됨

객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언

객체마다 가지고 있을 필요가 없는 '공용데이터'라면 정적 필드로 선언

 

 

정적 멤버 사용

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

사용 방법은 클래스 이름과 함께 도트(.) 연산자로 접근

 

실습

package sec05.exam01;

public class Calculator {
	//정적필드, 정적멤버 
	// 계산기
	
	//선언
	static double pi = 3.14159;
	
	static int plus(int x, int y) {
		return x + y;
	}
	
	static int minus(int x, int y) {
		return x - y;
	}

	public static void main(String[] args) {
		// 호출 
		double result1 = 10 * 10 * Calculator.pi;
		int result2 = Calculator.plus(10, 5);
		int result3 = Calculator.minus(10, 5);
		
		System.out.println("result1 : " + result1);
		System.out.println("result2 : " + result2);
		System.out.println("result3 : " + result3);
	}

}
결과
result1 : 314.159
result2 : 15
result3 : 5

 

 

정적 메소드 선언 시 주의할 점

객체가 없어도 실행된다는 특징 때문에 정적 메소드를 선언할 때는 이들 내부에 인스턴스 필드나

인스턴스 메소드를 사용할 수 없음, this 키워드도 사용 불가

main() 메소드도 동일한 규칙이 적용, main()메소드도 정적 메소드이므로 객체 생성 없이

인스턴스 필드와 인스턴스 메소드를 main()메소드에서 바로 사용할 수 없음

package sec05.exam01;

public class ClassName {
	 
	
	//인스턴스 변수 
	int field;
	void method1() {
	this.field = 10;
	field2 = 500;
	method2();
	}
	
	// 정적 필드, 메소드는 메모리에 할당 되있음
	// 정적 필드, 정적 메소드
	static int field2;
	static void method2() {}
	static void method3() {	
		
//	this.field = 10; // 컴파일 에러 
		
	ClassName cn = new ClassName();
	cn.field = 100;
	// 객체 생성 후 참조 변수로 접근가능
		
	field2 = 300;
	method2();
		
	}
	
}

 

 

싱글톤

 

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

단 하나만 생성된다고 해서 이객체를 싱글톤이라고 합니다.

인스턴스가 하나만 존재

한 번의 인스턴스화만 허용하고 해당 인스턴스를 전역적으로 접근

 

싱글톤을 만들기

1. 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 함 ( 생성자를 호출한 만큼 객체가 생성       되서 ) 외부에서 호출할 수 없도록 하려면 생성자 앞에 private 접근 제한자 붙여주면 됨

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

    ( 정적 필드도 private 접근 제한자를 붙여 외부에서 필드값을 변경하지 못하도록 막음 )

3. 외부에서 호출할 수 있는 정적 메소드인 getInstance()를 선언하고 정적 필드에서 참조하고 있는 자신의 

    객체를 리턴 해줌

 

외부에서 객체를 얻는 유일한 방법은 getInstance()메소드를 호출하는 방법 

getInstance() 메소드는 단 하나의 객체만 리턴하기 때문에 아래 코드에서 변수1과 변수2는 동일한 객체 참조

클래스 변수1 = 클래스.getInstance();
클래스 변수2 = 클래스.getInstance();

 

실습 1

선언

package sec05.exam01;
// 싱글톤 개념
public class Aaa {
	// 정적 필드
	private static Aaa a1 = new Aaa();//자기 자신을 초기화 
	// 생성자
	private Aaa() {}
	// 정적 메소드
	static Aaa mmm() {
		return a1;
	}
	void test() {
		System.out.println(a1);
	}
	

}

 

호출

package sec05.exam01;
//싱글톤 개념

public class AaaEx {

	public static void main(String[] args) {
//		Aaa.a1.mmm();
		Aaa a2 = Aaa.mmm();
		a2.test();
		
		Aaa a3 = Aaa.mmm();
		a3.test();
	}

}
결과
sec05.exam01.Aaa@3b6eb2ec
sec05.exam01.Aaa@3b6eb2ec

실습 2

선언

package sec05.exam01;

public class Singleton {
	//싱글톤 선언
	
	//정적 필드
	private static Singleton singleton = new Singleton();
	
	//생성자
	private Singleton() {}
	//정적 메소드
	static Singleton getSingleton() {
		return singleton;
	}
}
호출

package sec05.exam01;

public class SingletonEx {

	public static void main(String[] args) {
		//싱글톤 호출
		
	/*	
		Singleton obj1 = new SingletonEx();
		Singleton obj2 = new SingletonEx(); */ //컴파일 에러
		
		Singleton obj1 = Singleton.getSingleton();
		Singleton obj2 = Singleton.getSingleton();
		
		if(obj1 == obj2) {
			System.out.println("같은 Singleton 객체입니다.");
		}else {
			System.out.println("다른 Singleton 객체입니다.");
		}
	}

}
결과
같은 Singleton 객체입니다.

 

 

 

final 필드와 상수

 

final 필드

final 타입 필드 [= 초기값];

final 필드는 저장된 초기값이 최종 값이므로, 수정할 수 없음

초기값을 줄 수 있는 방법은 2가지가 있음

1. 필드 선언 시에 주는 방법

2. 생성자에서 주는 방법

 

package sec05.exam01;

public class FinalTest {
	// 상수 선언
	static final int z = 23;
	
	final int x;
	final String ssn;
	
	// 생성자 자동 추가 
	public FinalTest(int x, String ssn) {
		super();
		this.x = x;
		this.ssn = ssn;
	}

	// 호출
	public static void main(String[] args) {
		FinalTest ft = new FinalTest(10, "홍");
//		ft.x = 40;
//		ft.ssn = "kim" 상수 값 변경 불가
		System.out.println(ft.ssn);
		final int y;
		y = 400;
//		y = 700; 컴파일 에러 상수 변경 불가
		System.out.println(FinalTest.z);
//		FinalTest.z = 30; 상수 변경 불가

	}

}

 

 

상수

일반적으로 불변의 값을 상수(static final)라고 부름

상수는 static이면서 final이어야 함

static final 필드는 객체마다 존재하지 않고 클래스에만 존재

한 번 초기값이 저장되면 변경할 수 없음

static final 타입 상수 = 초기값;

상수 이름은 모두 대문자로 작성하는 것이 관례

서로 다른 단어가 혼합된 이름이라면 언더바(_)로 단어들을 연결

 

 

 

패키지와 접근 제한자

패키지 선언

클래스를 작성할 때 해당 클래스가 어떤 패키지에 속할 것인지를 선언하는 것을 패키지 선언이라고 함

패키지는 클래스의 일부, 클래스만 따로 복사해서 다른 곳으로 이동하면 클래스를 사용할 수 없기 때문에

패키지 이름 규칙

1. 모두 소문자로 작성하는 것이 관례

2. java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용해서는 안됨

3. 숫자로 시작하면 안되고 특수문자는 _, $ 만 허용

 

실습

같은 패키지 A, B

A

package sec06.exam03.package1;

public class A {
//	public A(boolean b) {}
//	A(int b){}// default
//	private A(String s) {}
	
	public int field1;
	int field2;// default
	private int field3;
	
	//메소드
	public void method1() {}
	void method2() {}
	private void method3() {}
}
B

package sec06.exam03.package1;

public class B {
//	A a1 = new A(true); // public A(boolean b) {} 가능
//	A a2 = new A(1);// A(int b){}// default 가능
//	A a3 = new A("문자열"); // private A(String s) {} 불가
	
	public B() {
		A a = new A();
		a.field1 = 1;
		a.field2 = 2;
//		a.field3 = 3; // 불가 
		
		a.method1();
		a.method2();
//		a.method3(); // 불가
	}
	
}

 

다른 패키지 C

C

package sec06.exam03.package2;


import sec06.exam03.package1.A;
import sec06.exam03.package1.B;

public class C {
	B b; // import 가능
//	A a; // default로 import 불가 public으로 바꿔줘야됨
	
//	A a1 = new A(true); // public A(boolean b) {} 가능
//	A a2 = new A(1);// A(int b){}// default 불가
//	A a3 = new A("문자열"); // private A(String s) {} 불가
public C() {
	A a = new A();
	a.field1 = 1;
//	a.field2 = 2; // 불가
//	a.field3 = 3; // 불가 
	
	a.method1();
//	a.method2(); // 불가
//	a.method3(); // 불가
	
}

}

 

 

import문

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

import문으로 해당 패키지의 클래스 또는 인터페이스를 가져와 사용할 것임을 컴파일러에게 알려줘야 함

import문은 패키지 선언과 클래스 선언 사이에 작성

만약 사용하고자 하는 클래스들이 동일한 패키지 소속이라면 개별 보다는 '*'를 이용

 

 

 

접근 제한자

접근 제한자(Access modifier)는 말 그대로 접근을 제한하기 위해 사용됨

접근이란 클래스 및 인터페이스 그리고 이들이 가지고 있는 멤버의 접근을 말함

 

'프로젝트 기반 자바(JAVA) 응용 SW개발자 취업과정' 카테고리의 다른 글

2023-06-02 13일차  (0) 2023.06.02
2023-06-01 12일차  (0) 2023.06.01
2023-05-30 10일차  (0) 2023.05.30
2023-05-26 9일차  (1) 2023.05.26
2023-05-25 8일차  (0) 2023.05.25

+ Recent posts