2022.08.02 [TUE]
- Day 5-
수업 주요 목차
- 제어문으로 구구단 만들기-
- 변수의 종류와 특징(지역변수, 인스턴스변수, 클래스변수)
- 자바 메모리 구조(상세히) Class Diagram 공부와 그에 따른 Java Program을 구성
- 관계(relationship):UML의 Class Diagram => association(일반), aggregation(소유), composition(구성)
- 객체 초기화 단계 (기본)
🤖Review
클래스 작성시 구성요소
- package - 디렉토리별로 분류하기 위해 사용(소문자 사용)
- import - 다른 클래스나 패키지 자원을 사용하고자 할 때 사용(패키지명.클래스명)
- class - 객체 생성
- instance variable(i.v) - 클래스로부터 만들어지는 객체의 속성정보(data) 저장
- [constructor] - 객체 초기화 / 클래스와 이름이 같아야 함 / 명시하지 않으면 컴파일시 자동삽입
- method - 객체의 기능을 정의
Data Type(자료형)
- Primitive(기본형)
- Integers(정수형) byte, short, int, long
- Decimers(실수형) float double
- Character(문자형) char
- 논리형 boolean
2. Reference(참조형) - 기본형이 아닌 모든 데이터 타입은 참조형
For loop Review
package step1.review;
public class TestReviewForLoop2 {
public static void main(String[] args) {
/*
* 구구단 2단 ~ 9단까지
*
* 2*1=2 2*2=4 2*3=6 ... 2*9=18
* 3
* 4
* ...
* 9*1=9 ...
*
* for -> 8번 반복
* 랙 -> 9번 반복
*/
for(int i=1;i<=8;i++) {
//System.out.println("i "+i+ " : ");
for(int j=2;j<=9;j++) { // 곱하기 1부터 시작하기 때문에 j를 1로 설정해서 시작하게 하면 뒷자리도 사용 가능
System.out.print("\t"+j+"="); i 와 j가 제대로 설정되면 그 외에는 문자로 넣어주면 간단쓰
}
System.out.println();
}
}
}
어제 예제를 진행할 때 행을 먼저 만들었어서 행을 먼저 만드려고 했으나 출력해보니 뭔가 이상해서 살펴보던 중 갑자기 강사님이 풀이를 시작하셔서 머리가 점점 하얗게 하얗게.... 그래서 아무렇게나 때려 넣은 결과
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
2= 3= 4= 5= 6= 7= 8= 9=
총체적 난국....이렇게 출력 됐는데 앞에 숫자와 결과는 어떻게 넣어야할 지 몰라서 (라기 보다 시간이 없어서 차분히 뜯어 고칠 기회가 없었다. 뒤쳐지면 다음 진도를 못따라 가기 때문에 강사님 답만 얼른 받아적고 집에 와서 살펴보며 다시 작성해봤다.
package step1.review;
public class TestReviewForLoop2 {
public static void main(String[] args) {
/*
* 구구단 2단 ~ 9단까지
*
* 2*1=2 2*2=4 2*3=6 ... 2*9=18
* 3
* 4
* ...
* 9*1=9 ...
*
* for -> 8번 반복
* 랙 -> 9번 반복
*/
for(int i=2;i<=9;i++) { //2단부터 9단까지
// System.out.println(i);
for(int j=1;j<=9;j++) { //9번 반복
System.out.print(i+"*"+j+"="+i*j+"\t");
}
System.out.println();
}
}
}
첫번째 for문에서는 2단부터 시작할 것이기때문에 i는 2로 설정해주면 내려갈수록 구구단의 첫 숫자로 사용이 가능했다. 비교 연산자는 9단까지 니까 9보다 작거나 같다고 표시해주고 1씩 더해지는 ++로 설정을 해주면
2
3
4
5
6
7
8
9
여기까지 나오고 그 다음 다시 for문으로 나머지를 설정해주면 되는데 새로운 변수 j는 곱하기 1부터 시작하기 때문에 1로 설정, 곱하기 9까지 할 거니까 비교연산자로 9로 설정, 그리고 마찬가지로 ++로 1씩 더해주면
2
1
2
3
4
5
6
7
8
9
3
1
2
3
4
5
6
7
8
9
4
1
2
3
4
5
6
7
8
9
5
1
2
3
4
5
6
7
8
9
6
1
2
3
4
5
6
7
8
9
7
1
2
3
4
5
6
7
8
9
8
1
2
3
4
5
6
7
8
9
9
1
2
3
4
5
6
7
8
9
이런 보기 힘든 결과가 나오는데 2단의 1부터 9, 3단의 1부터 9 ...9단의 1부터 9까지 찍어내기 성공. 이제 예쁘게 정리만 해주면 되기 때문에 i(단) + "*"(곱셈 기호) + j(곱하는 숫자) + "="(등호) + i*j(곱한 결과) + "\t"(tab만큼 띄어쓰기) 로, 그리고 프린트 라인 이 아닌 그냥 프린트로 sysout 해주면
2*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18 3*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27 4*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
...? 띠용 2단, 3단, 4단 ... 끝날 때마다 줄을 바꿔주도록 sysout을 해주면 이제 진짜
2*1=2 2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*1=3 3*2=6 3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*1=4 4*2=8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
완성!
객체 초기화 단계
: 객체 생성시 초기화는 다음과 같은 단계를 거친다. (이후 상속 공부시에 더 추가될 예정)
1) 인스턴스 변수의 기본 초기화 (ex. 0;false;null)
2) 인스턴스 변수의 명시적 초기화 (ex. int i = 3;)
3) 생성자에 의한 초기화 (eclipse 예제 참고)
변수의 종류와 특징
1) 인스턴스 변수(instance variable) : 클래스 단위에서 선언, 객체의 속성 정보를 저장, Heap 메모리 영역에 저장
선언만 해도 기본 초기화 (0, 0.0, false, null)
2) 지역 변수(local variable) : 생성자 또는 메서드 영역에서 선언되고 초기화됨, Stack 메모리 영역에 저장
특정 기능을 위해 일시적으로 사용된 후 메모리에서 해제
선언 후 명시적 초기화 필요 (ex. int i=1;)
지역변수는 자신의 선언된 실행영역 {} 내에서만 사용이 가능
3) 클래스 변수 (class/static variable) : class의 정보를 저장할 때 사용, meta space 메모리 영역에 저장 (이후 공부 예정)
자바 메모리 구조
- Stack : 일시적으로 사용되는 지역변수 정보(local variable)가 저장되는 영역 (Last In, First Out : LIFO)
- Heap : 객체의 속성 정보(instace variable)가 저장되는 영역, 참조할 수 있는 주소값이 JVM에 의해 생성되고 관리됨
- Meta Space : class의 정보가 저장되는 영역, static 즉 class variable 정보가 저장됨 (이후 공부 예정)
Relationship
: UML의 Class Diagram => association, aggregation, composition
[ association > aggregation > composition ]
- association : use a 관계 ex) 사람이 렌트카를 이용하다.
- aggregation : has a 관계 ex) 고객이 스마트폰을 소유한다.
- composition : consist of 관계 ex) 자동차는 엔진과 여러 부품으로 구성된다. 사람이 뇌를 가지고 있다.
🔎 Eclipse 실습 내용
1. 객체 초기화 단계를 확인하는 예제 : 객체 생성시 초기화는 다음과 같은 단계를 거친다. (이후 상속 공부시에 더 추가될 예정)
1) 인스턴스 변수의 기본 초기화 (0;false;null)
2) 인스턴스 변수의 명시적 초기화 (ex. int i = 3;)
3) 생성자에 의한 초기화
package step2;
public class TestObjectInit {
public static void main(String[] args) {
MyDate date=new MyDate(9);
System.out.println(date.flag); //false
System.out.println(date.num); //0.0
System.out.println(date.str); //null
System.out.println("**결과예상**");
System.out.println(date.day1); //0 -> 변수 호출
System.out.println(date.day2); //7 -> 변수 호출
System.out.println(date.day3); //9 -> method 호출
}
}
package step2;
public class MyDate {
//테스트를 위해 인스턴스 변수의 접근 제어자를 디폴트로 설정 (private가 아닌 default로 설정)
boolean flag; //인스턴스 변수 boolean 형은 선언만 하면 false로 초기화
double num; // 인스턴스 변수 double 형은 선언만 하면 0.0로 초기화
String str; //인스턴스 변수 String 형은 선언만 하면 null로 초기화
int day1; // 인스턴스 변수 정수형은 선언만 하면 0로 초기화
int day2=7;// 인스턴스 변수에 명시적 초기화를 시킴
int day3=8; //인스턴스 변수에 명시적 초기화를 시킴
public MyDate(int day3) {
this.day3=day3;
}
}
↓
false
0.0
null
**결과예상**
0
7
9
(* day 3의 경우 명시적으로 초기화 되었으나 진행되는 main method의 진행에 따라 초기화된 값이 아닌 결과가 나옴)
2. Variable Scope(변수 범위)
package step3;
public class TestVariableScope {
public static void main(String[] args) {
VariableScopeExam vs = new VariableScopeExam();
System.out.println("****생성자 실행****");
vs.test1();
System.out.println("***test1() 실행****");
vs.test2(7);
System.out.println("***test2() 실행****");
vs.test3(6);
System.out.println("***test3() 실행****");
}
}
package step3;
public class VariableScopeExam {
int i; //instance variable, 자동 초기화
static int j; // class variable, 자동 초기화
public VariableScopeExam() {
int i=1; // local variable, 명시적 초기화
System.out.println(i);
}
public void test1() {
int i=2; // local variable
System.out.println(i);
System.out.println(this.i); // instance variable
}
public void test2(int i) { //매개변수 parameter이자 local variable
System.out.println(this.i);
System.out.println(i);
int k=8; // local 변수는 선언된 영역 내에서만 사용가능
System.out.println(k);
}
public void test3(int i) { //위 test2()에서 선언한 k를 사용할 수 있을까? nope
//System.out.println(k); -> error - local 변수는 선언된 영역 내(중괄호 안)에서만 사용가능
int y=0;
if(i>0) {
int x=1; //if 실행문 내에서만 x 사용가능
System.out.println(x);
y=2;
}
// if 위의 x 지역변수를 사용할 수 있을까? nope
// System.out.println(x); -> error - local 변수는 선언된 영역 내(중괄호 안)에서만 사용가능
// 위의 y 지역변수를 사용할 수 있을까? yes
System.out.println(y);
}
}
↓
1
****생성자 실행****
2
0
***test1() 실행****
0
7
8
***test2() 실행****
1
2
***test3() 실행****
3. Variable Init. & Variable scope (객체 초기화 단계 및 변수 범위와 메모리 적재 흐름에 대한 예제)
package step4;
public class TestObjectInitAndVariableScope {
public static void main(String[] args) {
Friend f=new Friend("아이유",30);
FriendService service=new FriendService();
service.test1(f);
System.out.println(f.getName()); // ???
System.out.println(f.getAge()); // ??
System.out.println("**TEST1**");
service.test2(f);
System.out.println(f.getName()); // ???
System.out.println(f.getAge()); // ??
System.out.println("**TEST2**");
}
}
package step4;
public class Friend {
private String name;
private int age;
public Friend(String name, int age) {
this.name=name;
this.age=age;
}
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;
}
}
package step4;
public class FriendService {
public void test1(Friend f) {
f=new Friend("손흥민", 31);
}
public void test2(Friend f) {
f.setName("황의조");
}
}
↓
아이유
30
**TEST1**
황의조
30
**TEST2**
🤡 test1() 내멋대로 풀이
1. Friend f 가 우선 Stack에 적재되고 Friend() 생성자로 객체가 생성되면서 Heap에 적재+주소값이 생긴다.
2. FriendService service도 마찬가지
3. FriendService 클래스에 test1 method의 로컬변수는 Friend f 속성이지만 new 예약어로 새로운 객체를 생성해서 다른 주소값을 가진 새로운 객체가 생성되었다.
4. 하지만 같은 이름이라도 주소값이 다른 101 Friend는 로컬변수, 즉 중괄호가 닫히며 사라지는 일시적인; G.C.대상이기 때문에 main method 실행시 원래 f에 할당된 아이유, 30이 결과가 된다.
test2()는 setName으로 아이유를 황의조로 바꿨기 때문에 황의조로 결과가 나옴
4. 객체의 주소값 변경 예제
package step5;
import step4.Friend;
public class TestChangeObject {
public static void main(String[] args) {
Friend f1=new Friend("황희찬",20);
Friend f2=new Friend("정우영",31);
f1=f2;//f2에 저장된 객체 주소값을 f1에 할당한다.
//실행 결과 예상
System.out.println(f1.getName()+" "+f1.getAge());
System.out.println(f2.getName()+" "+f2.getAge());
f1.setName("아이유");
// 실행 결과 예상
System.out.println(f1.getName()+" "+f1.getAge());
System.out.println(f2.getName()+" "+f2.getAge());
}
}
package step4;
public class Friend {
private String name;
private int age;
public Friend(String name, int age) {
this.name=name;
this.age=age;
}
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;
}
}
↓
정우영 31
정우영 31
아이유 31
아이유 31
🤡 내멋대로 풀이
1. Friend f1과 f2가 각각 stack에 쌓인다.
2. Friend()가 각각 생성되며 Heap에 각각 다른 주소의 정보가 저장된다.
3. f2의 정보가 f1으로 할당되며 f1이 f2의 주소값이 바뀌게 된다.
4. sysout으로 각 f1 과 f2의 이름과 나이를 찍어보면 정우영 31이 나온다.
5. 그 상태에서 f1의 이름을 setName으로 '아이유'로 바꾼다.
6. 현재 f1과 f2의 주소값은 같기 때문에 f1의 이름을 바꾸는 것이 황의찬이 아닌 f1이 연결된 101주소에 있는 정우영이 아이유로 바뀌게 된다.
7. sysout 해보면 이름은 아이유, 그리고 나이는 따로 바꾸지 않았기 때문에 31 그대로 나오게 된다.
5. Class Diagram - Association (사람이 렌트카를 이용하는 관계)
package step6;
public class TestAssociation {
public static void main(String[] args) {
Person p=new Person();
p.tour();
}
}
package step6;
public class Person {
public void tour() {
RentCar rentCar=new RentCar("테슬라",20);
System.out.println(rentCar.getPrice()+"원 비용을 지불하고");
System.out.println(rentCar.getModel()+"렌트하여 여행하다");
}
}
package step6;
public class RentCar {
private String model;
private int price;
public RentCar(String model, int price) {
this.model = model;
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
↓
20원 비용을 지불하고
테슬라렌트하여 여행하다
6. Class Diagram - Aggregation 1 (고객이 스마트폰을 소유하다.)
package step7;
public class TestAggregation {
public static void main(String[] args) {
Customer c=new Customer();
c.setName("장기하");
//스마트폰 객체를 만들어서 할당
//customer에 할당
c.setSmartPhone(new SmartPhone("갤럭S22", 100));
System.out.println(c.getName());
System.out.println(c); // customer 객체의 주소값
System.out.println(c.getSmartPhone()); // smartPhone 객체의 주소값
System.out.println(c.getSmartPhone().getModel()); // c 객체가 소유한 smartPhone의 model 명을 반환받아 출력
System.out.println(c.getSmartPhone().getPrice());
// c 객체가 소유한 smartPhone의 price를 200으로 변경
c.getSmartPhone().setPrice(200); // (Error) c.setSmartphone 이런식으로 썼었음
System.out.println(c.getSmartPhone().getPrice());
}
}
package step7;
public class Customer {
private String name;
//aggregation: has a 관계 고객이 스마트폰을 소유하다.
// 이 관계에서는 인스턴스 변수로 저장해 사용한다.
private SmartPhone smartPhone;
public SmartPhone getSmartPhone() {
return smartPhone;
}
public void setSmartPhone(SmartPhone smartPhone) {
this.smartPhone=smartPhone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package step7;
public class SmartPhone {
private String model;
private int price;
public SmartPhone(String model, int price) {
this.model = model;
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
↓
장기하
step7.Customer@2a139a55
step7.SmartPhone@15db9742
갤럭S22
100
200
7. Class Diagram - Aggregation 2 (학생이 노트북을 소유하다.)
package step8;
public class TestAggregation2 {
public static void main(String[] args) {
Student s=new Student();
//아래 코드에 대응하는 student의 인스턴스변수와 메서드를 정의해본다.
s.setName("아이유");
System.out.println(s.getName()); // Student 이름 출력
//아이유 Student 객체가 소유한 NoteBook의 model 명을 반환받아 출력
s.setNoteBook(new NoteBook("그램","흰색"));
System.out.println(s); // 주소값
System.out.println(s.getNoteBook().getModel());
//아이유 Student 객체가 소유한 NoteBook의 color 명을 반환받아 출력
System.out.println(s.getNoteBook().getColor());
// 흰색에서 빨간색으로 변경
s.getNoteBook().setColor("빨간색");
System.out.println(s.getNoteBook().getColor());
}
}
package step8;
public class NoteBook {
private String model;
private String color;
public NoteBook(String model, String color) {
this.model = model;
this.color = color;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package step8;
public class Student {
private String name;
private NoteBook noteBook;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public NoteBook getNoteBook(){
return noteBook;
}
public void setNoteBook(NoteBook noteBook) {
this.noteBook = noteBook;
}
}
↓
아이유
step8.Student@2a139a55
그램
흰색
빨간색
// 오늘의 단축키
cmd + shift + o => Scanner import 단축키
"\t"+2 =-> tab만큼 띄어쓰기
// 오늘의 질문
- 생성자에서는 명시적 초기화를 해줄 필요없나요? -> 생성자의 매개변수는 로컬변수지만 명지석 초기화 필요없음(하면 에러)
//오늘의 이슈
eclipse+for문 review
//오늘의 숙제
복습+!!상속 예습!!