과제
2022.07.06 / Hw1

             키보드를 통해서 연도(ex) 2020)를 입력 받는다.
       이때 입력 받은 연도가 윤년인지 평년인지를 판별하는 
       프로그램을 작성하세요

       (단, GregorianCalendar 클래스를 이용해서 처리 하세요.)

 

 

의도

객체 생성

GregorianCalendar 클래스 활용

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220706/GregorianLeapYearHw.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_07_06;

import java.util.GregorianCalendar;
import java.util.Scanner;

public class GregorianLeapYearHw {

	public static void main(String[] args) {

		// 입력
		System.out.println("연도를 입력하시오");
		Scanner sc = new Scanner(System.in);
		int year = sc.nextInt();
		
		// 객체 생성
		GregorianCalendar gc = new GregorianCalendar();
		
		if(gc.isLeapYear(year)) {
			System.out.println("윤년 입니다.");
		}else {
			System.out.println("평년 입니다.");
		}
	}
}

 

 

출력

 과제
2022.07.05 / Hw1

             키보드를 통해서 연도(ex) 2020)를 입력 받는다.
       이때 입력 받은 연도가 윤년인지 평년인지를 판별하는 
       프로그램을 작성하세요

 

1년 실제론 365.242374일
평년 = 365일 (2월달 - 28일까지)

윤년 = 366일 (2월달 - 29일까지)

소숫점 보정위해 윤년만듬

 

* 윤년의 정의
1. 해당 연도를 4로 나누어 떨어지면 윤년
2. 그 중에서 100으로 나누어 떨어지면 윤년이 아님
3. 그 중에서 400으로 나누어 떨어지면 윤년

 

 

의도

제어문(조건문) 활용

 

 

깃허브

https://github.com/kindacool/Hw/tree/main/HW20220705

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_07_05;

import java.util.Scanner;

public class LeapYearHw {

	public static void main(String[] args) {

		System.out.println("연도를 입력하시오");
		Scanner sc = new Scanner(System.in);
		int year = sc.nextInt();
		boolean isLeapYear = false; // true면 윤년, false면 평년

		if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
			isLeapYear = true;
		}

		if (isLeapYear == true) {
			System.out.println("윤년 입니다.");
		} else {
			System.out.println("평년 입니다.");
		}
	}

}

 

 

+ 코드 설명

윤년인 경우는 크게 2가지다
1. 4로 나눠지고 100으로 나누어 떨어지지 않는 경우 -> 바로 윤년이다.
2. 4로 나눠지고 100으로 나누어 떨어지는데 400으로 나누어 떨어지는 경우

 -> 400으로 나누어떨어지는 수라면 애초에 4로도 나누어떨어지고 100으로도 나누어 떨어지는 수임.

-> 즉 year % 400 == 0 라고만 쓰면 된다

 

 

출력

복습

변수
1. 지역변수
2. 멤버변수
3. 정적 멤버변수 (= 정적필드, 나중에 공부)

객체모델링
속성 -> 필드
동작 -> 메소드

- 클래스(설계도) -> 객체
- 대부분의 클래스는 객체 생성시 new연산자 사용

필드
- 메소드 바깥쪽에 정의되는 변수
- 힙메모리에 저장되고 자동초기화된다.
- 할당시점 : new연산자로 객체 생성시 힙메모리상에 할당

생성자
- 클래스명과 동일, 앞에는 접근제어자만옴, 필드값을 초기화 시키는 역할

메소드
- 객체의 동적인 것 표현

기본자료형인 필드
- 객체생성시 힙메모리할당되며
- 자동으로 초기화
정수형 : 0
실수형 : 0.0
논리형 : false

참조형인 필드
- null , 참조하는 주소가 없다.

생성자 호출
- 생성자 매개변수에 맞는값 넣어서 생성

생성자 오버로딩
- 한개 클래스 안에 동일한 이름으로 만든 여러 생성자

this
this. : 필드 생성자 메서드 안에서 멤버변수와 매개변수 이름이 같을때사용
this() : 같은 클래스내의 생성자 호출하라는 의미

과제풀이(Lotto.java) 설명
https://laker99.tistory.com/17

- 새로 발생된 난수값과 이전의 난수값들을 비교하기 위해 중첩 for문 사용
- i-- 한 뒤 괜히 더 돌아가는걸 막기위해 break 해주는게 좋다 
- 하나 중복을 발견하면 다음꺼부터는 중복일리가 없다, 이전에 이미 다 처리되었기 때문에
- 오름차순 적용

1. num[0] = 5, num[1] = 5 일때, 안의 for문이 돌아가면서  num[0] 과 num[1]을 비교해서 같으므로 i--시킴
2. 그럼 i=0이 되고 break 되어 나옴 이해 바깥 for문에 의해 ++ 되며 i=1 이 됨
3. 다시 num[1]값을 랜덤으로 받는것

오름차순하기
- 정렬알고리즘 통해서 (버블정렬 = 자신의 옆자리에 있는 것과 비교)
- Arrays 클래스의 sort()함수이용해서 num 배열이름 넘겨주면 오름차순 정렬해줌(java.util.Arrays)

필드 = 멤버변수
- 메소드 바깥쪽에 정의됨
- 기본자료형은 초기화가 됨

파일 생성
- 메인메소드를 가진 클래스만 public class가 될 수 있다!
+ 생성자의 접근제어자 주로 public 이다.

클래스 실행하기
1. 클래스 안에 메인메소드 넣기(독립적실행가능)
2. 메인 메소드가 있는 클래스에서 실행시켜주기

 

필드로 직접 접근하기 예제

class Korean{
	//필드
	String nation = "대한민국";
	String name;
	String ssn; //전화번호
	
	public Korean(String name, String ssn) {
		this.name = name;
		this.ssn = ssn;
	}
	
	
}

public class KoreanEx {

	public static void main(String[] args) {

		Korean k1 = new Korean("박자바","011225-1234567");
		System.out.println("k1.name : " + k1.name);
		System.out.println("k1.ssn : " + k1.ssn);
		
		Korean k2 = new Korean("김자바","930525-0654321");
		System.out.println("k2.name : " + k2.name);
		System.out.println("k2.ssn : " + k2.ssn);
	}

}

- k1객체 만든 후 k1. 통해서 필드로 접근
- k2객체 만든 후 k2. 통해서 필드로 접근
- 필드 name, ssn을 private으로 바꾸게 되면 KoreanEx클래스에서  k1.name k2.ssn 해서 접근 불가(출력 불가)
다른 클래스라서, 다이렉트 접근을 막는다

 

필드값
- nation은 "대한민국"으로 초기화
- name과 ssn은 객체를 생성할때 생성자를 통해 전달된 값으로 각각 초기화됨

할당 시점
- new연산자로 힙메모리에 새로운 공간 생성할때 힙메모리상에 새로운 공간 할당받음(참조형은 다 마찬가지)
- 자료형이 String이라서(필드값) null로 자동초기화되지만 여기선 객체생성시 생성자호출시 받는 값으로 초기화 (name,ssn)
- 주소를가진 레퍼런스 변수 : k1, k2
- 필드들 nation, name, ssn 의 접근제어자가 default이므로 같은 패키지 내는 모두 접근 가능. 그래서 다른 클래스에서 k1.ssn 가능

 

그림


자바의 접근 제어자 정리

접근제어자   자신의클래스   같은패키지                하위클래스       다른패키지

private                    O                    X                                X                    X
생략(default)          O                    O                                X                    X
protected                O                   O                                O                    X
public                      O                   O                                O                   O

+ 같은 클래스 내 : 접근 제어자 의미 없다. 뭐든 접근 된다.
- private : 오직 같은 클래스에서만 됨 , 다른 클래스에서 접근하는걸 허용하지 않음, 가장 좁은 접근허용
- public : 가장 넓은 접근 허용함, 다른 패키지(폴더) 안의 클래스까지 접근가능
- default : 중간정도 접근 범위, 같은 패키지(폴더) 내에선 다 가능
- protected : 상속관련, 상속 배우고 난후 공부

접근제어자 범위 비교
가장넓음 public > default > protected > private 가장좁음

생성자 오버로딩
- 생성자 여러개 생성
- 구분되는 점이 있어야함

생성자 오버로딩 구분
1. 매개변수 자료형
2. 매개변수 개수
3. 매개변수 순서

메소드
- 언어에 따라 함수라고도 한다
- 쓰는 이유 : 객체의 동작 + 여러개 코드를 모아두고 한번 메소드가 정의되면 호출을 통해 재사용하기 위해서

메소드 만드는법
ex) public static void main(){}
1. 접근제어자 
2. static (특별한 경우에만 쓴다,공유 원할때)
3. 자료형 / void
4. 메소드이름 + ()

+ 자바에는 정적 클래스는 없다. 
+ 정적 메소드는 흔하지 않다.

 

접근제어자 예제

 

package p2022_06_29;

class Calculator {
	// 메소드
	void powerOn() {
		System.out.println("전원을 켭니다.");
		return;
	}

	int plus(int x, int y) { // 지역변수 : x, y, result
		int result = x + y;
		return result;
//		System.out.println("test");
	}
//return문 : plus() 메소드를 호출한 곳에 값을 돌려주는 역할
//return문은 메소드 가장 마지막 줄에 사용해야한다.
	double divide(int x, int y) {
		double result = x / (double) y;
		return result;
	}
	
	void powerOff() {
		System.out.println("전원을 끕니다.");
		return;
	}

}

public class CalculatorEx {
//p217 ~ 218
	public static void main(String[] args) {

		Calculator cal = new Calculator();
		cal.powerOn();
		
		int result1 = cal.plus(5, 6);
		
		byte x = 10;
		byte y = 4;
		double result2 = cal.divide(x,y);
		System.out.println("result2 : " + result2);
		
		cal.powerOff();
	}

}

- Calculator 클래스 앞에 private 쓰면 CalculatorEx 클래스에서 객체를 만들 수 없음(클래스 접근 불가)
- Calculator 클래스의 메소드 powerOff 앞에 private쓰면 cal.powerOn() 을 할 수 없음(메소드 접근 불가)

패키지 = 폴더
- 같은 폴더 안 = 같은 패키지 안
- 서로 다른 폴더 안 = 서로 다른 패키지 안 = public만 접근가능


위 예제의 부분1

	int plus(int x, int y) { // 지역변수 : x, y, result
		int result = x + y;
		return result;
		//System.out.println("test"); 오류남
        }

+ return문 : plus() 메소드를 호출한 곳에 값을 돌려주는 역할
+ return문은 메소드 가장 마지막 줄에 사용해야한다.
- 메소드가 실행되는동안 필요한 값들을 매개변수로 전달해줌(매개변수 = 지역변수)
- 메소드 실행되는동안만 스택에 값 존재, return되면 자동으로 지워짐
- 그래서 메모리 관리 크게 신경안써도 된다.

위 예제의 부분2

	cal.powerOn();

- 메인 메소드 안에서 객체 생성하며 생성자 호출후 메소드 호출
- 필드처럼 메소드에 접근할때도 객체.메소드() 로 호출함 (정적메소드가 아닌경우)

위 예제의 부분3

	int result1 = cal.plus(5, 6);


- Call by Value로 값 전달하며 메소드 호출
- plus()는 결과를 리턴자료형 int로 돌려줌 그래서 int result1으로 받아야하는것

위 예제의 부분4 (주의)

	double divide(int x, int y) {
		double result = x / (double) y;
		return result;
	}


- 리턴자료형이 double이므로 double형 값을 돌려준다
- int형인 x와 int형인 y를 산술연산시 int형으로 처리됨
ex) x = 10 , y = 4 이면 다 잘리고 2만 나온다. (손실 발생)
- 손실 발생을 막기 위해서 (double)을 붙여줘서 강제 형변환 -> 2.5
- 그걸 double로 return 시켜줌
- (double) 을 빠뜨리면 자동형변환되어서 2 -> 2.0 이 나옴(손실발생)
- 10/4 는 2.5이므로 살리려면 (double)해서 강제형변환시켜서 값이 double로 처리되도록 해야함.

위 예제의 부분5(CalculatorEx의 main 메소드 내부)

		byte x = 10;
		byte y = 4;
		double result2 = cal.divide(x,y);
		System.out.println("result2 : " + result2);


+ byte는 1바이트 정수형 자료형
- cal.divide에서 매개변수로 byte를 넘김 -> 근데 devide 메소드의 매개변수는 int 형 4바이트 이다. 
- 4바이트짜리 변수에 1바이트 짜리 값을 할당 => 컴파일러가 자동형변환시켜줌. 큰자료형으로 작은값으로 들어가므로
- 자동형변환되어서 위 코드 가능함

