본문 바로가기

Java

Day 4. 과제

정적 멤버와 static?

정적(static)은 '고정된'이란 의미를 가지고 있다. 정적 멤버는 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메소드를 말한다. 이들을 각각 정적 필드 , 정적 메소드라고 한다. 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다. 정적 필드와 정적 메소드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스(바이트 코드)를 로딩해서 메소드 메모리 영역에 적재할 때 클래스 별로 관리된다. 따라서 클래스이 로딩이 끝나면 바로 사용할 수 있다.  필드를 선언할 때 인스턴스 필드로 선언할 것인가, 아니면 정적 필드로 선언할 것인가의 판단 기준은 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언하고, 객체마다 가지고 있을 필요성이 없는 공용적인 데이터 라면 정적 필드로 선언하는 것이 좋다. 예를 들어 계산기를 만드는 클래스에서 원의 넓이나 둘레를 구할 때 필요한 파이π는 계산기 객체마다 가지고 있을 필요가 없는 변하지 않는 공용적인 데이터 이므로 정적 필드로 선언하는 것이 좋다. 만일 계산기 마다 색이 다르다면 색은 인스턴스 필드로 선언해야 한다. 

public class Calculater{     String color;

static double pi = 3.14159; }

클래스가 메모리로 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트(.) 연산자로 접근한다.

클래스.필드;

클래스.메소드(매개값, ..;

public class Calculater{        static double pi = 3.14159;

static int plus(int x, int y){

return x + y;

}

static int minus(int x, int y){

return x - 7;

}

}

double result1 = 10 * 10 * Calculater.pi;

int result1 = Calculater.plus(10,3);

int result2 = Caculater.minus(10,3);

정적 필드와 정적 메소드는 원칙적으로는 클래스 이름으로 접근해야 하지만 다음과 같이 객체 잠조 변수로도 접근이 가능하다.

Calculater myCal = new Calculater();

double result1 = 10 * 10 * myCal.pi;

int result1 = myCal.plus(10,3);

int result2 = myCal.minus(10,3);


하지만 정적 요소는 클래스 이름으로 접근하는 것이 좋다. 

정적 메소드와 정적 블록을 선언할 때 주의할 점은 객체가 없어도 실행된다는 특징 때문에, 이들 내부에 인스턴스 필드나 인스턴스 메소드를 사용할 수 없다. 또한 객체 자신의 참조인 this 키워드도 사용이 불가능하다. 정적 메소드와 정적 블록에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조 변수로 접근해야한다.

static void Method(){

ClassName obj = new ClassName();

obj.field1 = 10;

obj.method();

}



싱글톤(Singleton)

전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우가 있다. 단 하나만 생성된다고 해서 이 객체를 싱글톤(Singleton)이라고 한다. 싱글톤을 만들려면 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 한다. 생성자를 호출한 만큼 객체가 생성되기 때문이다. 생성자를 외부에서 호출할 수 없도록 하려면 생성자 앞에 private 접근 제한자를 붙여주면 된다. 

public class 클래스 {

//정적 필드

private static 클래스 singleton = new 클래스();


//생성자

private 클래스() {}


//정적 메소드

static 클래스 getInstance() {

return singleton;

}


}


외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법이다. getInstance() 메소드는 단 하나의 객체만 리턴하기 때문에 변수1과 변수 2는 동일한 객체를 참조한다.

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

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


public class Singleton{

private static Singleton singleton = new Singleton();


private Singleton(){}


static Singleton getInstance(){

return singleton:

}

}

public class SingletonExample{

public static void main(String[] args) {

/*

Singleton obj1 = new Singleton(); //컴파일 에러

Singleton obj2 = new Singleton(); //컴파일 에러

*/


Singleton obj1 = Singleton.getInstance();

singleton obj2 = Singleton.getInstance();


if(obj1 == obj2){

System.out.println("같은 싱글톤 객체 입니다.");

}else {

System.out.println("다른 싱글톤 객체 입니다.");

}

}



}


Wrapper(포장) 클래스

자바는 기본 타입(byte, char, short, int, long, float, double, boolean)의 값을 갖는 객체를 생성할 수 있다. 이런 객체를 포장(Wrapper) 객체라고 하는데 그 이유는 기본 타입의 값을 내부에 두고 포장하기 때문이다. 포장 객체의 특징은 포장하고 있는 기본 타입 값은 외부에서 변경할 수 없다. 만약 내부의 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 한다. 

public class BoxingBoxingExample{

public static void main(String[] args) {

//Boxing

Integer obj1 = new Integer(100);

Integer obj2 = new Integer("200");

Integer obj3 = Integer.valueOf("300");


//unboxing

int value1 = obj1.intValue();

int value2 = obj2.intValue();

int value3 = obj3.intValue();



}


}



String 메소드

String은 문자열의 추출, 비교, 찾기, 분리, 변환 등과 같은 다양한 메소드를 가지고 있다. 


문자 추출(charAt())

매개값으로 주어진 인데스의 문자를 리턴한다. 여기서 인덱스를 0에서부터 "문자열길이-1"까지의 번호를 말한다.

public class StringCharAtExample { public static void main(String[] args){ String ssn = "010624-1230123"; char sex = ssn.charAt(7); switch(sex){ case '1': case '3': System.out.println("남자입니다."); break; case '2': case '4': System.out.println("여자입니다."); break; } } }


문자열 비교(equals())

자바는 문자열 리터럴이 동일하다면 동일한 String 객체를 참조하도록 되어 있다. 

String strVar1 = new String("서청원");

String strVar2 = "서청원";

String strVar3 = "서청원";


strVar1 == strVar2 --> false

strVar2 == strVar3 -->true


strVar1.equals(strVar2) --> true

strVar2.equasl(strVar3) --> true


(출처 - 이것이 자바다)