클래스(3) : 클래스의 구성 요소 / 메서드

부트캠프(END)/Java|2022. 5. 25. 20:55

클래스의 구성 요소

1. 변수

  1.1. 공유 변수

  1.2. 인스턴스 변수

  1.3. 지역 변수

2. 메서드 ← 오늘은 여기

  2.1. 인스턴스 메서드

  2.2. 클래스 메서드(static,공유 메서드)

3. 초기화(변수)

  3.1. 생성자

  3.2. 초기화 블록

    3.2.1. 인스턴스 블록

    3.2.2. 정적(static) 블록

 

메서드?

재사용을 목적으로 특정 작업을 수행하는 명령문의 집합이다.

객체지향 프로그래밍은 객체와 객체를 상호 연결하여 구현하는 프로그래밍이다.

함수와 유사하게 어떤 값을 입력하면 해당 값으로 작업을 수행하여 결과를 반환한다.

단, 함수와 달리 메서드는 입력값이 없거나, 출력값이 없거나, 둘 다 없을 수도 있다.

 

왜 사용하는가?

1. 재사용성이 높다.

일단 한 번 메서드를 만들어 놓기만 하면 몇번이든 호출해서 사용할 수 있다.

2. 중복된 코드를 제거할 수 있다.

또한 기능별로 분리가 가능하여 유지보수(수정 및 추가)가 용이하다.

(ex) 특정 기능에서 오류가 날 경우 모든 코드를 확인할 필요 없이 해당 기능을 구현하는 메서드만 보면 됨

3. 구조적인 프로그래밍이 가능하여 가독성이 향상된다.

 

메서드의 선언과 구현

반환타입 메서드이름(타입 변수명, 타입 변수명, ...매개변수...) {
    //메서드 호출시 수행할 코드
    return 결과값; //메서드 종료. 반환타입이 void일 때 생략 가능
}

반환타입

사용자가 요청한 결과값을 어떤 타입으로 받을 지 결정한다. 하나만!

매개변수

메서드가 작업을 수행하는 데 필요한 값들을 제공받기 위한 것.

클래스와 클래스를 연결하는 도구로 사용된다. 

여러개 사용이 가능하지만, 3개 이상이면.. 웬만하면 배열이나 클래스를 사용하는 것이 좋다.

가변형 매개변수도 있음. 보내주는 데이터가 확실하지 않은 경우 주로 사용한다. (ex) int... arg

메서드는 호출 시 블럭의 시작부터 끝까지 무조건 수행한 후 호출한 위치로 돌아간다.

 

메서드의 유형

1. 인스턴스 메서드

인스턴스 변수와 관련된 작업을 한다.

다시말해, 메서드를 수행하기 위해 인스턴스 변수가 필요한 메서드이다.

인스턴스 변수가 필요하다 = 인스턴스가 선언되지 않으면 인스턴스 메서드도 사용할 수 없다.

2. 클래스 메서드(static)

인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드이다.

멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 주로 사용하며, 인스턴스를 생성하지 않아도 사용할 수 있다.

메서드 내에서 인스턴스 변수를 사용하지 않는 경우 static을 붙이는 것을 고려해야 한다.

 

 

클래스의 종류

데이터형 클래스 (변수만 가지고 있는 클래스)

사용자 정의 데이터형, 관련된 데이터를 모아서 관리할 목적으로 만듬 (읽기/쓰기)

메모리에 데이터를 저장하고, 저장된 데이터를 읽는 데 사용한다.

~VO, ~DTO(데이터를 모아서 브라우저로 한번에 전송) 등

액션 클래스 (메서드만 가지고 있는 클래스)

기능만 처리

~DAO(데이터베이스 연결), ~Manager(크롤링, 파일 읽기) 등

혼합 클래스

데이터형 클래스 + 액션 클래스

 

실습(계산기 만들기)

package day18;

import java.util.*;

