[JAVA]13일차(배열의 복사/접근제어 지시자/정보은닉/캡슐화/클래스와 인스턴스/날짜요일구하기/static)

정효진·2021년 7월 30일
0

Developer Study

목록 보기
15/47
post-thumbnail

7월29일(금)

Test091~Test095

◼ 배열의 복사

▪ 배열의 복사란?

: 배열 변수의 복사에는 데이터 복사, 주소값 복사 두가지 형태가 존재한다.

  • 주소값 복사 → 얕은 복사 → 원본을 수정하면 복사본에 영향을 미치게 되는 복사 방법.
    (배열 뿐 아니라 모든 참조형 데이터에 해당하는 복사 방법)
  • 데이터 복사 → 깊은 복사 → 실제 요소로 들어있는 값에 대한 복사로
    원본을 수정해도 복사본에 영향을 미치지 않는 복사 방법.

▪ 배열의 복사(주소값 복사) 코드 설명📝

//Test092.java 파일과 비교~!! (주소값 복사)

public class Test091
{
	public static void main(String[] args)
	{
		int[] nums = {10, 20, 30, 40, 50};     //---배열 원본
		int[] copys;                           //---복사본으로 만들 배열

		int temp;

		copys = nums;                          //--check~!!!  복사~!!!

		temp = nums[0];                       //--temp ← 10

		nums[0] = 1000;                         //- 1000 20 30 40 50

		for (int i=0; i<copys.length; i++)
		{
			System.out.print(copys[i] + " ");

		}System.out.println();

		System.out.println("temp : " +temp);

	}
}
/*
1000 20 30 40 50
temp : 10
계속하려면 아무 키나 누르십시오 . . .
*/

▪ 배열의 복사(데이터 복사) 코드 설명📝

//Test091.java 파일과 비교~!! 
//(데이터 복사)
//-- int 형 배열에 대한 깊은 의미의 복사를 처리하는
//   메소드를 정의하는 형태로 실습을 진행한다.

public class Test092
{
	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()메소드)

		//int[] copy3 = nums.clone();			
        //-- 오른쪽이 커서 자동 형변환에 위배	

        //nums.clone();
        //-- 배열을 복사하게 해주는 clone()메소드. 객체(object)타입으로 반환하게끔 되어있다. 대상 데이터 타입이 객체라고 본다.


	    // 원본 배열 요소의 수정 발생~!!!
		nums[1] = 2;

		//결과 확인
		for (int i=0; i<nums.length; i++)
		{
			System.out.print(nums[i] +  " ");
		}System.out.println();
		//--==> 10 2 30 40 50

		for (int i=0; i<copys1.length; i++)
		{
			System.out.print(copys1[i] +  " ");
		}System.out.println();
		//--==> 10 2 30 40 50

		for (int i=0; i<copys2.length; i++)
		{
			System.out.print(copys2[i] +  " ");
		}System.out.println();
		//--==> 10 20 30 40 50

		for (int i=0; i<copys3.length; i++)
		{
			System.out.print(copys3[i] +  " ");
		}System.out.println();
		//--==> 10 20 30 40 50
	}                                       

	// 매개변수로 int 배열 타입을 넘겨받아 이를 복사한 후
	// 복사한 배열을 반환하는 기능을 가진 메소드 정의
	public static int[] copyArray(int[] os)                   //-- {10, 20, 30, 40, 50}
	{
		// 매개변수로 넘겨받은 배열(os)
		// 즉, 원본 배열 만큼의 배열방(메모리 공간)을 확보한
		// 복사할 배열방 생성
		int[] temp = new int[os.length];
		// int[] temp = new int[5];                          //-- [ ]-[ ]-[ ]-[ ]-[ ]

		// 원본 배열(os)에 담겨있는 각각의 요소들을
		// 복사 배열(temp)에 담아내기... 하나씩... 하나씩...
		for (int i=0; i<os.length; i++)                     //-- for (int i=0; i<os.length; i++)  //i ->0 1 2 3 4
		{
			temp[i] = os[i];                                //-- temp[0]=os[0] / temp[1]=os[1] / ...
		}

		// 복사한 배열(temp) 반환
		return temp;

	}
}

◼ 접근제어 지시자

지시자클래스 내부동일 패키지상속받은 클래스이외의 영역
privateOxxx
defaultOOxx
protectedOOOx
publicOOOO

※ public > protected > default > private

public class Test093             //public 접근제어 지시자
{
	public static void main(String[] args)
	{
		int a;           //default 접근제어 지시자

	}
}

◼ 정보은닉(Information Hiding)

▪ setter / getter

▪ 코드

import java.util.Scanner;

class CircleTest2
{
	private int r;

	void input()
	{
		Scanner sc = new Scanner(System.in);
		System.out.print("반지름 입력 : ");
		r = sc.nextInt();
	}

