JAVA 복습

동제동이·2023년 3월 19일
1

JAVA

목록 보기
4/5
post-thumbnail

JAVA 객체에 대한 문제를 보면서 아직 내 것으로 만들지 못했다고 느꼈다...
똑같은 문제, 똑같은 로직인데도 코드를 짜다가 멈추고를 반복했다.

- 내가 어느 부분을 어려워 했는지
- 내가 어느 부분을 대충 넘어갔는지
위의 두 가지를 계속 생각하며 혼자 찾아보거나, 코드를 짜거나
강사님께 질문했다. 복습하면서 나중에 잊더라도 찾아보자

Overloading과 Overriding

개념을 배울 때 이해가 안되는 건 아니였지만,
막상 코드를 짜다보니 두 개념이 헷갈렸다.

Overloading

한 클래스 내에 동일한 이름의 메소드를 여러 개 작성하는 것이다.
아래의 예시 코드를 보면 나는 delete의 이름을 가진 메소드를
2개 생성했다.

	// 회원정보 하나 삭제
	public boolean delete(String id) {	
		for(int i=0; i<m.length; i++) {
			if(m[i] != null && m[i].getId().equals(id)) {
				m[i] = null;
				return true;
			}
		}
		return false;
	}
	
	// 전체회원정보 삭제
	public void delete() {
		for(int i=0; i<m.length; i++) {
			m[i] = null;
		}
	}

하지만 매개변수의 개수와 타입이 다르다면 같은 이름의 메소드를
사용할 수 있다.
(단, return 값만 다르다면 오버로드할 수 없다.)

Overriding

상속관계인 클래스에서 부모클래스에 선언된 메소드를 자식클래스가 재정의하는 것 (부모클래스에 선언된걸 자식클래스에서 덮어쓰기)

// 부모 클래스
public class OverrideParent {
	public void print() {
    	System.out.println("!이건 부모클래스 함수!");
    }
 }
// 자식 클래스
public class OverrideChild extends OverrideParent {
	@Override
    public void print() {
    	System.out.println("!이건 자식클래스 함수!");
    }
}
// 실행
OverrideParent op = new OverrideParent();
op.printMsg();			// !이건 부모클래스 함수!

OverrideChild oc = new OverrideChild();
oc.printMsg();			// !이건 자식클래스 함수!

(단, 메소드, 매개변수 개수, 매개변수 타입, 리턴 타입이 동일해야하고,
privatefinal 메소드는 오버라이딩 불가능)

Static

  • static을 이용하면 정적필드와 정적메소드를 만들 수 있다.
  • static은 클래스로 인식하기에 클래스의 로딩이 끝나는 즉시 사용할 수 있다.
    static은 힙 영역이 아닌 static 영역에 할당된다.
  • static 영역의 장점으로 여러 객체가 공유해서 접근할 수 있는 장점이 있지만
    static 영역은 GC가 관여하지 못하기에 프로그램이 종료될 때까지 메모리가 할당된 채로 존재하기에 너무 static을 많이 쓰면 시스템에 악영향을 끼칠 수 있다.

  • static을 선언한 클래스 맴버는 new로 인해 인스턴스를 생성하지 않아도 접근할 수 있다.

public class Test() {
	public void testPrint() {
    	System.out.println("생성자를 만들어야함!");
    }
    
    public static void staticTestPrint() {
    	System.out.println("생성자 안만들어도 돼!");
    }
}
public class StaticTest {
    public static void main(String[] args) {
        // static을 선언안한 경우 생성해서 사용
        Test test = new Test();
        test.testPrint();
        
        // static을 선언한 경우
        Test.staticTestPrint();
    }
}

StackOverflow

스택 영역의 메모리 크기보다 더 많이 사용할 경우 발생하는 에러로,
보통 스택 영역은 원시 타입, 또는 객체의 주소 값을 저장하는 데
GC에 의해 관리된다.

학원과제를 풀던 중 아래와 같은 코드를 작성했을 때,
왜 이런 에러가 뜨는지 몰랐다.

// 학생 화면을 담당하는 클래스
public class MainView {
	Scanner sc = new Scanner(System.in);
    StudentController controller = new StudentController();
    ...
}

// 학생 관리 프로그램의 기능을 담당하는 클래스
public class StudentController {
	MainView mv = new MainView();
    ...
}

위의 MainView와 StudentController를 보면,
new 생성자를 통해 서로를 계속 실행시켜 무한루프에 빠진다.
처음에 이해가 안가서 그림을 그리고 보니 이해가 갔다.
(아래 그림처럼 계속 서로를 new 생성자로 호출)

return

return도 학원과제를 풀던 중 이해를 잘 하지못하고 사용하다 이해했다.

public void inputMenu() {
		while(true) {
		System.out.println("===== 도형 프로그램 =====");
		System.out.println("3. 삼각형");
		System.out.println("4. 사각형");
		System.out.println("9. 프로그램 종료");
		System.out.print("메뉴 번호 : ");
		int choiceMenu = sc.nextInt();
		
		switch(choiceMenu) {
			case 3 : triangleMenu(); break;
			case 4 : squareMenu(); break;
			case 9 : System.out.println("프로그램 종료"); return;
			default : System.out.println("잘못된 번호입니다. 다시 입력해주세요."); break;
			}
		}
	}
    
    public void triangleMenu() {
		while(true) {
		System.out.println("===== 삼각형 =====");
		System.out.println("1. 삼각형 면적");
		System.out.println("2. 삼각형 색칠");
		System.out.println("3. 삼각형 정보");
		System.out.println("9. 메인으로");
		System.out.print("메뉴 번호 : ");
		int choiceMenu = sc.nextInt();
		
		switch(choiceMenu) {
			case 1 : inputSize(3, 1); break;
			case 2 : inputSize(3, 2); break;
			case 3 : printlnformation(3); break;
            // 여기가 문제!!
			case 9 : System.out.println("메인으로 돌아갑니다."); inputMenu(); return;
			default : System.out.println("잘못된 번호입니다. 다시 입력해주세요.");
			}
		}
	}

위처럼 코드를 짜고 실행해보니 9번을 입력하면 inputMenu()로 돌아가길 바랬다.

하지만 계속 inputMenu()가 두 번 실행되어 종료를 두 번해야지
종료가 되었는데... 알고보니 위의 주석처리처럼 문제가 있었다.

return을 사용하면 그 즉시 해당 메소드를 중지하고 호출한 메소드로 돌아가는 것, 이걸 나는 해당 메소드를 중지하는 것으로 끝인줄 알고 있었다... (그림참고)

덕분에 잘못된 개념도 고치고 배우게 된 점도 있었다.

끝!

0개의 댓글