class Calc {
    int add(int a, int b) {
        System.out.println("this:" + this);
        return a + b;
    }
    int sub(int a, int b) {
        System.out.println("this:" + this);
        return a - b;
    }
    int multiply(int a, int b) {
        System.out.println("this:" + this);
        return a * b;
    }
    String div(int a, int b) {
        System.out.println("this:" + this);
        String result = "";
        if (b == 0) {
            result = "0으로 나눌 수 없습니다.";
        } else {
            result = a + "/" + b + "=" + (a / (double) b);
        }
        return result;
    }
    void equals() {
        System.out.println("this:" + this);
        Scanner scan = new Scanner(System.in);
        System.out.print("첫 번째 정수 입력:");
        int a = scan.nextInt();
        System.out.print("두 번째 정수 입력:");
        int b = scan.nextInt();

        System.out.print("연산자 입력!:");
        String strOp = scan.next();

        char op = strOp.charAt(0);

        if (op == '+')
            System.out.printf("%d+%d=%d", a, b, add(a, b));
        //메서드 안에서 메서드를 호출할 수 있는데,
        //같은 클래스 안에서는 객체명 없이 메서드 그냥 호출할 수 있다. 
        else if (op == '-')
            System.out.printf("%d-%d=%d", a, b, sub(a, b));
        else if (op == '*')
            System.out.printf("%d*%d=%d", a, b, multiply(a, b));
        else if (op == '/') {
            String result = div(a, b);
            System.out.println(result); //이렇게 해도 되고
            System.out.printf("%s\n", div(a, b)); //이렇게 해도 된다.
            //%d(정수), %f(실수), %s(문자열), %c(문자)
        } else
            System.out.println("잘못된 연산자입니다.");
        //멤버-> 인스턴스변수, 인스턴스 메서드. 
        //클래스 내에서는 마음대로 끌어다 쓸 수 있음.
        //static은 멤버가 아닙.. 공유하는 내용이라...
    }
}

public class Ex2 {

    public static void main(String[] args) {
        //Calc 클래스를 호출하기 전에 아직 Calc의 메서드는 저장이 되지 않았음.
        Calc calc1 = new Calc(); //이제 Calc의 메서드를 사용할 수 있다.
        System.out.println(calc1);
        calc1.equals(); //인스턴스 메서드 호출

        Calc calc2 = new Calc();
        System.out.println(calc2);
        calc2.equals();
    }

}

인스턴스 메서드와 static 메서드의 작성방법은 동일하다.
new를 사용해서 생성시에는 메서드가 따로 저장된다.
주의1. 인스턴스 메서드는 호출시에 반드시 객체명을 표기해 주어야 한다.
주의2. 메서드는 같은 클래스 안에서는 객체명 표기 없이 사용할 수 있다. 

→ 클래스 영역 안에는 this라는 "자신의 객체"를 갖고 있기 때문입니다~
→ 같은 클래스 영역 안에서는 생략이 가능하기 때문에 객체명 표기 없이 사용할 수 있는 것처럼 보이는 것.

 

실습(영화 검색 프로그램 만들기)

Movie.java - 데이터형 클래스

package day18;

public class Movie {
	int mno; //영화 번호 
	String title; //영화 제목
	String genre; //장르 
	String poster; //포스터 이미지 링크
	String actor; //출연진 
	String grade; //관람등급
	String regDate; //개봉일
	String director; //감독

}

MovieManager.java - 액션형 클래스

package day18;
import java.io.*;
import java.util.StringTokenizer;
//선생님이 만들어 주신 파일
public class MovieManager {
    static Movie[] movie=new Movie[1938];
    static 
    {
    	try
        {
        	FileReader fr=new FileReader("/Users/Downloads/데이터모음/movie.txt");
        	StringBuffer sb=new StringBuffer();
        	int i=0;
        	while((i=fr.read())!=-1)
        	{
        		
        		sb.append((char)i);
        	}
        	//System.out.println(sb.toString());
        	
        	String[] mo=sb.toString().split("\n");
        	int k=0;

        	for(String s:mo)
        	{
        		StringTokenizer st=new StringTokenizer(s,"|");
        		movie[k]=new Movie();
        		movie[k].mno=Integer.parseInt(st.nextToken());
        		movie[k].title=st.nextToken();
        		movie[k].genre=st.nextToken();
        		movie[k].poster=st.nextToken();
        		movie[k].actor=st.nextToken();
        		movie[k].regDate=st.nextToken();
        		movie[k].grade=st.nextToken();
        		movie[k].director=st.nextToken();
        		k++;
        	}
        }catch(Exception ex){}
    }
}

MovieMain.java

package day18;

import java.util.*;