+ plus와 divide 메소드의 매개변수 이름들이 같지만 그 메소드 내에서만 사용되는 지역변수이므로 충돌이 발생하지 않음

메소드의 매개변수에 참조형이 오는 예제
- 값이 아닌 주솟값을 전달해야한다.
- sum1은 배열에 전달된 값들의 합을 돌려주는 함수

package p2022_06_29;

//p220 ~ 221
class Computer {
	// 주솟값 전달에 의한 메소드 호출(Call by Reference 방식)

	int sum1(int[] values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

	// vargus : 전달된 값은 배열로 받음
	int sum2(int... values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

}

public class ComputerEx {

	public static void main(String[] args) {

		Computer com = new Computer();
		
		int[] values1 = { 1, 2, 3 };
		int result1 = com.sum1(values1); // sum1() 메소드 호출 , 주솟값을 가진 values1을 넘김
		System.out.println("result1 : " + result1);

		int result2 = com.sum1(new int[] { 1, 2, 3, 4, 5 }); // sum1() 메소드 호출 , 배열을 만들어서 그 주소를 넘김
		System.out.println("result2 : " + result2);

		int result3 = com.sum2(1, 2, 3); // sum2() 메소드 호출 ,
		System.out.println("result3 : " + result3);

		int result4 = com.sum2(1, 2, 3, 4, 5); // sum2() 메소드 호출 ,
		System.out.println("result4 : " + result4);

	}

}

- "같은 int형 배열"의 주소값을 써서 메소드를 호출해야함
- Computer 클래스의 참조형변수인 int[] values는 아직 주솟값이 없는 상태 , new를 써서 int형 배열을 만들어 주솟값을 가진 걸 넘겨줘야함
- 그래서 main쪽에 int형 1차원배열을 만들어줌
- sum1에서 참조형이 매개변수로 왔으므로 같은 int형 배열의 주솟값을 넘겨야함
- new연산자를 아직 안썼으므로 아직 int[] values는 가리키는게 없음 
- 주솟값 전달에 의한 메소드 호출임
+ 값전달보다 주솟값 전달이 더 효율적이고 빠른 방식임

 

vargus (...)
- ...은 vargus 라고 함
- 전달된 값들은 1개일수도 여러개일수도 있지만 전달되는 값들은 모두 배열로 받음
- 매개변수가 있으면 매개변수의 개수대로 메소드 호출시 써줘야하지만 ... 은 int값을 1개 전달하든 여러개 전달하든 모두 배열로 처리됨

 

Call by Reference
- values1 int형 배열 힙메모리상에 4바이트 공간 3개 만들어지고 1,2,3이 들어가있고, 그 걸 values1이 그 스택에서 그 배열의 주소를 가지고 있음

 

	int result1 = com.sum1(values1)

- 에서 주솟값을 담고있는 values1을 전달 = 주소를 전달 = Call by Reference
- 주솟값이 없었던 Computer 클래스의 sum1의 values는 주솟값을 전달받아서 Computer 클래스의 values는 이제 이 {1,2,3} 배열을 가리키게됨
- 합을 구해서 리턴형 int로 result1에 값을 돌려줌

- 매개변수 중에서 참조형이 오는 경우 중 클래스/인터페이스가 가장 많다(배열은 많진 않다)
- API 제공 클래스 + 사용자 정의 클래스 => 이것들도 자료형이다
- 참조형변수는 주솟값을 가진다

 

매개변수에 주소값을 전달하는 법(위 예제 부분)

int[] values1 = { 1, 2, 3 };
int result1 = com.sum1(values1); // sum1() 메소드 호출 , 주솟값을 가진 values1을 넘김
System.out.println("result1 : " + result1);

int result2 = com.sum1(new int[] { 1, 2, 3, 4, 5 }); // sum1() 메소드 호출 , 배열을 만들어서 그 주소를 넘김
System.out.println("result2 : " + result2);

1.이렇게 values1 처럼 만들어진 배열공간의 주소값을 전달하는방법이 있다.
- values1이 가진 주솟값을 전달 


2.(new int[] { 1, 2, 3, 4, 5 } 처럼 오른쪽의 new연산을 써서 새로운 공간을 만들어서 그것의 주솟값을 넘겨줄 수도 있음
- 기억공간이 만들어지고 그거의 주솟값이 sum1 메소드의 매개변수로 넘어감
- 값을 받는 변수가 없기 때문에 이건 재사용이 안된다. 이후 가비지 콜렉터가 이 힙메모리상 배열을 지워버린다.
- 더이상 이 힙메모리에 접근할수없을때 해제된다.
- 할당시점은 new를 썼을때 할당된다

 

그림

 

+ 배열 생성

int[] score = {80,90,100} // new안쓰지만 힙메모리에 데이터 개수만큼 공간 만들어짐
int[] score = new int[]{80,90,100}

 

+ 배열등의 참조형을 매개변수로 쓰는이유
- 매개변수가 100개라면?
- 값들은 힙메모리에 저장시켜놓고 주솟값만 매개변수로 전달하는게 훨씬 효율적

 

vargus(위 예제 부분)

	// vargus : 전달된 값은 배열로 받음
	int sum2(int... values) {
		int sum = 0;
		for (int i = 0; i < values.length; i++) {
			sum += values[i];
		}
		return sum;
	}

- 메소드의 매개변수가 2개면 2개 전달 1개면 1개 전달 해야했었다.
- but vargus쓰면 1개 전달하든 2개전달하든 3개전달하든 모두 매개변수로 받을 수 있다
- 전달된 값은 모두 배열로 처리됨
ex) 첫번째 전달된값은 0번방 두번째 전달된 값은 1번방...
- 다만 자료형은 맞춰줘야함 int ... values 면 몇개이든 int형 값을 전달해야함

 

		int result3 = com.sum2(1, 2, 3); // sum2() 메소드 호출 ,
		System.out.println("result3 : " + result3);

- 1,2,3을 sum2로 전달하면 values가 1,2,3 을 배열로 저장함
- 전달된값들은 "같은 int형 배열"로 처리됨
- 자주쓰는 기능은 아님

 

		int result4 = com.sum2(1, 2, 3, 4, 5); // sum2() 메소드 호출 ,
		System.out.println("result4 : " + result4);

- 로 하면 1,2,3,4,5를 넘기고 배열로 받아서 처리해줌

 

메소드안에서 다른 메소드를 호출하기
- 여태껏은 메인메소드안에서만 메소드를 호출했었다
- 이젠 main 메소드가 아닌 일반 메소드안에서 다른 메소드를 호출해보자

 

package p2022_06_29;

// p227
// 클래스 내부에서 메소드 호출 : 메소드 안에서 다른 메소드 호출
class Calculator1 {
	int plus(int x, int y) {
		int result = x + y; //17
		return result;
	}

	double avg(int x, int y) {
		double sum = plus(x, y); // plus() 메소드 호출
		double result = sum / 2;
		return result;
	}

	void execute() {
		double result = avg(7, 10); //avg() 메소드 호출
		println("실행결과 : " + result); //println() 메세지 호출
	}

	void println(String message) {
		System.out.println(message);
		return;
	}
}

public class CalculatorEx1 {

	public static void main(String[] args) {

		Calculator1 mycal = new Calculator1();
		mycal.execute(); // execute() 메소드 호출
//		execute(); //오류발생
	}

}

1. 메인메소드에서 메소드 호출시
- 객체.메소드() 해서 메소드를 호출해야함

ex)

		Calculator1 mycal = new Calculator1();
		mycal.execute(); // execute() 메소드 호출
//		execute(); //오류발생

 

2. 일반메소드에서 메소드 호출시(같은 클래스 내부)
- 객체.메소드() 가 아니라 객체없이 그냥 메소드() 만으로 호출 가능하다!

ex)

		double result = avg(7, 10);

- avg() 메소드 호출 그냥 avg(7,10)만으로 호출했음

 

위 예제 흐름
- JVM이 main메소드 실행 -> mycal.execute() 호출함-> execute()이 실행됨
-> 그 메소드에서 avg메소드를 호출하면서 매개변수를 7, 10 넘겨줌
-> avg 매개변수의 x에 7, y에 10이 들어감, avg에서 다시 plus() 메소드를 7,10을 넘겨주며 호출
-> plus() 메소드에서 합을 구해서 합을 result 해서 plus()를 "호출"한곳에 값을 돌려줌 즉 avg로 돌아감
-> 그걸 avg의 sum이 받아서 %2 한뒤 돌려줌
- (주의) plus()가 돌려줄땐 int형인 17을 돌려줌, 근데 sum을 double로 받았으므로 17.0 해서 /2 해서 8.5가 result가 됨
-> 그 8.5 값을 avg를 호출한 execute()에 돌려줌, 그걸 println()메소드에 결과값을 넘겨서
-> println()이 출력시킴

+ 자바는 객체지향언어라서 호출할 메소드가 뒤에있어도 상관없다
+ execute() 아래 println() 있지만 execute()에서 println() 호출가능
+ 일반 메소드끼리는 메소드 이름만으로 서로를 호출한다

 

메소드 오버로딩(Method Overloading)
- 1개의 클래스 안에 동일한 이름을 가진 메소드를 여러개 정의하는 것.
- 생성자 오버로딩 처럼 메소드도 한개의 클래스 안에 동일한 이름의 클래스 여러개 정의할 수 있다

메소드 오버로딩 구분하는 법
1. 매개변수 자료형
2. 매개변수 개수
3. 매개변수들의 순서

- 한가지를 이상을 만족해서 구분이 되어야만 올바르게 메소드 오버로딩 시킨것임
* 나중에 메소드 오버라이딩과의 차이를 알아야 한다. 완전히 다른 개념
+ 메소드 오버라이딩 : 두 클래스 사이에 상속이 정의되어야만 사용가능

String 클래스 (API 문서)
- 필드 생성자 메소드 순
- 필드 : 메서드 바깥쪽에 정의되는 변수

- 생성자 : 클래스명과 동일, 형식상 괄호가 반드시 있다
- 매개변수가 없는 생성자는 기본생성자
- 나머지는 클래스명과 동일하게 생성자가 만들어지는데 구분이 되도록 정의됨
-> 생성자 오버로딩

- 메소드도 똑같은 이름을 가진 메소드들이 있다
ex) copyValueOf(char[] data) 와 copyValueOf(char[] data, int offset, int count)
- equlas 메소드, format 메소드들은 같은이름인 메소드가 여러개다 -> 메소드 오버로딩

 

메소드 오버로딩

class Calculator2{
	//정사각형의 면적을 구해주는 메소드
	double areaRectangle(double width) {
		return width * width;
	}
	//직사각형의 면적을 구해주는 메소드
	double areaRectangle(double width, double height) {
		return width * height;
	}
}

- 메소드가 같은 이름이다
- 매개변수가 1개인 areaRectangle 과 매개변수가 2개인 areaRectangle
- 매개변수의 개수가 다르므로 올바르게 메소드 오버로딩 되었음
- 매개변수 1개 전달하면 매개변수 1개인 areaRectangle() 이 호출되고 2개 전달하면 매개변수 2개인 areaRectanble()이 호출됨
- 메소드 오버로딩은 아무 언어나 되는게 아니라 객체지향언어만됨(c++,java는 되고 c는 안됨)

 

앞으로 공부할 내용

1. static이 붙은 정적 필드(정적변수)
2. static이 붙은 정적 메소드

변수
지역변수
멤버변수
정적변수
중에서 정적변수를 하는 것이다

3. 상수를 만드는 법 (Constant)
- final을 붙이거나 static final 을 붙인다
- 기존 변수에 final 붙이면 상수가 되는것
- final을 클래스, 필드, 메소드 에 붙일 수 있다-> 어디에 붙이냐에 따라 의미가 달라짐
4.접근제한자와 패키지 의 관계
5. getter와 setter 메소드

 

정적 필드 (정적 변수)

- static 이 붙은 변수 

ex)

static int a; // 그냥 변수앞에 static을 붙이면 정적변수가 됨

- static : 공유를 목적으로 해서 누구나 쉽게 접근하도록 만들때만 static 붙인 정적 필드형태로 만듬
- API 보면 클래스들 정적필드, 메소드들 정적메소드들 엄청 많다


