국비지원 복습과정 9차(인터페이스, static)

Park In Kwon·2022년 9월 15일
0

1. 인터페이스

1-1. 추상 클래스의 한계

  • Java 클래스 간의 상속에는 하나의 부모만 존재할 수 있기 때문에, 앞의 상황에서 요구하는 다중 상속의 구현은 불가능하다.

1-2. Interface란?

  • 완벽한 추상화를 구현하기 위한 Java 클래스의 한 종류이다.
  • 다중 상속이 가능하기 때문에 용도별로 세분화 하여 필요한 요소만 상속할 수 있다.

1-3. 비교

  • 추상클래스
    -멤버변수, 생성자, 메서드, 추상메서드를 포함할 수 있다.
    -이 클래스를 상속받는 자식 클래스는 다른 클래스를 상속받을 수 없다.
    -객체의 생성이 불가능하다.
  • 인터페이스
    -추상메서드만 포함할 수 있다.
    -인터페이스는 다중 상속이 가능하다.
    -객체의 생성이 불가능하다.

1-4. 인터페이스 상속을 위한 implements 키워드

  • 인터페이스의 상속은 implements 키워드를 사용한다.
  • 인터페이스도 추상화를 구현하고 있기 때문에, 인터페이스를 상속받는 클래스는 인터페이스 내의 모든 메서드들을 반드시 재정의 해야 한다.

1-5. 인터페이스의 다중 상속

  • 인터페이스는 콤마( , ) 로 연결하여 여러 개를 동시에 상속 받을 수 있다.

    public class Monster implements Fight, move {

    }

  • 필요한 경우 다른 클래스와 동시에 상속받을 수 있다.

    public class Monster extends User implements Fight, Move {

    }

2. Static

     public class Article{
               private static int count;          // 전체 글 수
               private static String category;  // 카테고리

               private int num;           // 글 번호
               private String title;        // 글 제목
               private String regDate;   // 날짜
     }
  • 멤버변수는 모든 객체가 독립적으로 갖는 고유 데이터이기 때문에 게시물의 수라는 공유 데이터를
    모든 게시물이 갖게 된다.
  • 즉, 각각의 객체가 중복된 데이터를 갖게 된다.
  • 클래스를 설계할 때, 멤버변수 중 모든 객체에서 공통적으로 사용해야 하는 값에 static을 붙인다.
  • static이 붙은 멤버변수는 객체의 개수에 상관 없이 단 하나만 생성되며, 이를 모든 객체가 공유하기
    때문에 메모리를 효율적으로 사용할 수 있다.

2-1. 컴퓨터의 메모리 구조

  • 코드영역(고정영역) : 프로그램의 코드가 저장되는 영역
    이 영역에서 저장된 명령어들을 cpu가 하나씩 가져가서 실행한다.

  • 데이터영역(고정영역) : 전역변수와 static으로 선언된 변수가 할당된다.
    이 영역에서 할당되는 변수들은 프로그램 시작과 동시에 메모리
    공간이 할당되어 종료될 때까지 남아있게 된다.

  • 힙영역(동적 영역) : 프로그래머가 원하는 시점에 변수를 할당하고 소멸시키는 영역 메모리 동적 할당시 사용된다.

  • 스택 영역 (동적 영역) : 함수가 실행될 때 사용되는 파라미터와 지역변수에 대한 메모리 공간. 함수의 종료와 함께 소멸된다.

2-2. 하나의 프로그램이 사용하는 메모리영역

  • 고정영역 : 프로그램이 실행되면 실행파일이 메모리에 로드 된다.
    실행파일의 용량만큼 메모리를 사용한다.
    실행파일의 크기는 변할 수 없으므로 이 영역의 크기는 고정 크기를 갖게 된다.

  • 동적영역 : 프로그래머가 new 키워드를 사용해서 객체나 배열을 생성하면 사용된다. (힙 영역)
    메서드가 호출되는 동안 사용될 파라미터와 지역변수가 생성된다. (스택 영역)
    메서드가 종료되거나 객체가 더이상 사용되지 않으면 생성된 변수나 객체는 메모리에서 사라지므로, 이 영역은 유동적인 크기를 갖게 된다.

