딸기말차

[Java] 2. split, substring, 클래스, 메서드 본문

Bootcamp/Java

[Java] 2. split, substring, 클래스, 메서드

딸기말차 2023. 6. 25. 01:49

엔코아 플레이데이터(Encore Playdata) Backend 2기 백엔드 개발 부트캠프 (playdata.io)

 

백엔드 개발 부트캠프

백엔드 기초부터 배포까지! 매력있는 백엔드 개발자 포트폴리오를 완성하여 취업하세요.

playdata.io


1. 복습

수업을 시작하기 전 앞서 변수, 배열에 대한 복습을 진행하며 변수의 scope에 관한 내용도 설명해 주셨다.

/*
 * 데이터타입 종류
 * 1. 숫자형 : 정수, 실수 (int, float) -> 4byte
 * 2. 논리형 : boolean (true, false)
 * 3. 문자형 : char (사실 유니코드 값, int에 대입이 가능함) -> 2byte
 * 4. 문자열 : String
 * 
 * 소문자 데이터타입 : 기본 데이터타입
 * 대문자 데이터타입 : String.class라는 클래스가 존재하는 타입. 클래스기에 다양한 메서드를 가지고있다.
 */
 
 /*
 * 배열 선언
 * 1. 데이터타입[] 배열명;
 * 2. 데이터타입[] 배열명 = new 데이터타입[갯수]
 * 3. 데이터타입[] 배열명 = {}
 * new : 생성키워드, 생성 후 앞의 변수명에 저장 됨
 */
 
 /*
 * 클래스 내부 선언 변수 : 전역(필드, 속성, global) 변수
 * 클래스 내부 생성자 or 메서드에 선언된 변수 : 지역(local) 변수
 * method 앞에 get : 값을 추출 / method 앞에 set : 값을 설정
 * 
 * 나머지연산 : 특정 값을 3으로 나머지연산 한다 가정하면, 나머지는 0, 1, 2 중 하나로 결정. 개수 제한을 걸 수 있음
 * 비트연산 : 속도 가장 빠름
 */

복습한 내용을 바탕으로, 반복 및 조건문을 사용한 간단한 실습예제를 진행하였다.

평균나이와 평균급여를 구하면 되는 문제였지만, 변수의 형변환을 해주는 (float) 부분이 java 1.8에선 double로 작성해야 동작한다는 것을 알게 되었다.

java가 최근엔 20까지 버전이 업그레이드 되었는데 실제 업무에선 호환 문제때문에 아직도 1.8이나 11 버전을 사용하는 회사가 많기에, 반드시 기억해두면 좋을 것 같았다.

int[] age = {27, 34, 28, 26, 41, 28, 42, 29, 29, 32};
String[] name = {"PJH","JDW","AJH","HST","HTW","LWS","LSD","YJH","JSW","LKO"};
String[] phone = {"010-8532-0537","010-9672-5257","010-9932-4536","010-4117-0975","011-8975-7892","010-6251-6976","010-9482-6059","010-4845-0105","010-6283-4849","010-4510-1609"};
char[] gender = {'F','M','F','M','M','F','M','M','F','M'};
int[] pay = {460, 200, 250, 300, 300, 200, 350, 200, 400, 440};
String[] code = {"JP", "FR", "JP", "US", "CN", "DE", "KR", "JP", "DE","KR"};

// 참고 : Java 1.8에선 float 부분을 double로 써야 동작함
// 남자 사원의 평균 나이 구하기
int sumAge = 0;
int male = 0;
for (int i = 0; i < age.length; i++) {
    if (gender[i] == 'M') {
        sumAge += age[i];
        male++;
    }
}
System.out.println("남자 사원의 평균 나이: " + (float)sumAge / male);

// 여자 사원의 평균 급여 구하기
int sumPay = 0;
int female = 0;
for (int i = 0; i < pay.length; i++) {
    if (gender[i] == 'F') {
        sumPay += pay[i];
        female++;
    }
}
System.out.println("여자 사원의 평균 급여: " + (float)sumPay / female);

2.  Split (문자열 쪼개기)