ex) Math 클래스안엔 정적필드랑 정적메소드뿐
- 정적 필드는 클래스명.필드 로 사용
- 누구나 쉽게 생성할수있도록 따로 객체생성없이 클래스명.필드로 사용함

 

ex) 

int n = Integer.parseInt(String s);

- 에서 parseInt는 정적메소드라서 이렇게 클래스명.parseInt()로 사용함
- 세번째 변수인 정적멤버변수(정적 필드)
- 정적 필드 = 정적 멤버변수 = 정적 변수
- 메모리상에 할당되는 시점과 저장되는 영역이 (지역변수,멤버변수, 정적변수) 다 다르다(잠시 후 공부)

 

Math 클래스(정적 필드/메소드 예시)
- 내부에 정적 필드 뿐이다
- 정적필드 정적메소드 뿐
- 정적필드 E , PI 는 Math.E 로 접근가능
- 정적 메소드 , 정적 필드뿐이라 객체 생성할 필요가 없음
- math클래스는 생성자가 아무것도 없다 -> 생성자 자체를 못씀
- random() 메소드의 타입은 static double이다. 즉 정적메소드이고 리턴값이 double
- 정적 메소드 이므로 Math.random()으로 사용할수있다

 

정적변수의 메모리 할당 시점/장소
- 할당 시점 : 정적 멤버변수는 클래스가 메모리에 로딩되면(실행될때) 할당됨 
- 초기화 : 자동으로 설정되고 (정수형 0 실수형 0.0 논리형 false)
- 값 유지 : 프로그램이 종료될때까지 값을 유지한다
- 저장 영역 : 메모리의 static영역 (공유영역)에 자동으로 할당됨
- 저장 영역 : 공유영역 = 메소드영역 = static 영역 <->힙,스택과 다름
- 주의 : 장 오래 메모리에 상주하므로 많이쓰면 메모리가 부족해짐, 특별한경우아니면 만들지 않음

+ 특별한 경우, 반드시 정적멤버변수 만들어야하는 경우
- 싱글톤 : 객체생성을 1번만 하는 것, 이 경우엔 정적필드를 만들어야함

자동초기화
- 정적멤버변수는 자동초기화 된다.
- 배열과 마찬가지로 int는 0 , double 은 0.0, boolean은 false로 초기화 된다.
- 메소드영역에 값을 저장하고 한번 저장된값은 프로그램이 완전히 종료될때까지 값을 유지

정적 멤버변수에 접근하는 방법
- 정적 변수를 가지고 있는 클래스명으로 직접 접근 할 수 있다.

class StaticTest{
satic int a;

public static void main(String[] args) {
	System.out.println(StaticTest.a)
	}
}

- 정적메소드 사용시 클래스명.메소드()

 

정적 필드 / 정적 메소드 정리
- 정적 필드 = static이 붙은 변수
- 정적 메소드 = static이 붙은 메소드
- static이 붙은 필드를 가진 클래스가 로딩이 되면 이 정적필드는 메소드 영역에 저장이되고
자료형에 따라 기본자료형 변수들은 자동초기화됨

 

정적 멤버변수 만드는 법

- static 붙이기
- 예제 : NoneObject.java/UseNoneObject.java / UseNoneObject.java에만 메인메소드 있음

package p2022_06_29;

public class NoneObject {
    static int number = 3; // 정적 필드
    
    public static void printNumber() { // 정적 메소드
        System.out.println("number = " + number);
    }
}

- 메인메소드없으므로 독립적 실행은 안됨,
- 정적필드하나 정적메소드 하나 있는 NoneObject 클래스
- 이 클래스의 필드에 접근하고 메소드를 호출해보자

package p2022_06_29;

public class UseNoneObject {

    public static void main( String[] args ) {
    
//이 방식 잘 안쓴다
    NoneObject no = new NoneObject();
    System.out.println("no.number = " + no.number);
    no.printNumber();
    
//아래방식을 주로 쓴다
    System.out.println("NoneObject.number = " + 
					NoneObject.number);
    NoneObject.printNumber();
    
    }
}
출력
no.number = 3
number = 3
NoneObject.number = 3
number = 3

- NoneObject 클래스는 정적필드와 정적메소드를 가지고 있다
- UseNoneObject 클래스에서 접근할때 객체를 생성한 후 필드와 메소드를 사용할 수도 있지만
- 정적 필드와 정적메소드이므로 이렇게 안쓴다 (가능은 하지만 안쓴다)
- 필드 접근/메소드 호출하는 법 : NoneObject 클래스에서 .을 찍어서 정적필드, 정적메소드 로 접근

 

정적 필드 / 정적 메소드 접근 정리
- 누구나 쓸수있도록 하려고 static 붙인거임-> 객체생성해서 접근하지 않는다
- 결론 : 정적필드 , 정적메소드는 클래스명.필드, 클래스명.메소드() 해서 접근해라

정적 필드의 자동초기화
- 예제 : NoneObject.java 파일

package p2022_06_29;

public class NoneObject {
    static int number = 3; // 정적 필드
    
    public static void printNumber() { // 정적 메소드
        System.out.println("number = " + number);
    }
}

- 에서 static int number 에 3 초기화 안시킨다면?
- 자동으로 0으로 초기화시켜주므로 UseNoneObject 에서 실행해보면 0으로 출력됨

정적 멤버변수의 메모리 할당/해제(위 예제)
- NoneObject클래스가 로딩되자마자 number는 공유영역에 저장되면서 int형이니 0으로 초기화됨
- number의 값은 프로그램 종료시까지 계속 메모리에 상주함
- static 정적 필드 많이쓰면 메모리 부족

객체를 생성해서 정적필드/정적메소드에 접근(위 예제 부분)

//이 방식 잘 안쓴다
    NoneObject no = new NoneObject();
    System.out.println("no.number = " + no.number);
    no.printNumber();

- 가능은 하다
Q. 그럼 이때 new를 쓰면 정적필드는 어디로 저장될까? (질문하기) -> 그래도 메소드 영역

 

메모리 정리
- 힙 메모리에 저장 : JVM 시작할때 생성, 객체와  배열 저장, 가비지 콜랙터가 참조되지 않는 즉, 사용될수 없는 객체 제거
- 메소드영역 메모리 : static이 붙은 필드를 가진 클래스가 로딩이 되면 이 정적필드는 메소드 영역에 저장이됨.

 

static 필드의 의미(그 안의 값)

정적 필드 값의 유지 예시1 : StaticCount.java, Shared.java / 메인메소드는 Shared 클래스에만 있다

package p2022_06_29;

public class StaticCount {
    static int number = 3;
}

- 정적 필드 하나만 있다. 프로그램 종료까지 값을 계속 유지함
- 정적필드는 싱글톤을 만들때만 주로 쓴다. 객체를 1개만 생성해서 공유를 한다는 개념인 싱글톤

package p2022_06_29;

public class Shared {
    public static void main( String[] args ) {
    
        StaticCount sc1 = new StaticCount();
        System.out.println("sc1.number = " + sc1.number); //3
        
        sc1.number++;
        System.out.println("sc1.number = " + sc1.number); //4
        
        StaticCount sc2 = new StaticCount();
        System.out.println("sc2.number = " + sc2.number); //4
        
        sc2.number++;
        System.out.println("sc2.number = " + sc2.number); //5

        StaticCount.number ++;
        System.out.println("StaticCount.number = " + StaticCount.number); //6
    }
}
출력
sc1.number = 3
sc1.number = 4
sc2.number = 4
sc2.number = 5
StaticCount.number = 6

- 에서 StaticCount 클래스로 sc1라는 객체를 만들었음 
- (정적필드, 정적메소드 가진 클래스로 객체 만드는건 자주안하지만 가능하긴 함)
- sc1을 통해서 접근 된다!

 

값의 변화(값이 유지됨)
1. 처음 sc1.number 출력했더니 3 을 출력함 = 초기값이 3임
2. sc1.number++; 해서 sc1통해서 증가시킴 
3. sc1.number 출력시 4를 출력함

- 그 후 같은 StaticCount로 sc2 라는 새로운 객체도 만듬

4. 근데 힙메모리 영역이 아니라 메소드 영역이라는 공유영역이기 떄문에 sc2.number로 sc2에 접근해서 출력해도 number는 3이 아닌 가장 마지막에 저장한 값 4를 출력시킴
5. sc2.number 로 또 접근해서 ++ 증가시킴
6. sc2.number 출력시 5를 출력

- 마지막엔 객체가 아닌 StaticCount.number 로, 즉 클래스 명으로 접근한다 
6. StaticCount.number 를 ++
7. 출력하면 6이 나옴

 

정적 필드 값의 유지 예시2 : StaticTest01.java

package p2022_06_29;

class StaticTest {
	static int a = 10; // 정적 필드 : 메소드영역(공유영역) 에 저장
	int b = 20; // 인스턴스 멤버변수 : heap 메모리에 저장
}

class StaticTest01 {
	public static void main(String[] args) {
		System.out.println("StaticTest.a->" + StaticTest.a);
		StaticTest s1 = new StaticTest();
		StaticTest s2 = new StaticTest();

		System.out.println("s1.a->" + s1.a + "\t  s2.a->" + s2.a);
		System.out.println("s1.b->" + s1.b + "\t  s2.b->" + s2.b);

		s1.a = 100;
		System.out.print("s1.a->" + s1.a);
		System.out.println("\t  s2.a->" + s2.a + "  ");
		System.out.println(StaticTest.a);

		s1.b = 200;
		System.out.print("s1.b->" + s1.b);
		System.out.println("\t  s2.b->" + s2.b);
	}
}

- StaticTest01이 메인메소드가지고 있다
- StaticTest 클래스에는 static 정적 변수 1개, 일반적인 필드 1개 이렇게 있다
- 이런 일반적인 필드 는 instance 변수 또는 instance 필드 라고 부름
- 즉 a는 정적필드 b는 인스턴스필드

정적필드와 인스턴스 필드 비교
- StaicTest.a 는 정적필드기 때문에 클래스명. 으로 접근 가능
- 이때 초기값이 10으로 있기떄문에 10으로 출력됨

- 그 후 StaticTest 클래스로 new해서 객체 2개를 생성함 s1, s2
- new연산자로 할떄마다 힙메모리상에 새로운 공간을 할당받음
- 그래서 인스턴스 멤버변수인 b는 힙 메모리상에 할당받음
- 정적 변수인 a는 그대로 공유 영역에 있음

현재 상태
     a=10     //정적 멤버변수
 (공유영역)

s1             ------->  b=20
s2             ------->   b=20
                               
(Stack영역)                 (Heap영역)    


초기 상태
- b는 s1의 b, s2의 b 각각 있고, 힙메모리 상에 20으로 각각 있다.
- 이 값의 주소를 s1, s2가 스택메모리에서 갖고 있음

- a는 정적멤버변수라서 공유영역(메소드영역) 에 초기값 10을 저장하고 있는 상태
- 그래서 s1.a, s2.a는 10으로 출력됨 s1.b나 s2.b는 20으로 출력됨

변화
- s1.a 에 접근해서 값을 100으로 수정함
- s1.b 에 접근해서 값을 200으로 수정함

    a=100     //정적멤버변수
 (공유영역)

s1             ------->  b=200
s2             ------->   b=20
                               
(Stack영역)                 (Heap영역)   

변화된 상태
-  s1.a 와 s2.a 모두 출력시 100이 나옴
- 또한 클래스명으로 접근한 StaticTest.a  해도 100이 출력됨
- 즉 a는 가장 마지막으로 저장된 값이 공유됨

- s1.b만 200으로 수정됨(공유 안됨)
- s1.b를 출력하면 200, s2.b를 출력하면 20이 나옴

정적필드와 인스턴스 필드의 비교
- 정적 필드들은 마지막에 저장된 값을 계속 공유함
- 인스턴스 필드들은 클래스를 가지고 객체 생성할때마다 힙 공간 할당받으며 각각 초기값을 가지게 됨

정적 필드와 접근제어자 예제 : StaticTest02,03,04

StaticTest02.java
 
package p2022_06_29;

class StaticTest2 {
	private static int a = 10; // 정적 필드
	private int b = 20; // 인스턴스 필드

	public static void setA(int new_a) { // 정적 메소드
		a = new_a;
	}

	public static int getA() { // 정적 메소드
		return a;
	}
}

public class StaticTest02 {
	public static void main(String[] args) {
		//  System.out.println(StaticTest2.a); //a가 private으로 선언되어서 컴파일 에러 발생 
		System.out.println(StaticTest2.getA());

		StaticTest2 s1 = new StaticTest2();
		StaticTest2 s2 = new StaticTest2();

		s1.setA(10000);
		int res1 = s1.getA();
		System.out.println(res1);
		System.out.println(s2.getA());
	}
}
출력
10
10000
10000

