ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 017. 배열의 복사 (데이터 복사, 주소 복사), 클래스와 인스턴스 : 접근 제어 지시자와 정보은닉 , 캡슐화
    SsY/Class 2023. 3. 7. 22:51
    728x90

    2023.02.16 (목)

    배열
    - 배열의 복사
    ※ 자바에서 배열 변수의 복사에는 데이터 복사, 주소값 복사 두 가지 형태가 존재한다.
    1) 주소값 복사 → 얕은 복사
        원본을 수정하면 복사본에 영향을 미치게 되는 복사 방법
        (자바의 배열 뿐 아니라 모든 참조형 데이터에 해당하는 복사 방법)

    2) 데이터 복사 → 깊은 복사
        실제 요소로 들어있는 값에 대한 복사로
        원본을 수정해도 복사본에 영향을 미치지 않는 복사 방법

    • Test097, 098 (비교하며 보기)
      - Test097 : 주소값 복사 (== 얕은 복사)
      - Test098 : 데이터 복사 (== 깊은 복사)
    ※ clone()  메소드
     - java.lang.Object;   // Object 클래스(객체)의 메소드
      별도의 import 구문이 필요하지 않다( → ※ 상속파트에서 확인 가능) 
     - 깊은 의미의 객체 복사를 수행해주는 메소드이다.
    더보기
    public class Test096
    {
    	public static void main(String[] args)
    		{
    			int[] nums = {10, 20, 30, 40, 50};		//-- 배열 원본
    			int[] copys;							//-- 복사본으로 만들 배열
    
    			int temp;								//-- 데이터 임시 저장 변수
    													//	 (값 타입 확인 → 배열과 비교)
    			//check~!!!
    			copys = nums;							//-- 복사~!!!
    
    			temp = nums[0];							//-- temp = 10;
    
    			// 원본 배열의 데이터 수정
    			nums[0] = 1000;							//-- 1000 20 30 40 50
    
    			// copys 배열의 전체 요소 출력 확인
    			for (int i=0; i<nums.length; i++)
    				System.out.printf("%4d", copys[i]);
    			System.out.println();
    			//--==>> 10  20  30  40  50
    
    			// 원본 배열의 데이터 수정 이후 다시 확인	//-- 원본배열과 동일하게 변경 됨
    			//--==>> 1000  20  30  40  50
    
    			// temp 출력 확인
    			System.out.println("temp : " + temp);
    			//--==>> temp : 10
    		}
    }
    //		데이터 복사
    //		- int 형 배열에 대한 깊은 복사를 처리하는
    //		  메소드를 정의하는 형태로 실습 진행
    
    public class Test097
    {
    	public static void main(String[] args)
    		{
    			int[] nums = {10, 20, 30, 40, 50};				//-- 배열 원본
    
    			int[] copys1 = nums;							//-- 얕은 의미의 배열 복사 수행
    															//	 (주소값 복사)
    
    			int[] copys2 = copyArray(nums);					//-- 깊은 의미의 배열 복사 수행
    															//	 (사용자 정의 메소드 호출)
    			
    			int[] copys3 = (int[])nums.clone();				//-- 깊은 의미의 배열 복사 수행
    															//	 (자바 제공 → clone() 메소드)
    
    			// 원본 배열 요소의 수정 발생~!!!
    			nums[1] = 9999;
    
    			//결과 확인
    			for (int i=0; i<nums.length; i++)
    				System.out.printf("%6d", nums[i]);
    			System.out.println();
    			//--==>>     10  9999    30    40    50
    
    			for (int i=0; i<copys1.length; i++)
    				System.out.printf("%6d", copys1[i]);
    			System.out.println();
    			//--==>>     10  9999    30    40    50
    
    			for (int i=0; i<copys2.length; i++)
    				System.out.printf("%6d", copys2[i]);
    			System.out.println();
    			//--==>>     10    20    30    40    50
    
    			for (int i=0; i<copys3.length; i++)
    				System.out.printf("%6d", copys3[i]);
    			System.out.println();
    			//--==>>     10    20    30    40    50		
    		}
    
    	// 매개 변수로 int배열 타입을 넘겨받아
    	// 이 배열을 복사한 후
        // 복사한 배열을 반환하는 기능을 가진 메소드 정의
    	public static int[] copyArray(int[] target)
    	{
    		// 매개변수로 넘겨받은 대상 배열(target)
    		// 즉, 원본 배열 만큼의 배열방(메모리 공간)을 확보한
    		// 복사할 배열 생성
    		int[] result = new int[target.length];
    		
    		// 원본 배열(target)에 담겨있는 각각의 요소들을
    		// 복사 배열(target)에 담아내기
    		for (int i=0; i<target.length; i++)
    			result[i] = target[i];
    
    		// 최종적으로 복사한 배열(result) 반환
    		return result;
    	}
    }
    
    // 실행 결과
    
    /*
        10  9999    30    40    50
        10  9999    30    40    50
        10    20    30    40    50
        10    20    30    40    50
    계속하려면 아무 키나 누르십시오 . . .
    */

    클래스와 인스턴스
    - 접근제어 지시자와 정보은닉 그리고 캡슐화
    • 접근제어 지시자 
      - 접근 제어 지시자 == 접근 지시자 == 접근 제어자 == 접근 지정자 == 접근 제한자
      - 클래스나 메소드, 변수 앞에 붙임

    ▒ 자바 접근 제어 지시자의 관계

    				 ┌java.util.~
    ====================================================================================
     지시자		클래스 내부	동일 패키지	상속받은 클래스		이외의 영역
    ------------------------------------------------------------------------------------
     private	     O		     X		       X		     X
     default	     O		     O		       X		     X
     protected	     O		     O		       O		     X
     public		     O		     O		       O		     O
    ------------------------------------------------------------------------------------
    
    // ※ public > protected > default > private
    //    모두			     나만
    
    // default 라는 이름을 가진 접근 지시 제어자는 없다 
    //- 아무것도 붙이지 않고 만들었을 때, default 를 가지게 됨
    
    // protected 가 더 접근제어 될 것 같지만, default가 더 보수적인 것을 명심하자!
    // ( 비밀이라고 알고 있다는 것보다 아무것도 알려주지 않을 때가 더 보수적임!)
    // ( protected라고 알고 있다는 것은 상속받은 클래스를 지켜야하기 때문에 접근할 수 있다!)
    • 정보 은닉 (Information Hiding)
    『private』이라는 접근제어지시자를 선언하여
    클래스 내부에서만 접근 및 참조가 가능하게 하겠다는 의미
    더보기
    /*=============================================
               ■■■ 클래스와 인스턴스 ■■■
            - 정보 은닉과 접근 제어 지시자
    ==============================================*/
    
    //	※	접근 제어 지시자 == 접근 지시자 == 접근 제어자 == 접근 지정자 == 접근 제한자
    
    import java.util.Scanner;
    
    class CircleTest2
    {
    	// 멤버 변수, 인스턴스 변수, 전역 변수
    	//int num;
    	// ↓		// (정보 은닉)
    	private int num;		// int 형 전역 변수 → 자동 0으로 초기화 지원
    
    	// getter / setter 구성
        // 추후 컬렉션 (Collection) 에서 함께 다룰 예정
    	int getNum()				// 값을 얻는 메소드
    	{
    		return num;
    	}
    
    	void setNum(int num)		// 값을 세팅하는 메소드
    	{
    		this.num = num;
    	}
    
    	void input ()
    	{
    		Scanner sc = new Scanner(System.in);
    
    		System.out.print("반지름 입력 : ");
    		num = sc.nextInt();
    	}
    
    	double calArea ()
    	{
    		return num * num * 3.141592;	
    	}
    	
    	void write (double area)
    	{
    		System.out.println("반지름 : " + num);
    		System.out.println("넓이 : " + area);
    	}
    }
    
    public class Test098
    {
    	public static void main(String[] args)
    	{
    		//CircleTest2 인스턴스 생성
    		CircleTest2 ob1 = new CircleTest2();
    
    //	※	현재까지 배운 개념으로써는 유일하게
    //		CircleTest2 의 num 에 데이터를 전달할 수 있는 방법
    		
            //ob1.num = 10; // private으로 선언한 변수는 해당 클래스에서 이용할 수 없다.
    		//	↓
    		ob1.setNum(10); // 메소드를 통해서 접근이 가능하다!
    
    		//System.out.println("원의 반지름 : " + ob1.num);
    		//	↓
    		System.out.println("원의 반지름 : " + ob1.getNum());
    		//--==>> 원의 반지름 : 10
    
    		ob1.input();
    		//--==>> 반지름 입력 : 20
    		//		 → 『ob1.num = 20』
    
    		double result = ob1.calArea();
    		ob1.write(result);
    		//--==>> 반지름 입력 : 30
    		//       반지름 : 30
    		//       넓이 : 2827.4328
    
    	}
    }

    • 캡슐화
    ● 정보은닉 → getter / setter로 접근하는 방법
    ● 자바는 객체지향프로그램으로 객체를 단위로 사용하는데, 클래스도 객체이다.
       이 클래스를 필요에 의해서 여러개를 하나로 묶는 경우가 있는데 이를 캡슐화 라고 한다.
       - 변경사항이 있을 때, 변경되는 클래스의 범위를 줄일 수 있다
       - 작은 크기의 클래스를 다른 클래스의 정의에 활용할 수 있다
    ● 단, 객체 지향의 관점에서는 큰 하나의 클래스보다 작은 여러개의 클래스가 훨씬 큰 위력을 갖는다.
    더보기

    ex) 감기 증상 : 기침, 가래, 코막힘, 발열, 두통, 오한 ...
    (객체 지향 관점)
    만약 증상들에 대한 각각의 약이 따로 있다면?
    - 증상만큼 약을 먹어야 함, 하지만 필요하지 않은 약은 먹지 않아도 됨! 
    약의 우선순위 혹은 상성에 맞춰서 먹어야 함 (캡슐화 관점에서 객체지향에 반대)
     

    (캡슐화 관점)
     종합감기약
    - 상성이나 순위에 관계없이 약 하나만 복용하면 되게 한 개로 묶자!
    ▶ 필요한 증상에 대한 약만 먹으면 되는데 과복용 아닌가? (객체지향이라 캡슐화를 반대)

    이 관점은 업무에 따라 비율이 달라지기 때문에,  객체지향과 캡슐화의 비율을 맞추는것이 어렵다.


    • Test099 (달력 설계, Calendar 클래스 미사용)
      - 클래스 설계
      - 배열의 활용
      - 접근제어지시자와 정보은닉
    더보기
    /*=============================================
            ■■■ 클래스와 인스턴스 ■■■
    	 - 클래스 설계
    	 - 배열의 활용
    	 - 접근제어지시자와 정보은닉
    ==============================================*/
    
    // 사용자로부터 년, 월, 일을 입력받아
    // 해당 날짜의 요일을 출력하는 프로그램을 구현한다.
    // 단, 달력 클래스(Calendar)는 사용하지 않는다.
    // 또한 클래스의 개념을 활용하여 작성할 수 있도록 한다.
    // (→ WeekDay 클래스 설계)
    
    // 실행 예)
    // 년 월 일 입력 (공백 구분)  :2023 2 16
    // >> 2023년 2월 16일 → 목요일
    // 계속하려면 아무 키나 누르세요...
    
    //	※ Hint
    //		- 1년 1월 1일 → "월요일"
    //		- 1년은 365일이 아니다.
    //		- 2월의 마지막 날짜가 29일 → 윤년
    //		  2월의 마지막 날짜가 28일 → 평년
    //		- 윤년의 판별 조건
    //		 → 년도가 4의 배수이면서 100의 배수가 아니거나.
    //			400의 배수이면 윤년, 그 이외의 년도는 평년.
    
    import java.util.Scanner;
    
    class WeekDay
    {
    	private int y,m,d, w;
    	private String[] strW = {"일","월","화","수","목","금","토"};
    	private int sum;
    
    	public void input()
    	{
    		Scanner sc = new Scanner(System.in);
    		System.out.print("년 월 일 입력 (공백 구분) : ");
    		y = sc.nextInt();
    		m = sc.nextInt();
    		d = sc.nextInt();
    	}
    
    	public int cal()
    	{
    		// 1월 1일 부터 입력받은 y-1년도 12월 31일 까지 날짜 계산
    		sum = (y-1)*365 + (y-1)/4 - (y-1)/100 + (y-1)/400;
    		// y년도 m-1월 까지 날짜 계산
    		switch (m-1)
    		{
    			case 12: sum += 31;
    			case 11: sum += 30;
    			case 10: sum += 31;
    			case 9 : sum += 30;
    			case 8 : sum += 31;
    			case 7 : sum += 31;	
    			case 6 : sum += 30;
    			case 5 : sum += 31;
    			case 4 : sum += 30;
    			case 3 : sum += 31;
    			case 2 : if (y%4==0 && y%100!=0 || y%400==0)
    						sum += 29;
    					 else
    						sum += 28;
    			case 1 : sum += 31;
    		}
    		// 날짜 까지 계산
    		sum += d;
    		return w = sum%7;	
    	}
    
    	public void print(int w)
    	{
    		System.out.printf(">> %d년 %d월 %d일 → %s요일\n",y,m,d,strW[w]);
    	}
    
    }// weekDay class end
    
    public class Test099
    {
    	public static void main (String[] args)
    	{
    		WeekDay wd = new WeekDay();
    		wd.input();
    		int nalsu = wd.cal();
    		wd.print(nalsu);
    	}
    }
    
    // 실행 결과
    /*
    년 월 일 입력 (공백 구분) : 2023 3 7
    >> 2023년 3월 7일 → 화요일
    계속하려면 아무 키나 누르십시오 . . .
    */

     

    // 개인적 감상

    더보기

    개념에 대한 이해가 점점 늘어가면서 다시 풀어본 Test099 와 같이 식을 줄여볼 수 있었고, 

    Switch 문 안에도 if 문 적용이 가능할까 테스트 해보았는데, 정상적으로 돌아가서 신기했다.

    728x90
Designed by planet-si