day 10 - static 클래스, 싱글턴 객체, String의 비교법

2022-03-15
클래스에는 2가지 유형의 메서드를 사용할 수 있는데 instance 메서드와 static 메서드가 그것이다.

객체의 다른 표현 - instance

인스턴스 메서드는 무조건 1개씩만 생성할 수 있다. (Instance ins = new Instance();)

static 변수 - 정적변수, class 변수

동적 변수는 호출 명령을 만나야 만들어지지만

static 변수는 프로그램 시작과 동시에 만들어져있다.

따라서 다른 클래스 내에서도 객체를 생성하지 않고도 사용할 수 있다.

파일1
public static double rate; // 프로그램 시작 시 생성되는 정적변수
파일2
Save.rate = 0.1;

static 초기화

// 초기화
static {
System.out.println("0.무슨소리고");
}

public static void main(String[] args) {
System.out.println("1.내가 제일 먼저 수행됨");
  1. 이 시작되기 전에 static 에서 사전에 실행되도록 할 수 있다.

먼저 메모리에 준비가 되도록 한 뒤 본격적으로 프로그램을 시작하게 할 수 있게 된다.

Database driver load 작업 혹은 각종 Resource (image, sound...)

스태틱 초기화 창에 있는 요소가 먼저 메모리에 준비되기 때문에 프로그램 실행시 유용하다.

Design pattern

과거 개발방법론을 최적화 시켜놓은 이론

  1. Single-ton Pattern

매번 요청이 들어가더라도 1회만 호출하고 이후부터는 기존에 생성된 객체정보를 활용하는 방식

메모리 낭비를 방지할 수 있다.

static MySingleTon single = null;

이렇게 MySingleTon이라는 스태틱 객체를 만들고난 뒤

public statiac MySingleTon getInstance() {

		if single == null
		single = new MySingleTon();
		return single;
}

getInstance 메서드를 만들어주면 MySingleTon은 getInstance 메서드를 통해서 한번만 호출되기 때문에 메모리 낭비를 방지할 수 있다.

대표적인 싱글톤 객체로는 현재시간을 전달해주는 API Calendar 가 있다.

싱글톤 패턴으로 만들어진 객체는 1회만 만들어지기 때문에 getInstance(); 라는 메서드를 사용하여 불러오는 방식으로 사용할 수 있다.

--

자판기를 만드는 실습을 했다.

  • 유틸
// drink 단가 상수선언	
public static final int COLA = 500;
public static final int CIDER = 600;
public static final int JUICE = 800;
public static final int MILK = 400;

//drink 종류별 상수선언
public static final int DRINK_COLA = 1;
public static final int DRINK_CIDER = 2;
public static final int DRINK_JUICE = 3;
public static final int DRINK_MILK = 4;

int money; //받은금액
int drink; //선택음료

public void insertCoin(int money) {
this.money = money;
}
public void selectDrink(int drink) {
this.drink = drink;
}

public void displayResult() {
int price = 0;
if (money>=COLA||money>=CIDER||money>=JUICE|| money>= MILK) {

if(drink == DRINK_COLA) {
	price = COLA;
	System.out.printf("받은금액: %d 선택음료: 콜라(%d), 거스름돈 %d",money,COLA,(money-COLA));
} else if (drink == DRINK_CIDER) {
	price = CIDER;
	System.out.printf("받은금액: %d 선택음료: 사이다(%d), 거스름돈 %d",money,CIDER,(money-CIDER));
} else if (drink == DRINK_JUICE) {
	price = JUICE;
	System.out.printf("받은금액: %d 선택음료: 쥬스(%d), 거스름돈 %d",money,JUICE,(money-JUICE));
} else if (drink == DRINK_MILK) {
	price = MILK;
	System.out.printf("받은금액: %d 선택음료: 우유(%d), 거스름돈 %d",money,MILK,(money-MILK));
}
} else {
	System.out.print("잔액이 부족합니다.");
}

우선 상수를 설정하고 변수명을 설정했다.

그다음 void 메서드 2개를 만들고 변수명이 메서드(괄호 안)에 들어가도록 한 뒤 this메서드로 호출했다.

void display 메서드안에 if문으로 출력문구를 만들었다. 만약 money 값이 음료보다 크다면 drink의 값이 각각의 음료의 값과 같을 때 각각의 문장을 출력하도록 구문을 만들었다.

  • 메인클래스
	public static void main(String[] args) {
	int money;
	int drink;
	Scanner scanner = new Scanner([System.in](http://system.in/));
	VendingMachineUtil vendingmachine = new VendingMachineUtil();

	String y;
	do{
	System.out.print("금액: ");
	money = scanner.nextInt();
	System.out.print("음료선택(1.콜라 2.사이다 3.쥬스 4.우유): ");
	drink = scanner.nextInt();

	vendingmachine.insertCoin(money);
	vendingmachine.selectDrink(drink);

	vendingmachine.displayResult();

	System.out.println();
	System.out.print("다시하기? y/n ");
	y = scanner.next();
	}while (y.equalsIgnoreCase("y"));

	scanner.close();

값을 받기위한 int 값 2개를 설정하고 금액과 음료를 선택할 수 있게 설정했다.

자판기 유틸 클래스를 호출해주고

유틸객체.get메서드(입력된 값) 으로 유틸 속 메서드 안의 int 값에 입력된 값을 전달해주었다.

do while문으로 반복해서 금액과 음료를 선택할 수 있도록 만들었다.

String 의 비교법

	// 암시적 방식
	String s1 = "Twinkle";
	String s2 = "Twinkle";
	if(s1 == s2)
		System.out.println("Same");
	else
		System.out.println("Different");

->> same

암시적 방식으로 비교한다면 “twinkle” 이라는 값이 속한 주소의 값을 비교하게 되기 때문에 결과 값이 Same 으로 나오게 되지만 new를 이용해 값마다 주소를 지정해주게 된다면 주소값을 비교하기 때문에 Different 값이 출력된다.

// 명시적 방식	
	String s3 = new String("Little Star");
	String s4 = new String("Little Star");

	if(s3 == s4)
		System.out.println("Same");
	else
		System.out.println("Different");

->> different

이렇게 결과값이 일정하지 않게 나오는 상황을 방지하기 위해서 String 값을 비교할 때에는 .equals 라는 메서드를 사용하여 항상 같은 답이 나올수 있도록 유도한다.

String 추가시 메모리 낭비를 방지하는법

	String msg = ++count + "little," + ++count + "little," + ++count + "little";
	System.out.println(msg);
	System.out.println(msg.length());

String은 한번 + 로 추가를 할때마다 추가된 스트링 객체가 만들어진 뒤 GC에 의해 버려지는 행동을 반복하게 된다. 따라서 String을 + 로 늘릴때마다 새로운 스트링이 만들어지기 때문에 위의 코딩에서는 한번 연산에 2개의 버려지는 String이 생기게 된다. 만약 이게 2개가 아닌 10000개라 하고, 이런 연산을 서버에 접속하는 수많은 사람들이 전부 시도하게 된다면 결국 과한 메모리 낭비를 유발하게된다.

이를 위한 해결방식을 몇가지 배워보았다.

StringBuffer

StringBuffer 메서드를 불러온 뒤 append 를 이용해 String을 추가한다.

	StringBuffer sb = new StringBuffer(40); 
	// StringBuffer 에 40개 문자를 넣을 수 있는 공간확보
	count = 0;

	sb.append(++count);
	sb.append("little ");
	sb.append(++count);
	sb.append("little ");

	String msg1 = sb.toString(); 
// StringBuffer -> String 추출하기

	System.out.println(msg1);

Formatter

Formatter는 StringBuffer와 다르게 static 메서드이기 때문에 객체를 생성하지 않고도 바로 이용할 수 있다. 따라서 메모리 연산도 줄일 수 있고 StringBuffer보다 간결한 코드를 만들수도 있다.

JDK 5.0부터 지원된 기능이다.

count = 0;
		
		String msg2 = String.format("%d little, %d little, %dlittle", ++count, ++count, ++count);
		System.out.println(msg2);

좋은 웹페이지 즐겨찾기