- StaticTest2.a 로 접근이 안된다. 
- 이유 : 아무리 정적필드라도 외부클래스의 접근을 허용하지 않는 private 이 a 앞에 붙어서 다른 클래스인 StaticTest02 에서 접근시 에러 생김

 

private static int a = 10;

 

- 모순이 발생한다
- static은 공유를 하겠다는거고 private은 보호를 하는거라서 컴파일상 오류를 발생시키며 접근이 불가능하다.
- 결과적으로는 클래스명으로 접근하는 것이 허용되지 않음

 

private인 static 필드값 가져오는 방법
- getA() 메소드를 이용해서 접근한다
- getA() 메소드는 정적 메소드이고 public 이라 클래스명으로 접근가능하다\
ex)

System.out.println(StaticTest2.getA());

- 가능하다, 10이 출력됨

 

private인 static 필드값 설정하는 방법 (위 예제 부분)

		StaticTest2 s1 = new StaticTest2();
		StaticTest2 s2 = new StaticTest2();

		s1.setA(10000);
		int res1 = s1.getA();
		System.out.println(res1);
		System.out.println(s2.getA());

- StaticTest2로 새로운 객체 2개  s1, s2 생성함
- setA 메소드는 public static 이라 호출 가능하다. 클래스명으로 접근 가능하지만 이렇게 s1.setA(10000)처럼 객체로 접근도 되긴함
- s1.set(10000)으로 a값을 10000으로 셋팅
- s1.getA() 해서 접근도 되고, s2.getA() 해서도 됨 둘다 출력시 10000 됨

정적 필드와 접근제어자 결론
- private static하면 모순이 생겨서 결국은 다른 클래스에서 접근 못하는 필드임
- 그래서 StaticTest2.a가 에러생김(다른 클래스에서 호출하였기 떄문에)
-> private이 붙으면 정적 static 필드라도 다른 클래스에서 접근이 불가능함

정적 필드와 접근제어자 주의
- 정적 메소드 안에는 정적 필드만 사용가능함 (중요)
- 정적 메소드 안에 일반적인 필드 쓰면 오류발생 (저장영역과 기능이 다르기 떄문에)
- 정적메소드와 일반메소드는 기능이 다름

 

정적 필드 / 정적 메소드 주의 예제1 : StaticTest03

package p2022_06_29;

class StaticTest3 {
	private static int a = 10; // 정적 필드
	private int b = 20;

	public static void printA() { // 정적 메서드에서는 this를 사용하지 못함
		System.out.println(a);
		// System.out.println(b); //정적메소드 안에는 일반적인 필드 사용불가
		// System.out.println(this.a); //컴파일 에러 발생

	}

	public void printB() { // this는 인스턴스 메서드에서 여러 객체에 의해서
		System.out.println(b); // 메서드가 호출될 때 이를 구분하기 위해서 사용된다.
	}
}

public class StaticTest03 {
	public static void main(String[] args) {
		StaticTest3.printA();
		StaticTest3 s1 = new StaticTest3();
		StaticTest3 s2 = new StaticTest3();
		s1.printB();
		s2.printB();
	}
}

정적메소드를 쓸 때 주의사항


1. 정적 메소드에서는 this 레퍼런스 변수를 사용할 수 없다.
- this.는 힙메모리의 주소를 참조하는게 this.이고, this.는 개별적인 객체에 대한 주소를 가진 레퍼런스 변수라서 정적메소드 안에선 this. 를 사용할 수 없다


2. 정적 메소드에서는 일반적인 변수(인스턴스 필드)를 사용할 수 없다.
- 정적 메소드에서는 정적멤버변수만 사용가능함
- 일반적인 필드 = 힙메모리 이고,  정적필드 = 메소드 메모리(영역) 이라서 영역이 다르기 때문


3. 정적 메소드는 메소드 오버라이딩되지 않는다.
- static이 붙은 정적메소드는 메소드 오버라이딩이 되지 않는다.

 

+ 메소드 오버라이딩 : 두 클래스 사이 상속관계가 있을때, 부모로부터 상속되는 필드와 메소드 중, 메소드를 상속받을때, 이름과 형식은 똑같이 하면서 내부 내용은 다르게 쓰는 것.

정적 필드 / 정적 메소드 주의 예제2 : StaticTest04

package p2022_06_29;

class StaticTest4 {
	private static int a = 10; // 정적필드
	private int b = 20;

	public static void printA() {
		System.out.println(a);
//    System.out.println(b);   //컴파일 에러 발생 : 정적메소드 안 일반필드
	}

	public void printB() {
		System.out.println(b);
	}
}

public class StaticTest04 {
	public static void main(String[] args) {
		StaticTest4.printA();
		StaticTest4 s1 = new StaticTest4();
		StaticTest4 s2 = new StaticTest4();
		s1.printB();
		s2.printB();
	}
}

- 정적메소드 안에는 정적필드만 사용가능하다
- 일반 메소드 안에서만 일반필드 사용가능
- 정적 메소드 , 정적 필드는 클래스명. 해서 사용함 !    StaticTest4.printA();  
- 하지만 객체를 만들어서 객체.메소드 해서도 메소드 호출가능, 객체.필드 해서 필드 접근하는것도 가능

    StaticTest4 s1 = new StaticTest4();
    StaticTest4 s2 = new StaticTest4();
    s1.printB();
    s2.printB();

 

Math 클래스 (API 문서)

- 모두 정적필드 뿐
- 모두 정적메소드 뿐
- Math 클래스를 가지고 정적 필드와 정적메소드를 사용해보자

Math의 정적필드 2개
- E
- PI

Math의 생성자
- 생성자 자체가 없다
- 생성자는 제공되지 않는데 쓸수없다 Math 클래스로 new해서 객체생성하면 오류발생

Math의 메소드
- 모두 static 붙은 정적 메소드 -> 굳이 객체를 생성할 필요도 없다
- 그냥 Math.E , Math.random() 으로 쓰면됨

Math 클래스의 필드 사용 예제
+ Math라는 이름으로 사용자 지정 클래스 생성할 수 없다. 라이브러리에 이미 쓰고 있는 이름이라서

		System.out.println("E = " + Math.E);
		System.out.println("PI = " + Math.PI);

- Math클래스는 생성자가 제공되지 않기때문에 Math 클래스로 직접 객체를 생성할 수 없다
- 하지만 Math 클래스 = 정적 필드 + 정적 메소드 뿐이라서 객체 없어도 아무 문제 없음

Math 클래스 메소드 사용 예제(다양한 메소드 사용)

 

1. abs() 메소드
- 절대값을 구해서 결과를 돌려줌 
- abs() 메소드 여러개임 (메소드 오버로딩) , int, double, long, float등 타입별로 존재

	System.out.println("abs() = " + Math.abs(-10)); //절대값 , 결과는 10

 

2. ceil() 메소드
- 안에있는 소수점 이하 값을 무조건 올려버림 (올림) , 소수 첫째자리에서 올림함

	System.out.println("ceil() = " + Math.ceil(3.14)); //올림, 출력은 4.0

 

3. round() 메소드
- 반올림을 해주는 메소드
- 소수첫째자리에서 반올림해주고 결과는 long으로 돌려줌 11이 나옴 
- 매개변수 double, 반환은 long

	System.out.println("round() = " + Math.round(10.5)); //반올림, 출력은 11

 

4. floor() 메소드
- 무조건 내림을 해주는 메소드
- 소수점 이하는 다 버림, 매개변수 double, 반환은 double 
- 10.9 -> 10.0

	System.out.println("floor() = " + Math.floor(10.9)); //내림, 출력은 10.0

 

5. max() 메소드
- 최대값을 구해주는 메소드
- 메소드 오버로딩이 되어있다

ex) max(int a, int b) , max(double a, double b) 등
- 2개짜리 매개변수 있는 메소드들만 있다
- 자바에는 2개짜리만 제공함 -> 3개 이상이 필요하면 내가 만들어서 써야함 (파이썬은 제한 없음)
- 10과 20중 큰 값을 return 구문으로 돌려줌

		System.out.println("max() = " + Math.max(10, 20)); // 최대값 , 출력은 20

 

5. min() 메소드
- 최솟값을 구해주는 메소드
- 메소드 오버로딩이 되어있다
- min메소드도 2개짜리 매개변수 있는 메소드들만 있다

		System.out.println("min() = " + Math.min(10, 20)); // 최솟값, 출력 : 10

 

6. pow() 메소드
- 지수를 구할때 사용한다.
ex) 2의 3승 구할때 쓰는 메소드 Math.pow(2,3);
- pow(double a, double b) 이고 리턴은 double 형

		System.out.println("pow() = " + Math.pow(2,3)); // 2의 3승 , 출력은 8.0

 

7. random() 메소드
- 양수값으로 0.0보다 크거나같고 1.0보다 작은 범위의 실수형태의 난수 리턴
- 0.0 <= Math.random() < 1.0 범위의 난수 발생
- double형으로 리턴

		System.out.println("random() = " + Math.random());

 

8. sqrt() 메소드
- 제곱근을 구해주는 메소드
- 루트를 씌운값을 돌려줌
- 리턴은 double
ex) 루트5를 구할때 쓰는 메소드 Math.sqrt(5);

		System.out.println("sqrt() = " + Math.sqrt(5)); //루트5(제곱근5) , 출력은 2.23606...

 

우리가 쓰는 println() 의 구조

System.out.println("");

- System 클래스의 필드를보면 모두 정적필드
- 객체생성안하고 System.out으로 썼었던 이유 : 정적필드 중 out 이 있다
- out이 정적필드이기때문에 System.out을 쓴다

- 이 out이란 필드의 결과를 돌려주는 자료형이 PrintStream 이 리턴형이다 (객체로서 리턴)
- 즉 System.out은 자료형이 PrintStream이라는 자료형
- 이 PrintSteram 클래스를 찾아보면 println / print / printf 메소드가 들어있다(정적 메소드 아님)

+ void println()이 메소드 오버로딩되어있다. ex) void println(int i), void println(char x) 등

우리가 쓰는 Scanner 객체 생성하고 안에 System.in 썼던 이유
- Scanner 클래스를 찾아보면 Scanner(InputStream source)라는 생성자 가 있다.
- Scanner 생성자의 매개변수가 InputStream 타입이라서
- Scanner 객체 생성할때 생성자의 매개변수가 System.in 이었다
- System.in의 리턴형을 보면 InputStream 이다
+ in은 static이 붙은 정적필드라서 System.in 이라고 쓴다.

 

 과제
2022.07.04 / Hw1

반지름(r)이 5인 경우에 다음을 구하는 프로그램을 작성 하세요.
         (단, 결과는 소숫점 2째자리 까지 결과가 나타나도록 해야함)
              소수점은 DecimalFormat 클래스를 이용 해서 해결 하세요.

 

공식
         원주(원둘레)  2πr
         원의 면적 πr²
         구의 표면적 4πr²
         구의 체적(부피)  4/3πr³

 

의도

 API 문서에서 스스로 사용법 익히기

DecimalFormat 클래스 사용

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220704/CircleHw.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_07_04;

import java.text.DecimalFormat;

public class CircleHw {

	public static void main(String[] args) {

		// 반지름
		int r = 5;

		// 파이값
		final double pi = Math.PI;

		// 원주
		double n1 = 2 * pi * r;
		// 원의 면적
		double n2 = pi * Math.pow(r, 2);
		// 구의 표면적
		double n3 = 4 * pi * Math.pow(r, 2);
		// 구의 부피
		double n4 = ((double)4 / 3) * pi * Math.pow(r, 3);

		DecimalFormat df = new DecimalFormat("0.00");
		
		System.out.println("원주 : " + df.format(n1));
		System.out.println("원의 면적 : " + df.format(n2));
		System.out.println("구의 표면적 : " +df.format(n3));
		System.out.println("구의 부피 : " + df.format(n4));
		
//		System.out.printf("구의 부피 : " + "%.2f\n", n4); //도 가능하다
		

	}
}

 

 

출력

 

 

강사님 코드

package p2022_07_05;

import java.text.DecimalFormat;