2-3. static 데이터의 생성 위치

  • static 데이터는 메모리의 고정영역 중 데이터영역에 생성되고, 일반 멤버변수나 객체는 동적 영역 중 heap (힙) 메모리 영역에 생성된다.

2-4. 프로그램이 메모리를 사용하는 순서

  • 최초 실행시 고정 영역에 실행파일만큼의 메모리를 점유한다.
  • 프로그램이 각종 동작을 수행하는 동안 동적 영역을 사용한다.

2-5. 멤버변수와 static 멤버변수의 차이

  • static 변수는 프로그램의 실행과 동시에 객체의 생성 여부와 상관 없이 이미 존재하기 때문에 소스 코드에는 특정 클래스 안에 명시하지만, 그 클래스를 통해서 생성되는 객체나 그 안에 포함되는 멤버변수와는 다른 존재이다.

  • 객체가 생성되지 않더라도 이미 존재하고 있기 때문에 static 변수는 객체의 이름을 통해 접근하는 것이 아니라, 클래스의 이름을 통해서 접근해야한다.

  • 단, static 변수가 선언된 클래스 안에서는 변수 이름으로 직접 접근이 허용된다.

  • Article 클래스 및 다른 클래스에서 접근하는 경우

    Article.count = 5;
    Artilce.category = "공지사항";

  • Article 클래스 내부에서 접근하는 경우

    count = 6;
    cetegory = " 공지 사항";

4-6. static 데이터에 접근하기 위한 메서드

  • 클래스에서 정의하는 일반 메서드들은 객체의 생성과 동시에 동적 메모리 영역에서 활성화 된다.
    -> 동적 메모리 영역의 입장에서는 고정 메모리 영역의 자원들은 항상 존재한다.
    -> 고정 메모리 영역의 자원들은 동적 메모리의 자원들이 항상 존재하는 것이라는 보장을 받지 못한다.

  • 그러므로 객체의 생성과 상관 없이 static 변수에 접근하기 위한 메서드를 만들 필요가 있을 때,
    메서드의 정의 과정에서 static 키워드를 사용하면 static 자원에 접근하기 위한 메서드를 만들 수 있다.

    public static void setCount( int count ) {
    Article.count = count;
    }

  • 메모리 영역의 차이 때문에 static 메서드는 동적 메모리 영역의 멤버변수를 사용하거나, static이 아닌
    일반 멤버함수를 호출할 수 없다.

package staticobject;

//하나의 게시물을 표현하기 위한 JavaBeans
public class Article {
	
	/*
	 * static은 모든 객체가 공유하는 값이다. static값은 클래스 이름을 통해서
	 * 접근해야 하며, 객체의 생성 여부에 상관 없이 사용이 가능하다.
	 */
	
	//전체 게시물의 수를 표현하기 위한 데이터
	private static int count = 0;
	// 모든 게시물은 하나의 카테고리 안에 존재한다고 가정한다.
	// 게시물의 분류를 구별하기 위한 데이터
	private static String category;
	
	private int num;         // 글 번호
	private String title;    // 글 제목
	private String regDate;  // 작성일자
	
	
	public Article(int num, String title, String regDate) {
		super();
		this.num = num;
		this.title = title;
		this.regDate = regDate;
		
		/*
		 * 이 클래스에 대한 객체 생성 -> 게시물 신규 등록
		 * 게시물이 새로 등록될 때 마다, 전체 글 수를 의미하는
		 * count 변수가 1씩 증가한다.
		 * 전체 게시물 수는 모든 객체가 공유하는 값이므로,
		 * static으로 생성되어야 한다. 
		 */
		count++;
	}


	public static int getCount() {
		return count;
	}


	public static void setCount(int count) {
		Article.count = count;
	}


	public static String getCategory() {
		return category;
	}


	public static void setCategory(String category) {
		Article.category = category;
	}


	public int getNum() {
		return num;
	}


