2023.05.03
1교시
* 객체를 만들기 위해서는 사용자정의데이터형이 필요
* 사용자정의데이터형 (명시적 선언 클래스)
- 프로그램 작성 언어에 의해 기본적으로 지정된 여러 데이터형 가운데, 사용자가 직접 몇 개를 조합하여 정하는 자료 유형.
* student1 st1= new student();
크기 참조변수(번지의 위치를 기억- 주소를 가르킴) -> (최소)cpu의 크기인 8바이트를 가짐
* 실제데이터는 heap에 있음
* 클래스 = 설계도(개념), 객체(실체)
컴퓨터에게 일을 시키려면 실체화 시켜야함 -> 인스턴스화(실제 진짜 존재)
-> 클래스로 만든 객체는 인스턴스
객체를 생성한다 = 메모리에 공간을 확보한다(방을 갖는다) = new 연산자 활용
- 연산자 = 함수
※ 인스턴스화(객체화) 이해를 돕기 위한 예시
1. 클래스는 내가 학원 상담, 면접 등을 보았던 행위(학원 입장에서 나는 문서에 존재할 뿐 실체가 아님)
객체는 학원에 오기로 결정하여 수업을 온 행위(실체가 됨)
2. 렛잇고 는 클래스, 노래를 부르는 엘사는 객체
다른 사람이 부르면 새로운 객체(new)
* 동일 패키지 내의 클래스 구분
1. 실행클래스 main함수가 있는 클래스 , 데이터를 불러서 프로그램을 최초로 시작함(1회만 호출하면 됨)
2. 라이브러리 클래스 main을 사용하지 않은 클래스, 데이터가 들어있는 곳
-> 실행은 main이 있는 곳(실행 클래스)에서 해야 함
* 생성자는 반환값이 없으며 class의 이름과 같다
2교시
* 실행 클래스와 라이브러리 클래스 구분하여 만들기
* static : 공용, 정적
- 클래스 호출, 객체 생성을 따로 하지 않고 바로 사용 가능 (인스턴스는 객체를 생성해야 함)
- 클래스에 고정된 멤버
● 자바 객체의 주소를 확인하는 간단한 방법
1. 프로젝트(2023.05.03), 패키지(apple.orange), 클래스(Student) 만들기
2. 코드입력
package apple.orange;
public class Student {
public static void main(String[] args) {
Student s1 = new Student(); // 생성자 : 객체의 멤버를 초기화 함
p("s1 변수는 Student 객체를 참조합니다.");
p("" + System.identityHashCode(s1)); // 객체의 상대주소를 리턴합니다.
Student s2 = new Student();
p("s2 변수는 Student 객체를 참조합니다.");
p("" + System.identityHashCode(s2));
}
public static void p(String msg) { // p(String msg) = 메소드의 헤더(header), 시그니쳐
System.out.println(msg);
}
}
* 실행 값 : 1365202186
-> s1은 계속 같은 장소에 저장 됨
p("" + System.identityHashCode(s1));
* " " + 숫자 == 문자열
* System.identityHashCode
- 객체의 고유한 hashcode를 리턴하는 메소드
* hash기능 : 우리가 알 수 있는 단방향 문자열 암호화 기법(리턴 불가능)
- 복호화 하지 않는 유일한 문자열, 비밀번호 등
- s1과 s2는 다른 장소에 저장 됨
* 암호화 (참고)
<-복호화
원문 --------------암호화문
안녕 암호화-> 얀농
- (+1)을 한다는 것
ㅏㅑㅓㅕㅗㅛㅜㅠㅡㅣ
'ㅏ'에 +1을 하면 'ㅑ'로 변경 됨
- 개인키(대칭) : 보내는 키 = 소유 키, 동일한 키를 이용하여 데이터를 암호화 하여 노출 위험
- 공개키(비대칭) : 서로 다른 키로 데이터를 암호화하고 복호화 함, 노출이 되어도 변경하면 됨
● 클래스의 구성 멤버 - 책 221p
- 필드 (데이터 저장되는 곳)
- 생성자 (초기화 역할)
- 메소드 (기능, 객체의 동작에 해당하는 실행 블록)
3교시
● 필드 - 책 224p
* 정의 : 객체의 고유 데이터, 부품객체, 상태정보를 저장하는 곳
ex) 자동차
고유데이터 : 제작회사, 모델, 색상, 최고속도
상태데이터 : 현재속도, 엔진회전수
부품 : 엔진, 타이어, 차체
-> 필드로 선언되어야 하는 부분
* 필드 선언
- 클래스 { } 블록 어디든 / 생성자 선언과 메소드 선언 앞과 뒤 어디든 존재할 수 있다.
but ! 생성자와 메소드 사이의 { } 에 선언된 변수는 로컬(지역)변수임
- 구조 : 타입 필드 [ =초기 값];
타입 : 필드에 저장할 데이터의 종류를 결정 - 기본타입(int, byte), 참조타입(배열, 인터페이스, 열거) 모두 가능
초기 값은 필드 선언 시 주어질 수도 있고 생략될 수도 있다.
예시)
String model = "그랜저";
String color = "검정";
int maxSpeed = 350;
int speed; // 초기 값 없음
- String(타입), model(필드). "그랜저"(초기 값)
- 변수선언의 형태와 비슷하여 클래스 멤버 변수라고 부르기도 함
- 초기 값이 주어지지 않은 필드는 객체 생성시 자동으로 기본 초기 값(0에 제일 가까운 값)으로 설정된다.
* 필드를 사용하는 법 - 226p
- 필드를 사용한다 = 필드값을 읽고 변경하는 작업
- 필드는 소속한 곳의 아래에 있어야 함
- 필드는 객체에 소속된 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않음
- 메소드 안에 변수를 선언하여 사용하는 것과 유사
- 변수는 자신이 선언된 생성자 또는 메소드 블록 내에서만 사용할 수 있는 반면, 필드는 생성자와 모든 메소드에서 사용 가능함(like 전역변수)
- 클래스 외부에서 사용할 경우 클래스로부터 객체를 생성한 뒤 필드를 사용해야 함(이유 : 파란색 글)
Car 클래스
int speed; // 필드
Car() { // 생성자
speed=0; // 값 변경
}
void method(...) { // 메소드
speed=10; // 값 변경 - 클래스 내부의 생성자나 메소드에서 사용할 경우 단순히 읽어서 사용
}
Person클래스
void method() {
Car myCar = new Car() // 객체 생성
myCar.speed = 60; // 필드 사용, 값 변경
}
- 외부 Person 클래스에서 Car클래스의 필드를 사용하려면 Car 객체를 생성하고 .(도트- 객체접근연산자)으로 필드에 접근한다.
- 실행클래스 - main, 데이터클래스를 최초 1회 불러옴
- 구현클래스 - main이 있어도 상관이 없지만 수업은 없는 방법을 사용함
4교시
● 생성자 - 232p
- 생성자는 new연산자로 호출되는 { } 블록입니다.
- 객체를 생성할 때 호출되어 객체의 초기화를 담당
* 기본생성자 : 아무 내용 없는 생성자
- 구조 : [public]클래스() { }
-> 클래스의 형태를 따르며 클래스에 public이 있으면 public가 붙음
- 클래스 내부에 생성자 선언을 생략해도 기본 생성자가 있다.
-> 자바에서 자동으로 만들어짐(바이트코드파일에서 확인 됨)
but 클래스 내부에 명시적으로 선언한 생성자가 1개라도 있으면 컴파일러는 기본생성자를 추가해주지 않음
- 명시적으로 생성자를 선언하는 이유는 객체를 다양한 값으로 초기화 하기 위해서임
* 생성자 선언(사용자 정의 생성자)
- 우리가 생성자를 명시적으로 선언하는 경우
구조 : 클래스(매개변수선언, ...) { // 생성자 블록에 작성
객체의 초기화 코드
}
- 생성자는 리턴타입이 없고 클래스 이름과 동일함
- 객체의 초기화 코드에는 일반적으로 필드에 초기 값을 저장하거나 메소드를 호출하며 객체 사용 전에 필요한 준비를 함
- 매개변수선언은 여러개, 생략 가능
※ 매개변수 : new연산자로 생성자를 호출할 때 외부의 값을 생성자 블록 내부로 전달하는 역할
- 클래스에 생성자가 명시적으로 선언되어 있을 경우 선언된 생성자를 호출하여 객체를 생성해야 함.
* 에러
원인 1. 생성자 명시적 선언(=사용자정의생성자)을 하면 기본생성자가 추가 되지 않음
@매개변수를 가지는 생성자를 하나 이상 정의한 후 기본 생성자를 호출하면, 오류가 발생
@매개변수를 가지는 생성자를 하나라도 정의했다면, 기본 생성자는 자동으로 추가되지 않음.
-> 기본생성자를 직접 호출 해야 함
* car 클래스에서 생성자 만들기 후 저장해야 오류가 사라짐
* 예상결과와 달리 변경이 안 됨(참조변수 this 활용 법)
// 필드선언
String company = "현대자동차";
String model = "그랜저";
String color = "검정";
int maxSpeed = 350;
int speed;
Car(String model, String color, int maxSpeed) { // 매개변수, 함수 헤더가 일치해야함
model = model;
color = color;
maxSpeed = maxSpeed;
원인 2. 가까운 변수인 매개변수를 읽음
내용물(오른쪽)을 방(왼쪽)에 저장하는 특성을 가지고 있어서 본인을 본인에게 저장한 것이 됨; 이름 구분이 필요(this.model과 같은)
** 참조변수this 활용 내용
Car(String model, String color, int maxSpeed) {
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
- this.model 객체 자기 자신을 가르킴
- this.model은 인스턴스변수로부터 왔다가 인식 됨(상단에 필드 선언한 것을 가르킴)
-> this 기준 제일 가까운 자리가 필드임
- 오른쪽 model은 지역변수(매개변수), 왼쪽 model은 인스턴스변수(필드영역)인 것의 구분이 필요하여 this 사용
-> 오류 해결
5교시
● 생성자의 필요성
1. 값을 초기화
2. 값을 통제(범위 설정 등)
- 속도는 - (음수) 값을 가질 수 없다
-> 속도가 -100으로 움직이면 속도를 0으로 만들어서 중지 시켜야 함
if / else if / else 이용
Car(String model, String color, int maxSpeed, int speed) {
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
this.speed = speed;
if (maxSpeed > 300) { // 최대속도 300으로 설정(300이상의 값은 강제로 300)
this.maxSpeed = 300;
} else if (maxSpeed < 0) { // 속도에서 음수는 불가능하므로 0으로 설정
this.maxSpeed = 0;
} else {
this.maxSpeed = maxSpeed;
}
if (speed < 0) {
this.speed = 0;
} else {
this.speed = speed;
}
* 같은 매서드를 가진 것은 매개변수의 개수와 타입으로 구분(자바 특징)
-> 함수의 이름이 같더라도 매개변수의 개수와 타입이 다르면 구분이 됨(중첩함수)
-> 이런 특성을 오버로딩이라고 함
public class CarExample {
public static void main(String[] args) {
// Car 객체 생성
Car car = new Car();
// 필드값 읽기
p("제작회사 : " + car.company);
p("모델명 : " + car.model);
p("색상 : " + car.color);
p("최고속도 : " + car.maxSpeed);
p("현재속도 : " + car.speed);
// 필드 값 변경
car.speed = 60;
p("수정된 속도 : " + car.speed);
p("--------------------------------------------");
// redCar 객체 생성 - new로 생성된 객체는 다르다(메모리상의 위치가 다름)
Car redCar = new Car();
// 필드 사용 - 값 변경
redCar.color = "빨강"; // 매개변수 3개
redCar.model = "골프";
redCar.company = "벤츠";
// 필드 값 읽기
p("제작회사 : " + redCar.company);
p("모델명 : " + redCar.model);
p("색상 : " + redCar.color);
p("최고속도 : " + redCar.maxSpeed);
p("현재속도 : " + redCar.speed);
p("--------------------------------------------");
// 사용자 정의 생성자 호출로 객체 만들기(헤드 개수 맞추기)
Car carTruck = new Car("봉고", "베이지", 350, -100); // 매개변수 4개
// 필드 값 읽기
p("제작회사 : " + carTruck.company);
p("모델명 : " + carTruck.model);
p("색상 : " + carTruck.color);
p("최고속도 : " + carTruck.maxSpeed);
p("현재속도 : " + carTruck.speed);
p("--------------------------------------------");
Car carCompany = new Car(60, "기아", "노란색"); // 매개변수 3개(red와 타입이 다름)
// 필드 값 읽기
p("제작회사 : " + carCompany.company);
p("모델명 : " + carCompany.model);
p("색상 : " + carCompany.color);
p("최고속도 : " + carCompany.maxSpeed);
p("현재속도 : " + carCompany.speed);
p("--------car test program 종료----------");
}
public static void p(String msg) {
System.out.println(msg);
}
- 함수의 이름이 Car 로 동일하지만 매개변수의 개수와 타입이 다르기 때문에 구분이 됨
- 호출에 문제 없이 구분되어 결과가 나옴
이해에 도움이 되기 위한 요약 코드
Car() {...} // 매개변수 없는 기본 생성자 0개
Car(String model) {...} //매개변수 1개
Car(String model, String color) {...} // 매개변수 2개
Car(String model, String color, int maxSpeed) {...} // 매개변수 3개 - 외부에서 접근
Car(String model, String color, int maxSpeed, int speed) {...} // 매개변수 4개
* 컴퓨터는 입력에 대하여 결과가 하나만 나와야 함
-> 함수가 같은 이름을 여러개 사용하면 오류가 남
-> 매개변수가 다르거나 타입이 달라야함
6교시
* 다른 생성자 호출 this() - 241p
package apple.orange;
public class Car {
// 필드선언
String company = "현대자동차";
String model = "그랜저";
String color = "검정";
int maxSpeed = 350;
int speed;
// 기본 생성자(구조 - 클래스() {})가 이미 있다. - 자동으로 만들어짐(바이트코드파일에서 확인 됨)
Car() { // 매개변수 없는 생성자 0개
this.model = "그랜저"; // 고정으로 값을 넣음(강제 설정)
this.color = "파란";
this.maxSpeed = 60;
// 매개변수 3개 - this("그랜저", "파란", 60); 과 동일 내용
}
Car(String model) { // 3개짜리와 동일 , 생성자 호출 방식으로 변경
this.model = model;
this.color = "그린"; // 강제 설정
this.maxSpeed = 100; // 강제 설정
}
Car(String model, String color) {
this.model = model;
this.color = color;
this.maxSpeed = 150; // 강제 설정
}
// 사용자 정의 생성자(매개변수 3개) - 외부에서 접근
Car(String model, String color, int maxSpeed) { // 함수 헤더가 일치해야함
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}
// 사용자 정의 생성자(매개변수 4개)
Car(String model, String color, int maxSpeed, int speed) {
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
this.speed = speed;
}
}
- 코드 중복을 방지
* 생성자가 생성자를 부를 수 없음
- 자신(this)을 부르기 가능.
* Korean 클래스 만들기
package apple.orange;
public class Korean { // 명시적
// 멤버필드
String nation;
String city;
String name;
// 기본 생성자
Korean() { // = Korean("대한민국", "서울", "홍길동");
}
Korean(String nation) {
/*this.nation = nation; // 사용자가 입력한 코드
this.city = "서울"; // 중복되는 코드
this.name = "홍길동"; // 중복되는 코드*/
this(nation, "서울", "홍길동");
}
Korean(String nation, String city) { // name이 고정 됨
this(nation, city, "홍길동");
}
Korean(String nation, String city, String name) { // 최종처리는 얘가 함
this.nation = nation;
this.city = city;
this.name = name;
}
}
1. this.nation = nation;
this.city = city;
this.name = "홍길동"
2. this(nation, city, "홍길동"); // 상단의 3줄과 동일.
▷ 2번을 활용함으로써 코드의 중복을 방지한다.
7교시
* OAuth(오-오쓰)
구글과 트위터가 협력하여 개발한 사용자 인증 API(라이브러리)
보안기능
● 난수(랜덤)와 날짜를 이용한 게임 만들기
- 클래스명 : TodayFortuneGameApp
▶ 날짜 다루기 - Date클래스 or Calendar 클래스
package apple.orange;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import apple.orange.util.MeIO;
public class TodayFortuneGameApp {
public static void main(String[] args) {
// 1. 날짜 다루기 - Date클래스 or Calendar 클래스
Date today = new Date(); // 오늘 날짜를 구해라
System.out.println(today); // 단순한 오늘 날짜를 출력 - 유럽식(율리우스력 형식)
Date today = new Date(); // 오늘 날짜를 구해라
System.out.println(today); // 단순한 오늘 날짜를 출력 - 유럽식(율리우스력 형식)을 날짜 출력 -> 불편
- 율리우스력 형식이 출력 됨 : Wed May 03 19:48:43 KST 2023
▶ 미터법 형식으로 날짜를 바꾸기. ( 미터법 : 0000년 00월 00일 )
String formatString = "yyyy년 MM월 dd일의"; // 날짜 포맷
SimpleDateFormat dateFormat = new SimpleDateFormat(formatString); // 미터법 형식 변환 날짜형 클래스
// 오늘날짜를 지정된 형식으로 출력하자
System.out.println(dateFormat.format(today));
- 자바에서 날짜를 변환하여 출력하는 것을 날짜 포맷이라고 함.
String formatString = "yyyy년 MM월 dd일의"; // 포맷하기
- 일반적인 미터법 형식으로 변환하는 간단한 날짜형 클래스
SimpleDateFormat dateFormat = new SimpleDateFormat(formatString);
* SimpleDateFormat
1) 출력할 날짜 형식을 문자열로 지정
2) SimpleDateFormat 객체를 생성(기존클래스에서 객체 인스턴스화 하는법)
3) 생성 객체에 format()메소드에 출력할 날짜변수를 넣어줍니다.
System.out.println(dateFormat.format(today));
- SimpleDateFormat은 고정된 시간을 표한할때 굉장이 유연하고 편리하다
-> 타이머 같이 계속 흐르는 시간을 나타내는 방법으로 올바르지 않다.
* SimpleDateFormat 형식지정자
y: year / M: month / d: date / h: hour(01~12) H: hour(00~23)
/ m: minute / s: second S: millisecond(1/1000) / E: day in week(요일)
/ a: am/pm
▶ Calendar 클래스
// Calendar 클래스 사용
Calendar cal = Calendar.getInstance();
// 시분초 구하기
int hour = cal.get(Calendar.HOUR); // 날짜요소를 가져오는 메소드 get(출력할 내용 형식)
int min = cal.get(Calendar.MINUTE);
int sec = cal.get(Calendar.SECOND);
System.out.println("현재시간은 " + hour + "시" + min + "분" + sec + "초");
// 난수로 운세 구하기
Random r = new Random(); // 난수가 발생할 준비가 됨
int randomNumber = Math.abs(r.nextInt() % 100) + 1;
System.out.println("금전운(100) : " + randomNumber + "%");
}
}
- Calendar.getInstance() 생성 - new Calendar()가 아닌
- 싱글톤 패턴 - 객체를 한 번만 사용
* 형식지정자
YEAR: 연도 / MONTH: 월 / DATE: 일 / HOUR: 시간(1~12) / HOUROFDAY: 시간(0~23)
/SECOND: 초 /MILLISECOND: 1/1000초 / DAYOFWEEK: 요일 / AM/PM : 오전/오후
* 시간이 흐름에 따라 데이터가 변동 됨
ex) 월간매출, 주가 등
- 고정되지 않은 Calendar 사용
※ 글자 한번에 변경하는 방법
- 상단 탭의 Edit의 Find/Replace를 활용한다.
※ 데이터 생성에 도움이 되는 공통의 내용을 클래스로 묶어 활용하기
* MeIO - 내가 만든 인풋 아우풋이라는 뜻
- 내가 만든 라이브러리 -> 다른 클래스에서 임포트 해주기
-> import apple.orange.util.MeIO;
package apple.orange.util;
public class MeIO {
public static void p(String msg) {
System.out.print(msg);
}
public static void pl(String msg) {
// 1. System.out.println(msg);
p(msg + "\n"); // 2. 상단의 msg 활용
}
}
- 내가 사용할 단축키 등 작성하여 활용하