class StaticTest07 {
	public static void main(String[] args) {

		int r = 5;
		double l; // 원주(원둘레)
		double s; // 원의 면적
		double v1; // 구의 표면적
		double v2; // 구의 체적(부피)

		l = 2 * r * Math.PI;
		s = r * r * Math.PI;
		v1 = 4 * Math.PI * r * r;
		v2 = 4.0 / 3 * Math.PI * r * r * r; // pow(r,3)

		DecimalFormat df = new DecimalFormat("###.00");

		System.out.println("원주 : " + l);
		System.out.println("반지름이 " + r + "인 원의 면적 " + s);
		System.out.println("구의 표면적 : " + v1);
		System.out.println("구의 체적 :" + v2);
		System.out.println();

		System.out.println("원주 : " + df.format(l));
		System.out.println("반지름이 " + r + "인 원의 면적 " + df.format(s));
		System.out.println("구의 표면적 : " + df.format(v1));
		System.out.println("구의 체적 :" + df.format(v2));
		System.out.println();

//	System.out.printf("%f", l);
		System.out.printf("%.2f", l);
		System.out.println();
		System.out.format("%.2f", s);
		System.out.println();
		System.out.format("%.2f", v1);
		System.out.println();
		System.out.format("%.2f", v2);
	}
}

 과제
2022.07.01 / Hw1

       키보드를 통해서 주민번호를 입력 했을때 유효한 
          주민번호 인지 아닌지를 판별하는 프로그램을 작성하세요
          (단, 유효하지 않은 주민번호의 경우에는 메시지를 출력)
      
       1. 주민번호 앞자리 6자리가 아니면 메시지 출력
       2. 주민번호 뒷자리 7자리가 아니면 메시지 출력
       3. 유효한 주민번호 아니면 메시지 출력

 

 

■ 주민 등록 번호 타당성 검사법
1. 주민 번호 각 자리에 해당 숫자를 곱한다.

 

예)    8  0  0  1  0  1   -   1  2  3  4  5  6  7
                                                        체크용 번호 : 마지막 숫자 7
   ☓ )2  3  4  5  6  7        8  9  2  3  4  5


      (8*2)+(0*3)+(0*4)+(1*5)+(0*6)+(1*7)+(1*8)+(2*9)+(3*2)+(4*3)+(5*4)+(6*5) = 122


2. 1번의 연산 결과를 11로 나누어서 나머지를 구한다.
   122 / 11 = 11 ............ 1
                  (몫)         (나머지)

3. 11에서 나머지 값을 뺀후 “체크용 번호와”와 비교해서 같으면 올바른      
   주민번호, 그렇지 않으면 틀린 주민 번호
   11 - 1 =    10      ≠       7
              (연산결과)       (체크용 번호)

   만약, 연산결과가 10이상이면, 다시 10으로 나누어서 그 나머지를 체크용    번호와 비교 한다.
    10 / 10 = 1 .........  0      ≠      7
              (몫)     (나머지)        (체크용 번호)

 

테스트 값

        1 1 1 1 1 1 - 1 1 1 1 1 1 8 (올바른 주민번호)

     8 0 0 1 0 1 - 1 2 3 4 5 6 7(틀린 주민번호)

 

 

의도

String 클래스의 메소드 활용

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220701/JuminHw.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_07_01;

import java.util.Scanner;

public class JuminHw {
	public static void main(String[] args) {

		// 키보드로 주민번호 입력받기
		Scanner sc = new Scanner(System.in);
		System.out.println("주민번호 앞자리를 입력 하세요?");
		String jumin1 = sc.nextLine();

		System.out.println("주민번호 뒷자리를 입력 하세요?");
		String jumin2 = sc.nextLine();

		// 유효성 검사
		if (jumin1.length() != 6) {
			System.out.println("주민번호 앞자리 6자리를 입력하세요.");
		} else if (jumin2.length() != 7) {
			System.out.println("주민번호 뒷자리 7자리를 입력하세요.");
		} else if (!check(jumin1, jumin2)) {
			System.out.println("틀린 주민번호 입니다.");
		} else {
			System.out.println("올바른 주민번호 입니다.");
		}
	}

	static boolean check(String jumin1, String jumin2) {
		// 공식의 숫자들
		int[] a = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
		int total = 0;

		// 앞자리 처리
		for (int i = 0; i < jumin1.length(); i++) {
			String j = jumin1.substring(i, i + 1);
			total += a[i] * Integer.parseInt(j);
		}

		// 뒷자리 처리(마지막 숫자 빼기)
		for (int i = 0; i < jumin2.length() - 1; i++) {
			String j = jumin2.substring(i, i + 1);
			total += a[i + 6] * Integer.parseInt(j);
		}

		// 연산
		int total2 = total % 11;
		int total3 = 11 - total2;

		if (total3 >= 10) {
			total3 %= 10;
		}

		// 체크숫자와 같은지 확인
		if (total3 == Integer.parseInt(jumin2.substring(6, 7))) {
			return true;
		} else {
			return false;
		}
	}
}

 

 

출력

 

 

강사님 코드

package p2022_07_04;

import java.io.InputStream;
import java.util.Scanner;

public class JuminCheck01 {

	// 주민번호 타당성 검사하는 메소드
	public static boolean juminCheck(String jumin) {
		// jumin = "9010101234567";
		int total = 0;
		int total2;

		// total += Integer.parseInt(jumin.substring(0, 1)) * 2;
		// total += Integer.parseInt(jumin.substring(1, 2)) * 3;
		// total += Integer.parseInt(jumin.substring(2, 3)) * 4;
		// total += Integer.parseInt(jumin.substring(3, 4)) * 5;
		// total += Integer.parseInt(jumin.substring(4, 5)) * 6;
		// total += Integer.parseInt(jumin.substring(5, 6)) * 7;
		// total += Integer.parseInt(jumin.substring(6, 7)) * 8;
		// total += Integer.parseInt(jumin.substring(7, 8)) * 9;
		// total += Integer.parseInt(jumin.substring(8, 9)) * 2;
		// total += Integer.parseInt(jumin.substring(9, 10)) * 3;
		// total += Integer.parseInt(jumin.substring(10, 11)) * 4;
		// total += Integer.parseInt(jumin.substring(11, 12)) * 5;

		int[] mul = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };

		for (int i = 0; i <= 11; i++) {
			total += Integer.parseInt(jumin.substring(i, i + 1)) * mul[i];
		}

		total %= 11; // total = total % 11;
		total2 = 11 - total;
		if (total2 > 9)
			total2 = total2 % 10;

		if (total2 != Integer.parseInt(jumin.substring(12, 13))) {
			return false; // 체크용 번호와 일치하지 않을때
		} else {
			return true;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		JuminCheck01 jc = new JuminCheck01();

		InputStream is = System.in;
		Scanner sc = new Scanner(is);

		System.out.println("주민번호 앞자리를 입력 하세요?");
		String jumin1 = sc.next(); // 900101
		System.out.println("주민번호 뒷자리를 입력 하세요?");
		String jumin2 = sc.next(); // 1234567

		if (jumin1.length() != 6) {
			System.out.println("주민번호 앞자리는 6자리 입력");
		} else if (jumin2.length() != 7) {
			System.out.println("주민번호 뒷자리는 7자리 입력");
		} else if (!juminCheck(jumin1 + jumin2)) {
			System.out.println("잘못된 주민번호 입니다.");
		} else {
			System.out.println("올바른 주민번호 입니다");
		}

	}

}

변수의 종류
1. 지역변수
2. 멤버변수
3. 정적변수

지역변수
- 메소드 안에서 정의되고 안에서 사용되는 변수
- 기본자료형일때 메소드 호출시에 스택메모리에 할당되고, 메소드 실행이 종료되면 자동으로 메모리가 해제됨

멤버변수 (= 필드 = 전역변수)
- 메소드 바깥쪽에 정의되는 변수
- 기본자료형 멤버변수는 heap 메모리 영역에 저장됨.
- 그 클래스(생성자,메소드)안에서 모두 사용이 가능함 = 전역변수
- 자동으로 초기화 됨
- 참조형을 이용해서 new 연산자로 객체를 생성시 heap 메모리 영역에 새로운 공간을 할당받는데, 그 공간이 멤버변수를 위한 공간
- 가비지 콜렉터가 필요없는 힙메모리상의 변수들을 지워줌

변수와 메모리
- 기본자료형 && 지역변수 -> 스택 메모리
- 기본자료형 && 멤버변수 -> 힙 메모리
- 참조형 && 지역변수 -> 힙 메모리에 값, 스택 메모리에 주소값
- 참조형 && 멤버변수 -> (아직 모름)

클래스 형태의 자료형
ex) Animal클래스는 클래스 형태의 자료형이다.
- 사용자가 만들어쓰는 자료형이다

클래스
- 필드
- 생성자
- 메소드

접근제어자를 사용하는 곳
- 클래스
(클래스를 구성하는)
- 필드
- 생성자
- 메소드

접근제어자 역할
- 외부 클래스에서의 접근을 막을지 허용할지 설정

생성자의 역할
- 객체를 생성할때 호출되면서 이 필드값을 원하는 값으로 초기화 시키는 역할

생성자 종류
- 매개변수가 없는 생성자 = 기본생성자
- 매개변수가 있는 생성자

생성자와 메소드의 구분
1. 생성자 앞에는 접근제어자만 온다! 
2. 생성자는 클래스명과 동일한 이름

필드의 역할
- 변수기 때문에 값을 저장하는 역할만 함

메소드
- 기능이 가장 많음
- 동적인걸 표현함

필드의 초기화
- 배열처럼 필드는 자동 초기화가 된다. (int는 0으로 초기화)

사용자정의 클래스 예시

Animal a1 = new Animal();


- Animal은 클래스 자료형
- a1은 레퍼런스 변수
- new는 연산자
- Animal() 은 생성자를 호출함

생성자 안만들면
- 컴파일러가 자동으로 기본생성자 만들고 호출

+ 생성자 만들었을땐
- 매개변수가 있는 생성자를 만들면 기본생성자는 자동으로 만들어지지않음
- 만들어진 생성자들만 사용가능

생성자 호출하는 방법
1. 객체를 생성할때 호출됨
2. this()를 통해 호출할 수도 있음

필드 접근
- 객체.필드 로 접근
ex) a1.age 처럼 .으로 접근 가능하다
ex) age만으로 접근 불가능하다
- 힙메모리의 필드에 접근하기 위해서는 반드시 주솟값을 가지고 있는 a1으로 참조해서만 접근 가능

파일과 클래스
- 한개의 소스파일안에 클래스 여러개 작성해도 나중에 바이트 코드는 따로 만들어짐
ex) 한개의 파일안에 클래스가 2개들어가는 예제 CarEx

파일명
- public 접근 제어자는 메인 메소드를 가진 클래스만 쓸 수 있고 그 클래스와 파일명이 같아야함
- 하나의 소스파일에는 public class 가 하나만 올 수 있고 public class명과 파일명이 같아야함

 

예제

 

class Car {
	// 필드(field)
	String company = "현대 자동차"; //주어진 초기값
	String model = "그랜저";
	String color = "검정";
	int maxSpeed = 350;
	int speed;

	// 생성자(Constructor)
	public Car() {// 기본 생성자

		System.out.println("생성자 호출 성공");
	}
}

public class CarEx {
	public static void main(String[] args) {

		// 객체 생성
		Car mycar = new Car();
		System.out.println("제작회사 : " + mycar.company);
		System.out.println("모델명 : " + mycar.model);
		System.out.println("색깔 : " + mycar.color);
		System.out.println("최고속도 : " + mycar.maxSpeed);
		System.out.println("현재속도 : " + mycar.speed);

		// 필드값 변경
		mycar.speed = 60;
		System.out.println("수정된 속도 : " + mycar.speed); // 60

	}

}

- 선언과동시에 초기화가 되지 않은 speed는 , 객체가 생성되어 힙메모리상에 speed 공간이 생성될때
0으로 초기화 된다
- Car()은 생성자가 아니라 생성자를 호출하는 거임

그림

 

의미있는 객체 vs 의미없는 객체

- main 메소드를 가진 CarEx 클래스로 객체를 만들면? -> 만들어지지만 의미 없는 객체
- 멤버(필드,생성자,메소드) 가 있는 클래스로 객체를 만들어야 의미있는 클래스이다.

 

생성자 호출하는 방법
1. 객체를 생성할때 호출됨
2. this()를 통해 호출할 수도 있음
-  99%는 클래스로 객체를 생성할때 생성자가 호출됨

 

ex)

		// 객체 생성
		Car mycar = new Car(); //객체를 생성할때 생성자가 호출된다.
		CarEx car = new CarEx(); // 의미 없는 객체