	double calArea()
	{
		return r * r * 3.141592;
	}

	void write(double a)
	{
		System.out.println("반지름 : " + r);
		System.out.println("넓  이 : " + a);
	}

}
public class hyodii093
{
	public static void main(String[] args)
	{
		CircleTest2 ob1 = new CircleTest2();

		ob1.input();

		double result = ob1.calArea();
		ob1.write(result);
	}
}
/*
반지름 입력 : 2
반지름 : 2
넓  이 : 12.566368
계속하려면 아무 키나 누르십시오 . . .
*/

▪ 코드 설명📝

import java.util.Scanner;

class CircleTest2
{
	
	// 정보 은닉(Information Hiding)
	// 멤버 변수, 인스턴스 변수, 전역 변수
	// 『private』이라는 접근제어지시자의 선언은
	// 클래스 내부에서만 접근 및 참조가 가능하게 하겠다는 의미
	// int형 변수 0으로 초기화 지원
	private int r;

	//int r;

	//(private에 값 입력하기 위해)
	// getter 값을 얻는 것
	// setter 값을 채워넣는 것
	//근데 private으로 막아놓고 왜 겟 셋으로 받아와또? 
	// -> 입력받은것을 조건문에 걸러서 컨트롤이 가능해!(100이상만 입력받아라 이런것)
	// -> 규칙을 정할 수 있음

	/*
	int getR()       //getR과 setR은 CircleTest2의 멤버변수이다
	{
		return r;
	}

	void setR(int r)
	{
		this.r = r;
	}
	*/

	void input()
	{
		Scanner sc = new Scanner(System.in);

		System.out.print("반지름 입력 : ");
		r = sc.nextInt();
	}

	double calArea()
	{
		return r * r * 3.141592;
	}

	void write(double a)
	{
		System.out.println("반지름 : " + r);
		System.out.println("넓  이 : " + a);
	}

}

//외부의 다른 클래스
public class Test093
{
	// 그외부의 다른 클래스의 메소드
	public static void main(String[] args)
	{
		CircleTest2 ob1 = new CircleTest2();
		
		//ob1.r = 10;                                //입력받은값 넣으려고 input했는데 이러면 출력 10 됨 -> private지정하면 해결!
		//System.out.println("원의 반지름 : "+ob1.r);

		//ob1.setR(10);                                //private지정한거에 이렇게 넣으면 값 받아올 수 있음
		//System.out.println("원의 반지름 : " + ob1.getR());

		//ob1.r = 10000;
		
		ob1.input();
		//--5000

		double result = ob1.calArea();
		
		ob1.write(result);

	}
}
/*  실행 결과
반지름 입력 : 5000
반지름 : 5000
넓  이 : 7.85398E7
계속하려면 아무 키나 누르십시오 . . .
*/

◼ 캡슐화

▪ 해당 날짜의 요일을 출력하는 프로그램 코드

import java.util.Scanner;

class WeekDay
{
	private int y, m, d;

	public void input()
	{	
		Scanner sc = new Scanner(System.in);

		System.out.print("년 월 일 입력(공백 구분) : ");		// 2021 7 30
		y = sc.nextInt();
		m = sc.nextInt();
		d = sc.nextInt();
	}

	public String week()
	{
		int[] months = {31, 0, 31, 30, 31, 30,31,31, 30,31, 30,31};
		
		String[] weekNames = {"일","월","화","수","목","금","토"};

		int nalsu;

		if ((y%4==0 && y%100!=0) || y%400==0)
			months[1] = 29;
		else
			months[1] = 28;

		nalsu = (y-1)*365 + (y-1)/4 - (y-1)/100 + (y-1)/400;

		for (int i=0; i<(m-1); i++)
		{
			nalsu += months[i];
		}

		nalsu += d;

		int w = nalsu % 7;

		return weekNames[w];
	}

	public void print(String day)
	{
		System.out.printf(" %d년 %d월 %d일 -> %s\n", y, m, d, day);
	}

}
public class hyodii095
{
	public static void main(String[] args)
	{
		WeekDay ob = new WeekDay();

		ob.input();

		String result = ob.week();

		ob.print(result);
	}
}

▪ 해당 날짜의 요일을 출력하는 프로그램 코드 설명📝

