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;
}
}
지시자 | 클래스 내부 | 동일 패키지 | 상속받은 클래스 | 이외의 영역 |
---|---|---|---|---|
private | O | x | x | x |
default | O | O | x | x |
protected | O | O | O | x |
public | O | O | O | O |
※ public > protected > default > private
public class Test093 //public 접근제어 지시자
{
public static void main(String[] args)
{
int a; //default 접근제어 지시자
}
}
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일 → 금
계속하려면 아무 키나 누르십시오 . . .
*/
/*
클래스 변수(메소드)라고 부르는 이유는?
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 계속...