필드 수정하기

 

		// 필드값 변경
		mycar.speed = 60;

- 필드는 객체를 통해서 접근해야한다.

 

지역변수와 필드의 생성과 소멸
- 지역변수는 메서드 호출시 생성, 메소드 종료시 삭제
- 필드는 클래스로 객체를 생성할때 new 연산자를 통해 힙공간에 공간 할당받고, 나중에 이 공간을
참조할 수 있는 주소가 더이상 없을때 가비지 콜렉터가 이걸 쓰레기로 인식하고
힙메모리상의 그 공간을 지워버림

필드 = 멤버변수
- 기본자료형들은 자동으로 초기값이 설정됨 ex) boolean 은 false로
- 클래스,배열, 인터페이스들은 참조할 주소가 없다는 의미인 null 로 초기화됨. 
- 필드는 힙메모리상에 저장됨

 

//p303
class FieldInitValue{
	//필드
	byte byteField;
	short shortField;
	int intField;
	long longField;
	
	float floatField;
	float doubleField;
	
	char charField;
	boolean booleanField;
	
	int[] arrField;
	String referenceField;
}
public class FieldEx {

	public static void main(String[] args) {

		FieldInitValue f = new FieldInitValue();
		
		System.out.println("byteField : " + f.byteField);
		System.out.println("shortField : " + f.shortField);
		System.out.println("intField : " + f.intField);
		System.out.println("longField : " + f.longField);
		
		System.out.println("floatField : " + f.floatField);
		System.out.println("doubleField : " + f.doubleField);
		
		System.out.println("charField : " + f.charField);
		System.out.println("booleanField : " + f.booleanField);
		
		System.out.println("intField : " + f.arrField);
		System.out.println("stringField : " + f.referenceField);
		
		
	}

}

출력값

byteField : 0
shortField : 0
intField : 0
longField : 0
floatField : 0.0
doubleField : 0.0
charField :

 

초기화 값
- 정수형은 0으로 초기화
- 실수형은 0.0으로 초기화
- char 필드는 은 초기화 안된다
- 논리형 필드는 false로 초기화
- 배열과 클래스 필드는 null로 초기화 된다
* null : 참조할 주소가 없다는 의미

Q. 참조형이 필드일때 즉 String 클래스가 필드로서 있을때 이걸 어떻게 할당하나?
A. f.referenceField = "자바" 

해제시점
- f처럼 그 객체 공간을 힙메모리상에 있는 그 개게 공간을 가리키고 있는 참조 변수가 있으면 괜찮다.
- f처럼 그 공간을 가리키고있는 참조 변수가 없으면 가비지 콜렉터가 자동으로 그 힙메모리의 공간을 지움
- 그때가 해제되는 시점임 

생성자
- 생성자 앞에는 접근제어자만 온다
- 생성자를 통해서 내가 원하는 초기값을 그 객체의 필드로 초기화 시킬 수 있다
- 매개변수가 있는 필드 만들어서 할 수 있다
- 객체가 생성될때 호출되어 필드들을 초기화 시키는 역할만 함
- 기본생성자는 객체가 생성될때 컴파일러가 자동으로 생성해준다

클래스명 주의
- 동일한 패키지 안에 같은 이름의 클래스가 있을땐 오류 발생
- 동일한 패키지 = 동일한 폴더 내
- .class 라는 바이트코드는 따로 만들어지는데 같은 이름인 파일이 이미 있으므로 
- 메인메소드를 가진 클래스명으로 파일명을 일치시켜야함 = 메인메소드를 가진 클래스만 public class 일 수 있어서
- 메인메소드가 없다면 public을 가진 class 명과 일치시켜야함

 

클래스 예시 (MyDate Class)

package p2022_06_28;

class MyDate {
	private int year; // 필드
	private int month;
	private int day;

	public MyDate() { // 기본생성자(Default Constructor)
		System.out.println("[생성자] : 객체가 생성될 때 자동 호출됩니다.");
	}

	public void print() {
		System.out.println(year + "/" + month + "/" + day);
	}
}// MyDate end

public class ConstructorTest02 {
	public static void main(String[] args) {
		MyDate d = new MyDate();
		d.print();
// 접근제어자가 private 이기 때문에 외부 클래스에서 직접 접근할 수 없다.
//	System.out.println(d.year);
//	MyDate dd =  new MyDate();
	}
}

 

1. MyDate Class 필드
- MyDate Class의 필드들 접근제어자가 private이다.
2. MyDate Class 생성자
- 생성자가 1개 있다. 생성자 이름은 클래스명과 같고 앞엔 접근제어자만 있다
- 매개변수가 없는 생성자 = 기본생성자
3. MyDate Class 메소드
- static이 없다 
- 대부분의 메소드는 static 안쓴다
- 나중에 싱클톤 만들땐 정적 메소드 형태로 만듬
- void가 있으므로 return;필요없음

메소드가 하는일 3가지
- 필드값을 출력하는 일
- 필드값을 수정하는 일
- 메소드앞엔 자료값이 오기때문에 호출했을때 값을 돌려주는 역할도 가능

클래스의 실행 정리
- 메인메소드가 없는 MyDate 클래스는 main메소드가 안에 없기때문에 독립적인 실행은 불가능하고
컴파일까지만 가능
- 실행하려면 메인메소드를 추가하든지 메인메소드를 가진 클래스에서 실행을 해줘야한다.
- 클래스 내에서 자기 자신의 클래스로 객체를 만드는거 -> 의미없다
- 필드/생성자/메소드 가진 클래스로 객체 만들어야 의미있다.

 

MyDate d = new MyDate();

- new는 myDate 의 필드들을 저장할 공간을 힙메모리에 생성함
- 그리고 그 공간을 자동으로 0으로 초기화함
- 즉 year month day 의 값을 힙에 저장하기 위한 공간을 생성
- 그림

 

객체 생성시점 벌어지는 일
- 접근제어자와 상관없이 year month day는 초기값 0으로 설정
- myDate() 생성자를 호출하라는 코드로 인해 생성자 호출됨, 그 생성자로 가서 실행을 함(여기선 출력)

필드값 접근(출력)방법1
- d.year d.month d.day 로 접근시 여기선 오류가 발생한다
- private을 필드 앞에 붙이면 외부 클래스의 접근을 허용하지 않기때문에 d.year 처럼 필드에 접근이 불가능하다

필드값 접근(출력)방법2
- 메소드를 활용하는 방법을 사용해야함!
- 메소드 앞의 접근 제어자가 public인 print() 메소드를 이용하면 필드값을 출력 가능하다 d.print(); 로 필드값을 출력한다.

접근제어자와 클래스
- 필드는 private이지만 private은 같은 클래스내에서는 접근이 된다
- 그래서 MyDate안 클래스 안의 print() 메소드는 필드들에 접근이 가능한것이다.
- 가장 좁은 접근 private 가장 넓은 접근 public 이다
- public은 모두 접근 가능, 클래스나 패키지 달라도, 같은 파일이든 다른 파일이든 다 접근 가능
- private 같은 클래스 내에서만 접근 허용

생성자
- 생성자는 필드를 초기화하는 역할
- 0 대신 원하는값으로 초기화시켜야할때 생성자에서 초기화해준다

메소드
- 값을 돌려주기도 하고 수정하기도 하고 출력하기도 함

 

접근제어자
- public : 다른 패키지에서도 접근 가능
- default : 동일 패키지 내에서만 접근 가능
- protected : 상속 받은 클래스에서 접근 가능
- private : 자기 클래스에서만 접근 가능(정보은닉)

 

클래스 예시(기본생성자로 초기화)

package p2022_06_28;

class MyDate03 {
	// 필드
	private int year;
	private int month;
	private int day;

	// 생성자 : 객체를 생성할때 생성자가 호출되고, 필드값을 초기화 시켜주는 역할
	public MyDate03() { // 기본 생성자
		year = 2016;
		month = 4;
		day = 1;
	}

	public void print() { // 메소드
		System.out.println(year + "/" + month + "/" + day);
	}
}// MyDate end

public class ConstructorTest03 {
	public static void main(String[] args) {
		MyDate03 d = new MyDate03();
//    				생성자호출
		d.print();
	}
}

- 필드값이 생성자가 호출되기 전에는 0으로 모두 초기화 되었었지만
- 생성자를 호출하면서 2016 4 1 로 바뀜
- 원하는 값으로 초기값을 설정하고 싶으면 생성자를 씀

 

매개변수를 가진 생성자 예시
- 기본생성자가 아니라 매개변수를 가진 생성자
- 생성자는 기본생성자든 매개변수를 가지든 필드값을 초기화시키는 역할임 

 

클래스 예시(매개변수가 있는 생성자로 초기화)

package p2022_06_28;

class MyDate05 {
	private int year; // 필드
	private int month;
	private int day;

	public MyDate05() { // 기본생성자
	}

	public MyDate05(int new_year, int new_month, int new_day) { // 매개변수가진 생성자
		year = new_year;
		month = new_month;
		day = new_day;
	}

	public void print() { // 메소드
		System.out.println(year + "/" + month + "/" + day);
	}
}

public class ConstructorTest05 {
	public static void main(String[] args) {
		MyDate05 d = new MyDate05();
		d.print();

		MyDate05 d2 = new MyDate05(2017, 7, 19);
		// 매개변수가 있는 생성자 호출
		d2.print();
	}
}

- 기본생성자를 주석처리하면 아래에 있는  MyDate05 d=new MyDate05();  가 오류생김
- 매개변수를 가진 생성자를 만들땐 컴파일러가 기본생성자 만들어주지 않기때문에!
- 내가 아무 생성자도 안썼을떄만 기본생성자 생성해줌

 

기본생성자 자동생성 정리
- 기본생성자는 객체 생성할때 컴파일러가 자동으로 만들어 주지만,
- 예외적으로, 매개변수를 가진 생성자가 있을 경우에는 더이상 기본 생성자를 만들어 주지 않는다.
-> 원하면 내가 기본생성자도 써야함!

매개변수를 가진 생성자
- 매개변수가 있는 생성자를 쓸때 매개변수에 원하는 값 써서 초기화 
- 객체 생성할때마다 그 객체의 필드를 초기화
- 매개변수를 가진 생성자를 호출

    MyDate05 d2=new MyDate05(2017, 7, 19);
    d2.print();

- 생성자가 호출될때 생성자의 매개변수는 지역변수다.

	  public MyDate05(int new_year, int new_month, int new_day){	//매개변수가진 생성자
   			 year=new_year;
   			 month=new_month;
  			  day=new_day;
  		}
		MyDate05 d = new MyDate05();
		d.print();

    		MyDate05 d2=new MyDate05(2017, 7, 19);
    		//매개변수가 있는 생성자 호출
    		d2.print();

- 필드값을 초기화 하고 있다
- 이렇게 필드랑 이름이 다를때는 상관없지만 필드와 이 생성자의 매개변수가 이름이 같을때는  this 연산자사용(곧 공부)
- print()메소드는 필드값을 출력하는용도로 사용되고 있다.public 메소드라서 다른 메소드에서 접근 가능하다
- 2017이 new_year로, 7이 new_month로, 19가 new_day로 가서 이걸 생성자에서 year= new_year; 필드값을 원하는 값으로 초기값 설정 가능

 

호출과정
1. 한 파일 내 두개의 클래스는 이미 컴파일이 된 상태
2. JVM은 가장 먼저 main을 실행함
3. 이때 MyDate05 의 객체인 d 생성함.
4. 기본생성자를 호출함
5. 힙에 필드위한 기억공간/필드값 자동 초기화

+ 매개변수 있는 생성자 있는경우엔 기본생성자 만들어둬야함 
+ 안에 아무 내용없어도 형식이라도 만들어둬야함

 

그림



매개변수와 필드의 이름이 같은 경우
- 매개변수의 값이 필드를 초기화 할 수 없음
- 오류가 생기진 않는다.
- 필드(멤버변수) 쪽에 this. 라고 붙여야함, this. 가 있으면 이름이 같아도 값 대입 가능

 

this. 예제

 

package p2022_06_28;

class MyDate04{   
  int year;    
  int month;    
  int day;  

  public MyDate04(){
    year=2016;    month=4;    day=1;
  }
 
  public MyDate04(int year,int month,int day){
   this.year=year;
   this.month=month;
   this.day=day;
  }
  public void print(){
	System.out.println(year+ "/" +month+ "/" +day); 
  }
}// MyDate end

