ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL #14 -String, static
    카테고리 없음 2020. 4. 15. 11:46

     

    String은 int나 double 등등 다른 타입들과는 다르게 대문자로 시작한다. 

    이 말은 String은 다른 타입들과 다르게 클래스라는 것이다. 

    보통 클래스는 new로 생성하는데 클래스인 String은 왜 new를 쓰지 않고 단독으로 사용할까? 

    물론 클래스도 String cc = new String(); 과 같은 선언이 가능하다. 

    위와 같이 String을 선언하면 리터럴( literal )이 생성이 된다. 

    (리터럴이란 소스 코드 내에서 직접 입력된 값이라고 한다)

     

    아래의 StringMain 클래스에는 다양한 String 타입의 변수들이 있다. 

     

    String aa = "apple";

    String bb = "apple";

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

    Strign cc = new String("apple");

    String dd = new String("apple");

     

    첫번째 단의 aa와 bb는 똑같이 apple 값을 가지고 있다. 

    aa와 bb는 참조값이 같을까? 같다. 

    aa와 bb는 같은 문자열을 가지고 있을까? 그렇다. 

     

    aa와 bb는 같은 apple 값을 공유하고 있다. 

    각자 다른 apple 값의 주소를 가리키는 것이 아닌, 

    같은 힙에 같은 주소값을 가지고 apple이란 값을 공유하고 있는 꼴이다. 

     

    두번째 단의 cc와 dd는 new를 이용한 꼴로 같은 apple을 가지고 있지만 

    참조값이 다르고 문자열은 같은 형태이다. 

    이 둘은 new로 새로운 주소를 각자 만들어 가지고 있다. 

    new는 매번 새로운 주소를 생성한다. 

     

    apple과 같이 직접 입력된 값 리터럴은 같은 값을 가질 수 없고 

    같은 값을 가리킬 수 있다. 

    또한 메모리에 한 번 밖에 생성이 되지 않는다. 

    (추가 바람..)

     

    #StringBuffer 

    StrinfBuffer는 String과 다르게 편집이 가능한 문자열이다. 

    비슷한 것으로 StringBuilder가 있지만 StringBuffer가 더 자주 쓰인다고 한다. 

     

    String a = "ABC"; 를 해주고 여기에 DEF를 추가해주고 싶을 때 

    a += "DEF" 를 해준 결과 "ABCDEF"를 만들 수도 있다. 

    하지만 String은 수정을 할 수 없기 때문에 또 하나의 "ABCDEF" 라는 객체가 생성이 된 것이다. 

     

    하지만 StringBuffer는 수정이 가능해 새로운 객체를 생성하는 방식이 아닌 기존의 값을 수정하는 방식으로 원하는 값을 만들어낸다. 

    StringBuffer는 내부 버퍼(데이터를 임시로 저잘하는 메모리)에 문자열을 저장해두고 그 안에서 수정 작업이 일어나기 때문에 String과 다르게 객체를 굳이 생성하지 않아도 되는 것이다. 

     

    #Token 

    "010-123-456" 과 같은 문자열이 있고, 이것을 특수문자"-" 기준으로 나눈다고 했을 때 결과는 아래와 같다 

    "010"

    "123"

    "456"

    이 세 문자열은 토큰이라고 한다.  

    이렇게 문자열을 토큰 단위로 나누어주는 클래스가 있다. 

    바로 StringTokenizer이다.

    StringTokenizer는 아래의 메소드들을 포함한다. 

    만약 내가 "학원집PC방" 이 문자열을 각각 단어로 나누고 싶다면 

    while문을 이용해 (토큰은 index가 없기 때문에 for문이 안된다)

    먼저 토큰의 유무를 확인하고(hasMoreTokens()) 현재 위치에 토큰을 꺼내고 다음으로 이동(nextToken()) 하면 된다. 

     

    #static 

    static(정적)은 '고정된' 이라는 뜻이다. 

    정적멤버는 클래스에 고정된 멤버로 객체를 따로 생성하지 않아도 사용할 수 있다. 

    정적멤버는 객체(인스턴스)에 소속된 멤버가 아닌 클래스에 소속된 멤버이기 때문에 클래스 멤버라고도 한다. 

     

    정적필드와 메소드는 앞에 static을 붙여주고 선언해주면 된다. 

    나도 역시 그랬지만, 객체를 생성하는 일 없이 바로바로 사용할 수 있는 정적멤버가 편하기 때문에 

    계속 사용하면 안될까? 하는 생각을 할 수 있다. 

    하지만 당장 사용하지 않는 것들을 계속 대기시켜놓는 것은 메모리적으로 부담이기 때문에 

    어떤 특별한 상황을 골라서 사용해주는 것이 좋다고 한다. 

     

    그 상황에 대한 예를 보자. 

    아래의 클래스는 과일 3개에 대한 월별 합계를 나타내는 클래스이다. 

    과일 3개에 대해 1월, 2월, 3월 총 3개월에 대한 정보들을 나타낼 것인데, 

    월별 합계를 구할 것이다. 

    월별 합계의 경우엔 객체마다 가지고 있을 필요는 없는 공용 데이터로 이런 경우 정적 필드, 정적 메소드를 사용해주면 된다. 그러면 필요할 때만 불러서 사용할 수 있게 되므로 효율적이다. 

     

    아래의 코드는 합계를 구하는 calcTot() 메소드와 해당 메소드에서 사용할 합계 관련 필드들이 static 이다.

    class FruitDTO{
    	private String pum; 
    	private int jan, feb, mar;
    	private int tot; 
    	static int sumJan, sumFeb, sumMar;
    	// »ý¼ºÀÚ 
    	public FruitDTO(String pum, int jan, int feb, int mar){
    		this.pum = pum; 
    		this.jan = jan; 
    		this.feb = feb; 
    		this.mar = mar; 
    	}
    
    	public void calcTot(){
    		tot = jan + feb + mar;
    
    		sumJan += jan;
    		sumFeb += feb;
    		sumMar += mar;
    		
    	}
    
    	public void display(){
    		System.out.println("----------------------------------------");
    	
    			System.out.println(pum + "\t\t"+ jan + "\t" + feb + "\t" + mar + "\t\t"+ tot);
    		
    	
    
    	}
    
    	public static void output(){
    		System.out.println("\t\t"+sumJan + "\t" +sumFeb+"\t" +sumMar);
    	}
    	
    	
    }
    
    class FruitMain{
    	public static void main(String[] args){
    		
    		FruitDTO[] arr = {new FruitDTO("사과", 100, 80, 75),
    						new FruitDTO("딸기", 30, 25, 105),
    						new FruitDTO("포도", 25, 30, 90)};
    
    		System.out.println("PUM\t\tJAN\tFEB\tMAR\t\tTOT");
    		for(FruitDTO data : arr){
    			data.calcTot();
    			data.display();
    		}
    
    
    		System.out.println("----------------------------------------");
    		FruitDTO.output();
    	}

     

    static은 this가 없다. 그저 클래스 안에서만 존재한다. 

    만약 calcTot()에 static이 없었다면 한 객체 내에서만 계산이 이루어지고 전체 클래스에 대해서는 계산이 이뤄질 수 없었을 것이다. 

     

     

     

    댓글

Designed by Tistory.