-
017. 배열의 복사 (데이터 복사, 주소 복사), 클래스와 인스턴스 : 접근 제어 지시자와 정보은닉 , 캡슐화SsY/Class 2023. 3. 7. 22:51728x90
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'SsY > Class' 카테고리의 다른 글
019. 클래스와 인스턴스 : 접근지시제어자 활용, 메소드 중복정의(오버로딩) + 만년 달력, 주민등록번호 유효성 검사 (0) 2023.03.09 018. 클래스와 인스턴스 : static(클래스) 변수/메소드 (0) 2023.03.08 016. 배열의 배열(다차원 배열)실습, 배열의 난수(Random 클래스) (2) 2023.03.05 015. 배열의 선언과 초기화, 배열 중첩 (배열의 배열) (0) 2023.03.03 014. 클래스와 인스턴스 실습, 생성자(Constructor) (0) 2023.03.02 - Test097, 098 (비교하며 보기)