java 문법의 split에 관한 설명 및 테스트로, split을 하기위해선 인자로 어떤 문자를 넣을지 항상 잘 골라야한다.

또한, 강사님께서 현업에서는 테스트를 위한 출력 문구를 데이터를 관리하는 반복문 내에 사용하지 않는다고 하셨다. 이를 토대로 항상 출력은 따로 빼서 테스트를 해보는 습관을 들여야겠다 생각했다.

/*
 * split : 문자열 쪼개기
 * split 앞엔 항상 문자열이 와야함
 * split의 인자로 사용할 문자를 잘고르고, 저장은 String[]로
 */

// 3. 일본에 근무하는 사람들의 이름과 연락처 출력하기 (이름, 연락처)
// answer1
String inputCode = "JP";
String names = "";
String phones = "";
String[] splitNames;
String[] splitPhones;

for (int i = 0; i < code.length; i++) {
    if (code[i] == inputCode) {
        names += (name[i] + " ");
        phones += (phone[i] + " ");
    }
}
splitNames = names.split(" ");
splitPhones = phones.split(" ");

// 항상 출력은 분리해서 쓰는 습관
for (int i = 0; i < splitNames.length; i++)
    System.out.println("일본에 근무하는 사람들의 이름, 연락처: " + splitNames[i] + ", " + splitPhones[i]);

위의 풀이는 String 변수 하나에 공백을 포함해 데이터를 다 저장 후, split을 통해 쪼개는 방식으로 해결하고 있다.

하지만 너무 많은 변수를 사용하고 있기 때문에, ArrayList를 이용해 원하는 데이터를 저장 후 split하여 출력하면 어떨까 하는 생각이 들어 추가로 풀어보았다.

// answer2
ArrayList<String> nameCall = new ArrayList<String>();
for (int i = 0; i < code.length; i++)
    if (code[i] == "JP")
        nameCall.add(name[i] + " " + phone[i]);