public class ConstructorTest04 {     
  public static void main(String[] args) {
    MyDate04 d=new MyDate04();	//1생성자호출
    System.out.println(d.year); //바로 접근해서 출력
    System.out.println(d.month);
    System.out.println(d.day);
    d.print(); //메소드통해 출력

    MyDate04 d2=new MyDate04(2017, 7, 19);
    System.out.println(d2.year); //바로 접근해서 출력
    System.out.println(d2.month);
    System.out.println(d2.day);
    d2.print();
  }
}

d객체
- 여기 필드는 디폴트 접근제어자이므로 d.year로 바로 접근해서 출력 ㅏㄱ능
- 메소드 통해서 출력하는 방법되 있다.
- '//1생성자호출'에서 기본생성자를 호출해서 year=2016,month=4,day=1 로 초기화됨

d2객체
- 또다시 heap 상에서 새로운 공간을 생성함.
- 이 공간은 d2객체의 필드들을 저장하기 위한 공간이다

this.
- 내부 레퍼런스 변수
- this는 그 객체 를 의미함
- 객체 생성되어 매개변수 있는 생성자 호출할 때, 이 객체 d2가 가진 주솟값을 갖는게 this다
- 즉 this == d2를 의미한다 ( d2를 받는다 )
- 사용법 : this.필드 = 매개변수
- 생성자 안에서 멤버변수와 매개변수가 이름이 동일한 경우에 사용

- d2객체를 생성했을 때, 매개변수를 3개 가진 생성자를 호출한다, 그럼 year month day 값은 2017, 7, 19 로 설정이 된다.
- d2가 이 것들을 가리키고 있는데 this는 이 d2가 가리키는 것들을 똑같이 가리킨다 
- 즉 d2랑 this는 같은 주소를 갖고 있다
- d2.year == this.year
+ this. 을 안썼다고 오류가 생기진 않지만 매개변수의 값이 필드로 들어가지 않음 (값전달이안됨)-> 출력시 다 0이 나오는걸로 알 수 있다

 

그림



생성자의 매개변수로 멤버변수값 초기화하는법
1. 멤버변수와 매개변수의 이름을 다르게 설정
2. 멤버변수와 매개변수의 이름이 같고, 멤버변수 앞에 this를 붙인다.

생성자의 사용법
- 객체마다 언제나 같은 값으로 필드값 다 같게 설정할땐 기본생성자를 사용하고
- 객체가 생성될때마다 초기화할 값을(필드를) 다 다르게 설정하기 위해선 매개변수가 있는 생성자를 사용하는것임!

메소드가 하는 일
- 필드값을 수정, 출력, 필드값을 돌려주기

이클립스 생성자 만들기 기능
- 이클립스에 생성자 만들어주는 기능이 있다
- 오른쪽마우스 -> Source -> Generate Constructor using Fields
- Insertion point : 생성자가 들어갈 위치 지정
- Omit call to default constructor super() : 생성자 내부에 super()를 생략하기 위해서 체크(상속 공부한 뒤 공부)
- 자동으로 생성된 생성자에도 this 사용한다


this. 정리
- 생성자에서도 사용가능하고 메소드에서도 사용가능! (메소드에서 this.쓰는거 곧 한다)
- 생성자와 메소드 안에서 멤버변수와 매개변수 이름이 동일한 경우에 주로 사용함
- ex)

public Test(int a, int b) {
	this.a = a;
	this.b = b;
}


this() 정리
- 같은 클래스안에 있는 생성자를 호출할때 사용함(다른 클래스의 생성자는 안됨)
- 객체를 생성할때만 생성자를 호출할 수 있는게 아니라 this()를 통해서도 생성자를 호출 할 수도 있다.
- this()는 많이 쓰이진 않음

+ 상속 공부 후 super. , super() 를 배울것

메소드를 통해 필드값을 set 시키는 예제 (MyDate06/ConstructorTest06)

- 생성자를 통해서 객체를 생성할 때 필드값을 초기화 시킬 수 있다.
- 하지만 "중간에" 어떤 필드값 하나를 수정하고 싶을떄 생성자는 그 역할을 할 수 없다
- 생성자는 객체 호출시에 실행되므로
-> 중간에 변경하고 싶을때 메소드를 통해서 필드값 수정할 수 있다

메소드 역할 정리
1. 필드값 출력
2. 필드값 수정/변경 (생성자는 못함) -> set
3. 리턴자료형을 통해서 필드값을 돌려주는 역할도 함 (메소드 호출한곳으로 돌려줌) -> get

 

package p2022_06_28;

class MyDate06 {
	private int year; // 필드
	private int month;
	private int day;

//  public MyDate(){	//default 생성자
//  }  
	public MyDate06(int new_year, int new_month, int new_day) {
		year = new_year; // 2017
		month = new_month; // 7
		day = new_day; // 19
	}

	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	public void print() {
		System.out.println(year + "/" + month + "/" + day);
	}
}

public class ConstructorTest06 {
	public static void main(String[] args) {

		MyDate06 d = new MyDate06(2017, 7, 19);
		d.print();

		d.setYear(2022);
		d.setMonth(6);
		d.setDay(28);
		d.print();

		System.out.println("year : " + d.getYear());
		System.out.println("month : " + d.getMonth());
		System.out.println("day : " + d.getDay());
	}
}

- 필드값들은 private
- 디폴트생성자는 쓰는 일이없으면 안만들어도됨
- 생성자로 필드값을 초기화 하고 있다
- 연도값을 수정하고 싶을땐? -> 생성자가 할수없다 메소드가 해야함 -> 메소드로 수정
- 다른 클래스에 있는 main에서 호출 하여 필드값 수정할 것이므로 메소드 접근제어자는 public / default 여야한다. 

 

그림


메소드에서 this. 사용
- setYear 메소드에서 필드와 매게변수가 또 같은 이름이다
- 매개변수값이 필드에 안들어감 즉 수정이안됨
-> 수정 위해서는 this.를 붙여줘야함
- 생성자도 그렇고 메소드 안에서도 this. 쓸 수 있다.

메소드를 통한 필드값 수정 정리
- 생성자통해 필드값 수정변경 불가능
- 또 다른 객체를 생성하면서 새로운 공간을 만들지 않도록 주의
- 기존값을 수정하기위해선 메소드를 이용해야한다

이클립스 필드값 수정해주는 메소드 생성
- 오른쪽 버튼 -> Source -> Generate Getters and Setters

Sort by
- Fields in getter/setter pairs : getYear setYear getMonth setMonth  순서
- First getters the setters : getYear getMonth setYear setMonth 순서

getters 와 setters
- set으로 시작하는 메소드를 setters 메소드
- get으로 시작하는 메소드를 getters 메소드
- getters method : getYear(), getMonth(), getDay()
- setters method : setYear(), setMonth(), setDay()

setters
- 필드값을 매개변수로 전달된 값으로 설정/수정하기 위한 메소드이다
- 생성자는 객체 생성시에 초기값 설정할떄만 가능한거고 변경은 setters 메소드로 해야한다

getters
- 이 getters 메소드 앞에 있는 자료형에 맞게 값을 돌려주는데 생성자에의해 할당되거나 수정된 필드값을 값을 호출한 곳으로 돌려줌
ex) getYear() 은 year 란 필드값을 돌려줌 return year;

this() 사용 예제
- this() : 같은 클래스 안에 있는 생성자를 호출하라는 의미로 사용됨

class MyDate10{   

  private int year;    
  private int month;    
  private int day;

  public MyDate10(){
    this(2016, 1, 1);                   
  }  
  public MyDate10(int new_year){
    this(new_year, 1, 1);                
  }  
  public MyDate10(int new_year, int new_month){
     this(new_year, new_month, 1);    
  }  
  public MyDate10(int new_year,int new_month,int new_day){
    year=new_year;
    month=new_month;
    day=new_day;
  }    

  public void print(){
	System.out.println(year+ "/" +month+ "/" +day); 
  }
}

public class ConstructorTest10 {     
  public static void main(String[] args) {
    MyDate10 d=new MyDate10(2017, 7, 19);  
    d.print();
    MyDate10 d2=new MyDate10(2017, 7);     
    d2.print();
    MyDate10 d3=new MyDate10(2017);       
    d3.print();
    MyDate10 d4=new MyDate10();          
    d4.print();
  }
}

생성자 호출
- MyDate06 예제에서 클래스의 객체를 만들 때는 다른 클래스에서 만든다
- 즉, MyDate06 예제에서 생성자를 호출 할 때는 다른 클래스의 생성자를 호출 했다.
- 일반적으로 다른 클래스의 생성자 호출도 가능하고 같은 클래스의 생성자 호출도 가능하다
ex) ConstructorTest10 클래스안의 main 메소드 안에서 MyDate10 d = new MyDate10(2017,7,19) 
하는건 MyDate10 클래스 안의 생성자 즉 다른 클래스의 생성자를 호출한거임
- 하지만 this() 는 같은 클래스 안에 있는 생성자만 호출할 수 있다

 

위 예제 생성자 부분만 보기

  public MyDate10(){
    this(2016, 1, 1);                   
  }  
  public MyDate10(int new_year){
    this(new_year, 1, 1);                
  }  
  public MyDate10(int new_year, int new_month){
     this(new_year, new_month, 1);    
  }  
  public MyDate10(int new_year,int new_month,int new_day){
    year=new_year;
    month=new_month;
    day=new_day;
  }

생성자 오버로딩
- 여기서 MyDate10 생성자가 4개다
- 생성자 이름이 같아도 구분이 된다면 같은 이름의 생성자가 여러개 있어도 됨
- 한개의 클래스 안에 여러개의 생성자를 만드는 것 = 생성자 오버로딩 (생성자의 이름은 클래스명이랑 같아야한다)

생성자 오버로딩을 위한 구분
1. 매개변수의 자료형을 다르게 하는법
2. 매개변수의 개수를 다르게 하는법
3. 매개변수가 여러개있을때 순서를 바꾸는방법! 도 된다. 자료형,개수 같아도 순서가 다르면 구분됨

+ MyDate10 클래스에선 생성자의 구분을 매개변수의 개수 로 하고 있다.

 

위 예제 설명

    MyDate10 d2=new MyDate10(2017, 7);     
    d2.print();

1. 여기서 MyDate10(2017,7) 을 할 때, 매개변수가 2개인 생성자가 위에있다

  public MyDate10(int new_year, int new_month){
     this(new_year, new_month, 1);    
  }

2. 로 가서 위의 this(new_year, new_month, 1);  가

  public MyDate10(int new_year,int new_month,int new_day){
    year=new_year;
    month=new_month;
    day=new_day;
  }

3. 인 매개변수가 3개인 생성자를 부르면서 (new_year, new_month, 1) 를 매개변수로 전달
+ 이 매개변수가 3개인 생성자가 있어야만 this(2017,7, 1); 이게 가능한거임

MyDate10 d3=new MyDate10(2017);

- 시에

  public MyDate10(int new_year){
    this(new_year, 1, 1);                
  }

- 이 생성자가 호출되서 여기서 다시 this()로 매개변수가 3개인 생성자를 호출 하면서 (2017,1,1)값을 전달

+

  MyDate10 d4=new MyDate10();

- 를 main에 쓰면

  public MyDate10(){ //기본생성자
    this(2016, 1, 1);                   
  }

- 여기로 가서 this() 통해서 매개변수가 3개인 생성자 다시 호출하면서 매개변수로 값을 2016,1,1 넘겨줌

 

생성자 오버로딩 예시(String 클래스 by api 문서)
String 클래스의 생성자
- 모두 전부 이름이 String 이고 매개변수 부분이 다르다. = "생성자 오버로딩"
- 생성자 호출할때 구분이 가능해야 생성자 오버로딩이 잘 된거임
- 우리는 String(String original) 생성자를 사용

 과제
2022.06.30 / Hw2

Calendar 클래스를 이용해서 오늘 날짜, 시간, 요일을 
           출력하는 프로그램을 작성 하세요?

 

의도

API 문서에서 스스로 사용법 익히기

Calendar 클래스

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220630/CalendarHw.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

의도

API 문서에서 스스로 사용법 익히기

Calendar 클래스

 

코드

package p2022_06_30;

import java.util.Calendar;

public class CalendarHw {