class NaverMovie {
    int menu() {
        System.out.println("====Movie MENU====");
        System.out.println("1.Movie List");
        System.out.println("2.View Detail");
        System.out.println("3.Search by Titles");
        System.out.println("9.Close");
        System.out.println("==================");

        Scanner scan = new Scanner(System.in); //System.in은 static 메서드
        System.out.print("Select menu:");
        int m = scan.nextInt(); //인스턴스 메서드임
        return m;
    }
    //목록->페이지나누기
    Movie[] movieList(int page) {
        //목록을 void가 아니라 return으로 넘겨주게 되면 
    	//단점 : 배열개수를 어떻게 잡을 지 고민해야함.
        //-> 컬렉션을 사용하는것임. 11장에 나옴.
        Movie[] movies = new Movie[10];
        int pageCnt = (page * 10) - 10;
        
        int k = 0; //pagination을 위한 변수
        for (int i = pageCnt; i < pageCnt + 10; i++) {
        	if(page==194&&k>7) {
        		break; //예외처리! 마지막 번호가 1938번이기 때문에...
        	}
            Movie m = new Movie();
            m.title = MovieManager.movie[i].title;
            m.mno = MovieManager.movie[i].mno;
            movies[k] = m;
            k++;
        }
        return movies;
    }
    
    //상세보기
    Movie viewDetail(int mno) {
    	Movie m = MovieManager.movie[mno-1];
    	return m;
    }
    
    //영화명으로 찾기
    void searchTitle(String t) {
    	//찾기의 경우 결과가 몇 개일지 예상할 수 없으므로...
    	//배열로 리턴하기보단 void로 출력해준다.
    	for(Movie m:MovieManager.movie) {
    		if(m.title.contains(t))
    			System.out.println(m.mno+"."+m.title);
    	}
    }

    void process() {
        while (true) {
            int m = menu();
            int maxPage = (int)(Math.ceil(MovieManager.movie.length/10.0));
            
            if (m == 9) {
                System.out.println("Program closed.");
                break;
            }
            else if (m == 1) {
                Scanner scan = new Scanner(System.in);
                System.out.print("insert page(1~"+maxPage+"):");
                int page = scan.nextInt();
                Movie[] movie = movieList(page);
                for (Movie mm: movie) {
                	if(mm!=null) {
                		System.out.println(mm.mno + "." + mm.title);
                    }
                }
            }
            else if (m == 2){
            	Scanner scan = new Scanner(System.in);
            	System.out.println("insert movieNo(1~1938):");
            	int mno = scan.nextInt();
            	Movie movieDetail = viewDetail(mno);
            	System.out.println("----------Detail----------");
            	System.out.println("title:"+movieDetail.title);
            	System.out.println("grade:"+movieDetail.grade);
            	System.out.println("director:"+movieDetail.director);
            	System.out.println("actors:"+movieDetail.actor);
            	System.out.println("genre:"+movieDetail.genre);
            	System.out.println("--------------------------");
            }
            else if (m == 3) {
            	Scanner scan = new Scanner(System.in);
            	System.out.print("insert keyword:");
            	String key = scan.next();
            	searchTitle(key);
            }
        }
    }
}
public class MovieMain {

    public static void main(String[] args) {
        NaverMovie n = new NaverMovie();
        n.process();
    }

}

 

예외처리하기(중요)

package day18;

class X {
	int x;
}
public class MainClass {

	public static void main(String[] args) {
		X[] xList = new X[10];
		for(int i=0; i<8; i++) {
			X xx = new X();
			xx.x = i+1;
			xList[i] = xx; 
			//xList[i] = new X(); 
			//xList[i].x = i+1; 이렇게해도됨
		}
		
		for(X xx:xList) {
			if(xx!=null) //예외처리부분
				System.out.println(xx.x);
		}
	}

}

클래스 배열에서 값이 배열 길이만큼 끝까지 데이터가 채워지지 않은 경우,

그대로 출력하게 되면 아래와 같은 에러가 발생한다.

Exception in thread "main" java.lang.NullPointerException: Cannot read field "x" because "xx" is null

at day18.MainClass.main(MainClass.java:20)

이 때,, null값이면 출력하지 않도록 if(xx!=null)과 같이 예외처리를 해 주면 에러가 발생하지 않는다!

댓글()