/*
사용자로부터 년, 월, 일을 입력받아
해당 날짜의 요일을 출력하는 프로그램을 구현한다.
단, 달력 클래스(Calendar)는 사용하지 않는다.
또한, 클래스의 개념을 활용하여 작성할 수 있도록 한다.(-> WeekDay 클래스 설계)
그리고 배열의 개념도 적용시켜 작성할 수 있도록 한다.
접근제어지시자의 개념도 확인하여 작성할 수 있도록 한다.
최종적으로
WeekDay클래스 설계를 통해
Test095 클래스의 main() 메소드가 정상적으로 프로그램 실행될 수 있도록 한다.

실행 예)
 년 월 일 입력(공백 구분) : 1996 8 16

 1996년 8월 16일 → x요일
 계속하려면 아무 키나 누르세요...

※ 1년 1월 1일 -> 월요일
※ 1년은 365일이 아닐 때도 있다.

[힌트]
1년 1월 1일 ~ 1996년 8월 16일 ====> 전체 날 수

1. nalsu = 1.1.1 ~ 1995.12.31  작년까지의 날수구하고

2. nalsu += 1966.1.1 ~ 1996.7.31  입력한달 저달까지의 날수 구하고

3. nalsu += 1996.8.1 ~ 1996.8.16   나누기 7하면 요일 구해낼 수 있음!
*/

import java.util.Scanner;

class WeekDay
{
	// 주요 변수 선언
	private int y, m, d;                    //-- 사용자가 입력한 년, 월, 일을 담을 변수

	// 메소드 정의 -> 입력받기(input)
	public void input()
	{
		Scanner sc = new Scanner(System.in);

		System.out.print("년 월 일 입력(공백 구분) : ");		// 2021 7 30
		y = sc.nextInt();
		m = sc.nextInt();
		d = sc.nextInt();
	}

	
	// 메소드 정의 -> 요일 산출하기(week)
	//public String week()
	public String week()
	{
		// 각 월의 마지막 날짜(각 월의 최대값)을 배열 형태로 구성
		int[] months = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

		//테스트
		//System.out.println(months.week);
		//--==>> 12

		// 요일 이름에 대한 배열 구성
		String[] weekNames = {"일","월","화","수","목","금","토"};

		// 날 수 를 종합할 변수
		int nalsu;

		//윤년에 따른 2월의 날 수 계산
		//입력 년도가 윤년이라면... 2월의 마지막 날짜를 29일로 설정
		//입력 년도가 평년이라면... 2월의 마지막 날짜를 28일로 설정
		if ((y%4==0 && y%100!=0) || y%400==0)   //-- 윤년일...29일
			months[1] = 29;
		else                                    //-- 평년이라면...28일
			months[1] = 28;



		// 1. 1년 1월 1일부터 입력받은 년도의 이전 년도 12월 31일 까지의 날 수 계산
		//                 -------------------------
		//                         y-1
		// 2021.7.30 -> 1.1.1 ~ 2020.12.31
		nalsu = (y-1)*365 + (y-1)/4 - (y-1)/100 + (y-1)/400;
		//                  -------   ---------   ----------   
		//           4년에 한번 더하기 / 100년마다 빼고 / 400마다 하루씩 더하겠다
		
		// 365일만 하니까 오차가 부족해지더라
		// 4년에 한번씩만 366일을 하겠다
		// 20년 이면 => 20*365 + 20/4 = 7305
		// 그렇게 더했더니 오차가 많아지더라
		// 그래서 100년 마다는 더하지 말자
		// 20년 이면 => 20*365 + 20/4 - 20/100 = 7300 + 5 - 0(정수니까!) = 7305
		// 400은 100의 배수니까 더하는걸 하지 말아야하는 해인데 오차가 쪼금씩 모자라짐
		// 그래서 400년 마다는 더하자!
		// 20년 이면 => 220*365 + 20/4 - 20/100 + 20/400
		// 결과적으로 20년의 날수는 이렇게 됨!
		// 2021 = 2020*365 + 2020/4 - 2020/100 + 2020/400   ->2021년이 꽉채워진게 아니니가 2020년까지 꽉찬거 구한거! (y-1)

		//테스트
		//System.out.println("날 수  : " + nalsu);
		//--==>> 년 월 일 입력(공백 구분) : 2021 7 30
		//       날 수 : 737790(1.1.1 ~ 2020.12.31 의 총 날 수)


		// 2. 입력받은 월의 이전 월 까지의  날 수 계산 후 
		//    이 계산 결과를 1번의 결과에 더하는 연산
		for (int i=0; i<(m-1); i++)                       // i<(m-1)  check~!!!
		{
			nalsu += months[i];		// 입력받은 년도 1월 1일부터  입력받은 월의 전 월까지의 날짜
		}
		
		//테스트
		//System.out.println("날 수  : " + nalsu);
		//--==>> 년 월 일 입력(공백 구분) : 2021 7 30
		//       날 수 : 737971(1.1.1 ~ 2020.6.30 의 총 날 수)


		// 3. 입력받은 일의 날짜만큼 날 수 계산 후
		//    2번 결과에 더하는 연산
		nalsu += d;					// 입력받은 월 1일부터 d까지의 날짜
		
		//테스트
		//System.out.println("날 수  : " + nalsu);
		//--==>> 년 월 일 입력(공백 구분) : 2021 7 30
		//       날 수 : 738001 (1.1.1 ~ 2020.7.30 의 총 날 수)


		//--------------------------------------------여기까지 수행하면 날 수 연산 끝~!!!

		// 날 수 지금까지 구한이유? -> 요일 구하려고!
		// 무슨 요일인지 확인하기 위한 연산
		int w = nalsu % 7 ;			// 총 날짜 를 7로 나눈 나머지(%) 값 == 0 -> 일요일
									// 총 날짜 를 7로 나눈 나머지(%) 값 == 1 -> 월요일
		//System.out.println("w : " + w);
		//--==>> 년 월 일 입력(공백 구분) : 2021 7 30
		//           W : 5 -> 금요일
		
		return weekNames[w];			// 나머지 0 일때 ->  일요일
	}
	