for (int i = 0; i < nameCall.size(); i++) {
    String[] tmp = nameCall.get(i).split(" ");
    System.out.println("일본에 근무하는 사람들의 이름, 연락처: " + tmp[0] + ", " + tmp[1]);

3. Substring (문자열 자르기)

원하는 부분의 문자열을 잘라낼 때 사용하는 메서드인 substring에 관한 설명 및 테스트이다.

substring의 인자는 endIndex가 헷갈리기 쉽기 때문에, 내가 원하는 도착지점의 index + 1 이라 생각하면 편할 것 같았다.

String test = "임재,20190509,20190510,8,남,30대후반";
String[] splits = test.split(",");

String date1 = splits[1];
System.out.println(date1);

/*
 * 만약 연도를 뽑고 싶다면? 0 ~ 3까지, '4 이전까지' 뽑아야함
 * 시작~ 끝까지 substring하고 싶으면 시작 index만 적으면된다.
 * String.substring(startIndex, endIndex)
 * String.substring(startIndex)
 */

String year = date1.substring(0, 4);
System.out.println(year);

String month = date1.substring(4, 6);
System.out.println(month);

String day = date1.substring(6);
System.out.println(day);

String name = splits[0];

코딩을 하다보면 잘라낸 문자열을 형변환 하고 싶은 경우가 반드시 생긴다.

대부분 문자열로 구성 된 숫자를 정수형으로 변환하고 싶은 경우인데, 이런 경우 Integer.parseInt()를 사용하면 된다.

반대로, 숫자를 문자열로 바꾸고 싶은 경우엔 String.valueof() 를 사용하면 된다.

// 문자열 형태의 숫자는 (int) 처럼 강제로 형변환을 할 수 없다.
// 외부에서 입력받은 모든 숫자는 내부에서 문자열로 전달되기 때문에 반드시 Integer.parseInt()를 이용해 숫자로 변환시켜야 한다.
// 팁 : 숫자를 문자열로 바꿀 땐 String.valueof() 를 사용하면된다.
int age = Integer.parseInt(splits[5].substring(0, 2));

4. 클래스

java 클래스에 관한 설명 및 테스트이다. 여러 클래스를 다루다보면 상속 등 분명 헷갈리는 상황이 발생할 수 있기 때문에 객체지향 프로그래밍을 하기위해선 반드시 알아야되는 개념이라 생각한다.

/*
 * main이 없는 클래스는 내부에 생성자가 필요하다.
 * 생성자 : 다른 클래스가 현 클래스를 객체로 만들 때 자동으로 호출되는 메서드(함수)
 * 일반클래스 : main이 없는 클래스, 클래스 파일로는 아무 작업도 하지 못하고, 반드시 객체화 되어야만 일을 할 수 있다.
 * 일반클래스를 객체화 시키기는 방법 : new 클래스명()
 * 클래스 자신의 데이터는 this를 붙여서 사용. 탐색시간이 줄어든다.
 */
public class EMPClass {
	String name;          // 이름
	String joinDate;      // 가입일
	String lastVisitDate; // 최종방문일
	int numVisit;         // 방문횟수
	String gender;        // 성별
	String age;           // 연령대
	
	// 기본 생성자
	public EMPClass() {
		
	}
	
	// 기본 생성자에 대한 파생 생성자 : Overloading
	public EMPClass(String data) {
		String[] splits = data.split(",");
		this.name = splits[0];
		this.joinDate = splits[1];
		this.lastVisitDate = splits[2];
		this.numVisit = Integer.parseInt(splits[3]);
		this.gender = splits[4];
		this.age = splits[5];
	}
}

위 처럼 만든 클래스를 사용하기 위해선 main 메서드 내에서 객체를 만들어 사용해야한다.

EMPClass empClass1 = new EMPClass();
empClass1.name = "test";

EMPClass empClass2 = new EMPClass();
empClass2.name = "sample";

System.out.println(empClass1.name);
System.out.println(empClass2.name);

EMPClass empClass3 = new EMPClass("임재,20190509,20190510,8,남,30대후반");
EMPClass empClass4 = new EMPClass("성열,20190509,20190510,1,남,30대중반");
System.out.println(empClass3.age);
System.out.println(empClass4.age);

또한, 클래스는 자기자신 뿐만아니라 부모타입으로도 생성할 수 있다. 하지만 자식클래스에서 만든 내용을 사용할 수 없다는 단점이 있다.

/*
 * 하나의 클래스는 자기자신 뿐만아니라 부모타입으로도 생성할 수 있다.
 * 하지만 자식 클래스에서 만든 내용은 사용할 수 없다. ex) 조선시대는 비행기를 모른다.
 */
Object empObject = new EMPClass(test);

메인 메서드에서 new 키워드를 통해 클래스 객체를 생성하고, 생성자를 통해 데이터를 저장할 수 있다. 그럼 여러 데이터를 저장하고 싶으면 어떻게하면 될까?

String[] members = new String[3];
members[0] = "임재,20190509,20190510,8,남,30대후반";
members[1] = "성열,20190509,20190510,1,남,30대중반";
members[2] = "재희,20190426,20190426,2,여,40대후반";

int number = members.length;
EMPClass[] empClasses = new EMPClass[number];
for (int i = 0; i < number; i++)
    empClasses[i] = new EMPClass(members[i]);

for (int i = 0; i < number; i++)
    // 배열의 index를 초과하면 null값을 보냄 -> NullPointerException
    System.out.println(empClasses[i].name);

위 코드들은 메인 메서드가 존재하는 클래스와, 메인 메서드가 없는 클래스 간의 상호작용이라 볼 수 있다. 이 둘의 실행 과정이 어떻게 되는지 정리하면 다음과 같다.

/*
 * 1. EMPClass.class 파일 검색 -> EMPClass
 * 2. EMPClass.class 파일 내부 선언 -> EMPClass
 * 3. EMPClass.class 파일 내부에서 EMPClass 이름과 동일한 생성자 호출 -> EMPClass()
 * 4. 생성자를 이용하여 EMPClass 객체 생성 -> new EMPClass()
 * 5. 생성된 객체를 변수(객체명)에 저장 -> EMPClass empClass = new EMPClass()
 */

이 후 간단한 실습으로 회원의 성비 및 남여 비율을 구하는 문제를 내주셨다. 일반적인 for문을 사용해 해결해도 되지만, java엔 for-each라는 전체를 참조할 때 유용한 문법이 존재한다. 이를 사용해 해결해 보았다.

// 회원의 성비를 구하시오
int male = 0;
int female = 0;
for (EMPClass empClass : empClasses) {
    if (empClass.gender.equals("남"))
        male++;
    else
        female++;	
}
System.out.println("남:여 = " + male + ":" + female);

// 남여 각각의 비율
System.out.println("남자 비율: " + (float)male / empClasses.length);
System.out.println("여자 비율: " + (float)female / empClasses.length);

5. 메서드

아직 메서드에 관한 자세한 실습은 진행하지 않았지만, 강사님께서 미리 설명해주신 내용을 정리해보았다.

/*
 * 메서드
 * 1. 선언위치 : 클래스 내부
 * 2. 선언방법
 *  1) public 반환타입 매서드명() { 로직 }
 *  2) public 반환타입 매서드명() { 로직, 반환값 }
 *  3) public 반환타입 매서드명(파라미터) { 로직 }
 *  4) public 반환타입 매서드명(파라미터) { 로직, 반환값 }
 */

일반적으로 클래스 내부의 변수에 초기화를 할 때 생성자를 이용하지만, 초기화할 변수가 너무많거나 초기화 과정에서 여러 로직이 들어갈 경우, 생성자가 하는 일이 너무 많아져 메서드를 이용해 분리하여 처리하곤 한다.

public class EMPClass {
	String name;          // 이름
	String joinDate;      // 가입일
	String lastVisitDate; // 최종방문일
	int numVisit;         // 방문횟수
	String gender;        // 성별
	String age;           // 연령대
	
	// 기본 생성자
	public EMPClass() {
		
	}
	
	// 기본 생성자에 대한 파생 생성자 : Overloading
	public EMPClass(String data) {
		this.setSplit(data);
	}
	
	// 문자열을 각각 분리하여 전역변수에 설정하는 메서드 -> 생성자의 하는일을 줄여줄 수 있다.
	public void setSplit(String data) {
		String[] splits = data.split(",");
		this.name = splits[0];
		this.joinDate = splits[1];
		this.lastVisitDate = splits[2];
		this.numVisit = Integer.parseInt(splits[3]);
		this.gender = splits[4];
		this.age = splits[5];
	}
}

메서드를 생성하는데는 여러 방식이 있지만, 그 중 반드시 알아야되는 두가지 방식이 있다.

메서드 오버로딩메서드 오버라이딩인데, 이 둘의 특징을 사용하여 Java라는 언어가 구성되어 있는 것이나 마찬가지기 때문에, 꼭 알아둬야 한다고 생각한다.

/*
 * Overloading : 한 클래스내에서 이미 같은이름을 가진 메소드가 있더라도 같은 이름으로 정의할 수 있는 것
 * 1. 메소드명은 동일해야한다.
 * 2. 매개변수의 개수가 틀리거나, 데이터 타입이 달라야한다.
 * ex) println
 * 
 * Overriding : 부모클래스에서 상속받은 메소드를 자식클래스에서 재정의하는 것
 * 1. 메소드명, 매개변수, 리턴값이 모두 동일해야한다.
 * 2. 내부의 로직은 달라도된다.
 */

6. 2일차 후기

오늘 진행한 내용은 앞으로 개발을 함에 있어서 반드시 숙지해야되는 개념이라고 생각한다. 우리는 한 프로젝트 내의 수많은 클래스를 관리해야하고, 에러가 발생하지 않게 구성해야 하기 때문이다.

 

또한, 메서드 오버로딩과 오버라이딩같이 굉장히 중요하고 면접에서도 자주나오는 용어들은 꼭 이해하고 암기해야 한다고 생각한다. 강사님께서 판매하는 IT 용어집이 있다고 소개해 주셨는데, 구매하여 지하철을 오고가는 시간이나 여유시간에 한번씩 보면 굉장히 큰 도움이 될 것 같다.