	public void setNum(int num) {
		this.num = num;
	}


	public String getTitle() {
		return title;
	}


	public void setTitle(String title) {
		this.title = title;
	}


	public String getRegDate() {
		return regDate;
	}


	public void setRegDate(String regDate) {
		this.regDate = regDate;
	}


	@Override
	public String toString() {
		return "글 분류 = " + category 
				+ ", 전체 글 수 = " + count
				+ ", Article [num= "+ num
						   + ", title=" + title
						   + ", regDate=" + regDate + "]";
	}
}

package staticobject;

public class Calc {
	
	// ------------------------ 싱글톤 객체 생성을 위한 준비 시작
	/*
	 * static이 적용된 자원은 메모리의 고정영역에 생성되기 때문에, 클래스
	 * 자체의 객체나, 그 안에 포함된 멤버변수, 메서드와는 메모리 상에서 구별된다고 볼 수 있다.
	 * 그러므로 Calc 클래스 안에 static 형태로 Calc 클래스의 객체를 정의하더라도
	 * 코드상의 논리적인 연관관계를 위해 하나의 파일에서 정의하는 것일 뿐, 실제로는 
	 * Calc 클래스 자체어서 독립된 객체가 되는 것이다.
	 * Calc 클래스 이외의 여러 곳에서 new 연산자를 사용해 객체 할당이 가능하다면 
	 * SingleTon이라는 개념 자체가 성립되지 않으므로, 외부에서 이 객체에 직접적인 
	 * 접근을 못하도록 은닉시킨다.
	 */
	private static Calc current;
	
	//객체가 할당되지 않은 경우에만 할당하도록 하여 중복 할당을 방지한다.
	public static Calc getInstance() {
		
		if ( current == null ) {
			 current = new Calc();
		}
		
		return current;
	}
	
	// 객체에 null을 대입하면 메모리에서 삭제된다.
	public static void freeInstance() {
		current = null;
	}
	
	// 기본 생성자를 private 형태로 정의하면 객체 생성자가 은닉처리되어
	// 외부에서 new 연산자를 사용한 객체할당이 금지된다.
	private Calc() { }
	
	//------------------------- 싱글톤 객체 생성을 위한 준비 끝
	public int plus ( int x, int y ) {
		return x + y;
	}
	
	public int minus ( int x, int y ) {
		return x - y;
	}
}

package staticobject;

public class Main01 {

	public static void main(String[] args) {
		Article.setCategory("자유게시판");
		
		Article a1 = new Article(1, "첫번째 게시물", "2022-08-18"); 
		Article a2 = new Article(2, "두번째 게시물", "2022-08-19"); 
		Article a3 = new Article(3, "세번째 게시물", "2022-08-20");
		
		System.out.println(a1.toString()); 
		System.out.println(a2.toString()); 
		System.out.println(a3.toString()); 
		
		System.out.println("---------------------");
		
		Article.setCategory("공지사항");
		
		System.out.println(a1.toString()); 
		System.out.println(a2.toString()); 
		System.out.println(a3.toString()); 

	}
}

package staticobject;

public class Main02 {

	public static void main(String[] args) {
//		Calc c1 = new Calc();
//		int a = c1.plus(20, 10);
//		
//		Calc c2 = new Calc();
//		int b  = c1.minus(20, 10);
		
//		Calc c3 = new Calc();
//		int c = c3.plus(20, 10);
//		int d = c3.minus(20, 10);
		
		/*
		 * 싱글톤 객체 사용하기
		 * - getInstance() 메서드를 사용하여 객체를 리턴받는 형식으로 사용한다.
		 * - 여러 객체를 리턴받더라도 모두 하나의 static 객체를 참조하게 되기 때문에
		 *   전역 객체 하나만이 메모리에 할당되게 된다.
		 */
		
		Calc c = Calc.getInstance();
		int e = c.plus(20, 10);
		System.out.println(e);
		
		System.out.println( Calc.getInstance().minus(20, 10));
	}
}
profile
개발자로 진로 변경을 위해 준비하고 있습니다

0개의 댓글