	// 메소드 정의 -> 결과 출력하기(print)
	public void print(String day)
	{
		System.out.printf(" %d년 %d월 %d일 → %s\n",y,m,d,day);
	}

}


public class Test095
{
	public static void main(String[] args)
	{
		WeekDay ob = new WeekDay();  //-- WeekDay 클래스 기반 인스턴스 생성

		ob.input();                //-- 입력 메소드 호출

		String result = ob.week();   //-- 요일 산출 메소드 호출 및 결과 확인(수신)

		//테스트
		//System.out.println(result);

		ob.print(result);            //-- 출력 메소드 호출
	

	}
}
/*
년 월 일 입력(공백 구분) : 1994 12 31
 1994년 12월 31일 → 토
계속하려면 아무 키나 누르십시오 . . .

년 월 일 입력(공백 구분) : 1995 1 5
 1995년 1월 5일 -> 목
계속하려면 아무 키나 누르십시오 . . .

년 월 일 입력(공백 구분) : 2021 7 14
 2021년 7월 14일 → 수
계속하려면 아무 키나 누르십시오 . . .

년 월 일 입력(공백 구분) : 2021 12 24
 2021년 12월 24일 → 금
계속하려면 아무 키나 누르십시오 . . .

년 월 일 입력(공백 구분) : 2021 7 30
 2021년 7월 30일 → 금
계속하려면 아무 키나 누르십시오 . . .
*/

◼ static

/*
클래스 변수(메소드)라고 부르는 이유는?
1. 클래스가 로딩되는 시점에 메모리에 할당하니까
2. 클래스 이름 통해 접근하니까


class 클래스
{
	static 변수1
    변수2

	static 메소드1() '클래스 메소드'라고도 불림
	{
		static 변수
		'클래스 변수' 라고 불림
	}

	메소드2()
	{
	}
}
클래스 로딩 -> 메모리 퍼올린다(인스턴스가 생성) 가 원래 순서인데
이렇게 있으면 원래는 인스턴스가 생성되어야지 메모리가 생성되는데 static이 붙어있으면 
클래스 로딩 -> static 실행되서 메모리 올린다 -> 다른 메소드 인스턴스 생성
이래서 static이 제일 먼저 메모리가 발생함

레고로 치면 설계도를 보고 조립하는건데
static은 설계도를 읽으면서 다 만들어버림

class 다름 클래스
{
	main()
	{
		클래스 ob = new 클래스();

		ob.변수2
		ob.메소드1()   얘네는 '인스턴스 변수'라고 불림
					   얘네는 인스턴스 생성해서 접근함

		클래스.변수1
		클래스.메소드2()  얘네는 인스턴스 생성해서가아니라 클래스 이름으로 접근함
	}
}
------------------------------------------

class 클래스
{
	static 변수1
    변수2

	static 메소드1() '클래스 메소드'라고도 불림
	{
		System.out.println(변수2);          //--에러남 -> 동생이 태어났으면 형이 무조건 있지만 형이 태어났다고 해서 동생 있지는 않음
	
		System.out.println(변수1);	       //-- 가능함  태어난 시점은 변수1과 메소드1은 같음  그래서 실행됨
	}

	메소드2()
	{
		System.out.println(변수1);         //--- 가능함 얘는 클래스가 로딩후 인스턴스가 생성된거니까 변수1 가능함

		System.out.println(변수2);         //--- 가능함 인스턴스 매소드가 생성되었으니까 인스턴스변수 가능함
	}
}

-------------------------------------------
<static>

1. 탄생시점(태어난 시점)      //-- 인스턴스 생성시 메로리가 생성됨
                              //     클래스 ob = new 클래스();
							  // static이 붙은 메소드는 가장 먼저 태어남


2. 공유                       //--스테이플러 예시 하나로 공유해서 쓰는 것

*/

다음 포스팅에서 static 계속...

profile
개발새발

0개의 댓글

관련 채용 정보