	public static void main(String[] args) {

		Calendar c = Calendar.getInstance();
		int y = c.get(Calendar.YEAR);
		int m = c.get(Calendar.MONTH) + 1;
		int d = c.get(Calendar.DATE);
		int h2 = c.get(Calendar.HOUR_OF_DAY);
		int mm = c.get(Calendar.MINUTE);
		int s = c.get(Calendar.SECOND);
		int w = c.get(Calendar.DAY_OF_WEEK); // 일 : 1 ~ 토 : 7

		// 요일을 저장
		String[] week = { "일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일" };

		System.out.println(y + "." + m + "." + d + " " + h2 + ":" + mm + ":" + s + " " + week[w-1]);

	}

}

 

 

출력

 

 

강사님 코드

package p2022_07_01;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class DateTime02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
// 3.Calendar

		// Calendar c2 = new Calendar();

		// Calendar c1 = new GregorianCalendar();//업캐스팅

		Calendar c = Calendar.getInstance();

		int y = c.get(Calendar.YEAR);
		int m = c.get(Calendar.MONTH) + 1;// 0~11
		int d = c.get(Calendar.DATE);

		int h1 = c.get(Calendar.HOUR); // 12시간
		int ap = c.get(Calendar.AM_PM); // 0:오전
										// 1:오후
		int h2 = c.get(Calendar.HOUR_OF_DAY); // 24시간
		int mm = c.get(Calendar.MINUTE);
		int s = c.get(Calendar.SECOND);

		System.out.println(y + "년 " + m + "월 " + d + "일");
		if (ap == 0) {
			System.out.println("오전");
		} else {
			System.out.println("오후");
		}
		System.out.println(h1 + ":" + mm + ":" + s);

		int w = c.get(Calendar.DAY_OF_WEEK);// 1~7
		System.out.println("w=" + w);
		// 1:일, 2:월, 3:화, 4:수, 5:목, 6:금, 7:토
		String[] week = { "일", "월", "화", "수", "목", "금", "토" };

		System.out.println(week[w - 1] + "요일");
	}

}

 과제
2022.06.30 / Hw1

        키보드를 통해서 각 회원들의 정보를 입력 받는 클래스 (MemberInput)를 작성한다. 
       이때 입력 받는 회원의 정보는 성명, 나이, 이메일,주소를  입력 받는다.

      그리고 키보드를 입력한 회원의 정보는 새로운 회원정보를 저장하는

클래스(MemberInfo)의 멤버변수에 저장을 시킨후 출력하는 프로그램을 작성하시오.
        (단, 1명의 회원정보를 입력 받아서 처리한다. 
         가능하면 2명 이상의 회원 정보도 입력 받아서 처리 해본다.)
 
       MemberInfo클래스의 멤버변수를 초기화 방법을 생성자 대신에
        setter 메소드를 이용해서 초기화 시켜서 프로그램을 작성하세요.

 

 

의도

객체지향 프로그래밍

객체 배열

setters를 이용한 필드의 초기화

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220630/NewMemberInput.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_30;

import java.util.Scanner;

class NewMemberInfo {
	private String name;
	private int age;
	private String email;
	private String address;


	
	//setters
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public void setAddress(String address) {
		this.address = address;
	}


	// 메소드
	public void print() {
		System.out.println("이름 : " + name + " 나이 : " + age + " 이메일 : " + email + " 주소 : " + address);
	}
}

public class NewMemberInput {
	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);
		int i;
		// 멤버들을 저장할 객체배열
		NewMemberInfo[] members = new NewMemberInfo[5];

		for (i = 0; i < members.length; i++) {
			// 입력받기
			
			// 객체배열
			members[i] = new NewMemberInfo();	
			
			System.out.println("--" + (i + 1) + "번째 사람--");
			System.out.print("이름 > ");
			String name = sc.nextLine();
			members[i].setName(name);
			
			System.out.print("나이 > ");
			int age = sc.nextInt();
			members[i].setAge(age);
			
			sc.nextLine(); // 엔터가 값으로 입력되는걸 막기위해서

			System.out.print("이메일 > ");
			String email = sc.nextLine();
			members[i].setEmail(email);
			
			System.out.print("주소 > ");
			String address = sc.nextLine();
			members[i].setAddress(address);

			
			// 더 입력받을지 물어보기
			System.out.println("계속 입력하시겠습니까? y 또는 n");
			String a = sc.nextLine();
			
			if (a.equals("y") || a.equals("Y") ) {
				continue;
			}else if(a.equals("n") || a.equals("N")) {
				break;
			}

		}

		// 들어있는 만큼 출력
		for (int j = 0; j < (i + 1); j++) {
			members[j].print();
		}

	}
}

 

 

출력

 

 

강사님 코드

package p2022_07_01;

import java.util.Scanner;

public class MemberInput01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 객체 배열: 객체의 주소를 저장하는 배열
		MemberInfo01[] m = new MemberInfo01[5];
		int i = 0;
		String yn;

		do {
			Scanner sc = new Scanner(System.in);
			System.out.print("성명을 입력하세요? ");
			String name = sc.nextLine();
			System.out.print("나이를 입력하세요? ");
			int age = sc.nextInt();
			sc.nextLine();
			System.out.print("E-Mail을 입력하세요? ");
			String email = sc.nextLine();
			System.out.print("주소를 입력하세요? ");
			String address = sc.nextLine();

//			m[i] = new MemberInfo(name, age, email, address);
			// m.name="홍길동";

			m[i] = new MemberInfo01();
			m[i].setName(name);
			m[i].setAge(age);
			m[i].setEmail(email);
			m[i].setAddress(address);

			i++;

			System.out.print("계속할려면 y, 멈출려면 n을 입력?");
			yn = sc.next();
			if (yn.equals("y") || yn.equals("Y")) {
				continue;
			} else if (yn.equals("n") || yn.equals("N")) {
				break;
			}

		} while (true);

		for (int j = 0; j < i; j++) {
			System.out.println("성명:" + m[j].getName());
			System.out.println("나이:" + m[j].getAge());
			System.out.println("E-Mail:" + m[j].getEmail());
			System.out.println("주소:" + m[j].getAddress());
		}
	}

}

// DTO(Data Transfer Object)
class MemberInfo01 {
	private String name;
	private int age;
	private String email;
	private String address;

//	public MemberInfo(String name, int age, String email, String address) {
//		this.name = name;
//		this.age = age;
//		this.email = email;
//		this.address = address;
//	}	

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

}

 과제
2022.06.29 / Hw1
        키보드를 통해서 각 회원들의 정보를 입력 받는 클래스(MemberInput)를 작성한다. 
        이때 입력 받는 회원의 정보는 성명, 나이, 이메일, 주소를 입력 받는다. 
        그리고 키보드로 입력한 회원의 정보는 새로운 회원정보를 저장하는

        클래스(MemberInfo)의 멤버변수에 저장을 시킨후 출력하는 프로그램을 작성하시오.
        (단, 1명의 회원정보를 입력 받아서 처리한다. 
         가능하면 2명 이상의 회원 정보도 입력 받아서 처리 해본다.)

 

 

의도

객체지향 프로그래밍

생성자를 이용한 필드의 초기화

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220629/MemberInput.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_29;

import java.util.Scanner;

class MemberInfo {

	private String name;
	private int age;
	private String email;
	private String address;

	// 생성자
	public MemberInfo(String name, int age, String email, String address) {
		this.name = name;
		this.age = age;
		this.email = email;
		this.address = address;
	}

	// 메소드
	public void print() {
		System.out.println("이름 : " + name + " 나이 : " + age + " 이메일 : " + email + " 주소 : " + address);
	}

}

public class MemberInput {

	public static void main(String[] args) {

		Scanner sc = new Scanner(System.in);

		//멤버들을 저장할 객체배열
		MemberInfo[] members = new MemberInfo[3];

		for (int i = 0; i < members.length; i++) {
			// 입력받기
			System.out.println("--" + (i + 1) + "번째 사람--");
			System.out.print("이름 > ");
			String name = sc.nextLine();

			System.out.print("나이 > ");
			int age = sc.nextInt();

			sc.nextLine(); // 엔터가 값으로 입력되는걸 막기위해서

			System.out.print("이메일 > ");
			String email = sc.nextLine();

			System.out.print("주소 > ");
			String address = sc.nextLine();

			// 저장하기
			members[i] = new MemberInfo(name, age, email, address);

		}

		//전체 출력
		for (int i = 0; i < members.length; i++) {
			members[i].print();
		}

	}

}

 

 

출력

 

 

강사님 코드

package p2022_06_30;

import java.util.Scanner;

public class MemberInput {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// 객체 배열
		MemberInfo[] m = new MemberInfo[5];
		int i = 0;
		String yn;
		Scanner sc = new Scanner(System.in);
		String name, email, address;
		int age;
		do {
			System.out.print("성명을 입력하세요? ");
			name = sc.nextLine();
			System.out.print("나이를 입력하세요? ");
			age = sc.nextInt(); // 숫자를 입력받은후에 enter키를
			sc.nextLine(); // 누르면 null값을 return하게 됨
			System.out.print("E-Mail을 입력하세요? ");
			email = sc.nextLine();
			System.out.print("주소를 입력하세요? ");
			address = sc.nextLine();

			m[i] = new MemberInfo(name, age, email, address);
			// m.name="홍길동";
			i++;

			System.out.print("계속할려면 y, 멈출려면 n을 입력?");
			yn = sc.nextLine();
			if (yn.equals("y") || yn.equals("Y")) {
				continue;
			} else if (yn.equals("n") || yn.equals("N")) {
				break;
			}

		} while (true);

		for (int j = 0; j < i; j++) {
			System.out.println("성명:" + m[j].getName());
			System.out.println("나이:" + m[j].getAge());
			System.out.println("E-Mail:" + m[j].getEmail());
			System.out.println("주소:" + m[j].getAddress());
		}
	}

}

class MemberInfo {
	private String name;
	private int age;
	private String email;
	private String address;

	public MemberInfo(String name, int age, String email, String address) {
		this.name = name;
		this.age = age;
		this.email = email;
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}

	public String getEmail() {
		return email;
	}

	public String getAddress() {
		return address;
	}

}

 

 과제
2022.06.28 / Hw1

  1~45사이의 숫자를 6개 추출 하는 프로그램을 작성 하세요? 
 (단, 중복된 숫자는 1번만 출력 되도록 한다.) 
 Math.random() 이용해서 프로그램을 작성 하세요.

 

 

의도

Math.random() 메소드와 배열의 활용

 

 

깃허브

https://github.com/kindacool/Hw/blob/main/HW20220628/Hw1.java

 

GitHub - kindacool/Hw

Contribute to kindacool/Hw development by creating an account on GitHub.

github.com

 

 

코드

package p2022_06_28;

public class Hw1 {

	public static void main(String[] args) {
		/*
		 * 1~45사이의 숫자를 6개 추출 하는 프로그램을 작성 하세요? 
		 * (단, 중복된 숫자는 1번만 출력 되도록 한다.) 
		 * Math.random() 이용해서 프로그램을 작성 하세요.
		 */

		int[] random = new int[6];

		for (int i = 0; i < random.length; i++) {
			random[i] = (int) (Math.random() * 45 + 1);
			for (int j = 0; j < i; j++) { // 이전에 들어간 값과 같은 값이 있는지 검사
				if (random[i] == random[j]) { // 같은 값이 있다면
					i--; // 다시 할당하기 위해서 i--;
				}
			}
		}

		// 출력하기
		for (int i : random) {
			System.out.print(i + " ");
		}

	}

}

 

 

출력

 

 

강사님 코드

package p2022_06_29;

import java.util.Arrays;

class Lotto1 {

	public static void main(String[] args) {

		int num[] = new int[6];

		for (int i = 0; i < num.length; i++) {

			num[i] = (int) (Math.random() * 45) + 1;	// 1 ~ 45
//			num[0]=5, num[1]=5,
			for (int j = 0; j < i; j++) {
				if (num[i] == num[j]) {		// 중복
					i--;
					break;
				} // if end

			} // for end
		} // for end

		
		// 오름차순 정렬 : 버블정렬(자신의 옆자리에 있는 것과 비교)
		int temp = 0;
		for (int i = 0; i < num.length; i++){
			for (int j = i+1; j < num.length; j++) {
				if(num[i] > num[j]){
					temp = num[i];
					num[i] = num[j];
					num[j] = temp;
				}
			}
		}

//		Arrays.sort(num); // 오름차순 정렬

		for (int k : num) {
			System.out.print(k + "\t");
		}
	}
}

/*
 * 난수 발생 공식 난수 =(정수화) ((상한값-하한값+1)* Math.random()) + 하한값
 * 
 */

+ Recent posts