-
8. 객체지향프로그래밍2개발자 수업/Java 2021. 10. 5. 18:24
1. JVM의 메모리 구조
1) 호출스택(Call Stack) -- LIFO(Last In First Out), 후입선출
- 메서드의 저장공간
- 메서드가 호출되면 메서드가 수행에 필요한 메모리 공간을 할당받고
- 메서드가 종료되면 사용하던 메모리를 반환함
- 프로그램의 시작점 main()이 시작하면서 필요한 메모리 공간을 할당함
- 호출 스택에서 맨 위에 있는 메서드가 현재 실행중이며, 아래에 있는 메서드가 바로 위에 있는 메서드를 호출한 메서드이며 대기 상태/* * 콜스택(stack, LIFO)은 후입선출 * <---> 큐(Queue, FIFO)는 선입선출 */ public class CallStackTest { public static void first() { System.out.println("first() 실행됨"); second(); System.out.println("first() 종료됨"); } public static void second() { System.out.println("second() 실행됨"); CallStackTest.third(); System.out.println("second() 종료됨"); } public static void third() { System.out.println("third() 실행됨"); System.out.println("third() 종료됨"); } public static void main(String[] args) { System.out.println("main() 실행됨"); CallStackTest.first(); System.out.println("main() 종료됨"); } }
2) 힙(Heap)
- 인스턴스가 생성되는 공간
- new 연산자에 의해서 생성되는 객체는 모두 여기에 생성됨
2. 인스턴스 생성과 힙 메모리(heap memory)
1) 인스턴스(instance)
- 클래스는 객체의 속성을 정의하고, 기능을 구현하여 만들어 놓은 코드 상태
- 실제 클래스 기반으로 생성된 객체(인스턴스)는 각각 다른 멤버 변수값을 가지게 됨
- new 키워드를 사용하여 인스턴스 생성
2) 힙 메모리
- 생성된 인스턴스는 동적메모리 할당됨
- C, C++ 언어에서는 사용한 동적 메모리를 프로그래머가 해제시켜야 함(free(), delete())
- 자바에서는 Garbage Collector(GC)가 주기적으로 사용하지 않는 메모리를 수거함
3. 생성자(Constructor)
0) 모든 클래스는 반드시 최소 하나 이상의 생성자가 있어야 함
1) 생성자 기본 문법 : class_name([argument_list]) {statements}
2) 객체를 생성할 때 new 키워드와 함께 사용함
3) 생성자는 일반 함수처럼 기능을 호출하는 것이 아니고 객체를 생성하기 위해 new와 함께 호출됨
4) 객체가 생성될 때 변수나 상수를 초기화하거나 다른 초기화 기능을 수행하는 메서드를 호출함
5) 생성자는 반환 값이 없고, 생성자 이름은 클래스의 이름과 동일
6) 대부분의 생성자는 외부에서 접근 가능하지만, 필요에 의해 private으로 선언되는 경우도 있음class A { int value; } class B { int value; // public B() { // // } public B(int value) { this.value = value; } } public class ConstructorTest { public static void main(String[] args) { A a = new A(); B b = new B(30); /* * 컴파일 예외 발생 해결 방법 * 1) B클래스에 기본 생성자를 추가 * 2) B클래스 생성자 호출 시 매개변수 값으로 int 값을 지정 */ } }
/* * 1. this : 참조변수와 같은 역할 * 매개변수와 인스턴스 멤버변수와 구분 짓는 데 사용 * (반드시 this 사용해서 명확하게 프로그램 실행되도록 함) * 2. this() : 생성자에서 다른 생성자 호출 * 같은 클래스 내에서 다른 생성자를 호출할 때 사용 * 다른 생성자 호출은 생성자의 첫 문장에서 사용해야 함 * */ public class Car { String color; String gearType; int door; public Car() { // 직접적으로 인스턴스 멤버변수를 초기화 // this.color = "노랑"; // this.gearType = "수동"; // this.door = 4; // 같은 클래스 내에 있는 매개변수가 3개가 있는 생성자를 호출하는 구문 this("노량", "수동", 4); } public Car(String color, String gearType, int door) { this.color = color; this.gearType = gearType; this.door = door; } // 생성자를 이용한 인스턴스 복제 // 생성자에서 참조변수를 매개변수로 받아서 인스턴스 변수들의 값을 복제 public Car(Car car) { this.color = car.color; this.gearType = car.gearType; this.door = car.door; } @Override public String toString() { return this.color + ", " + this.gearType + ", " + this.door; } } public class CarTest { public static void main(String[] args) { Car car1 = new Car(); System.out.println(car1); Car car2 = new Car("흰색", "오토", 4); System.out.println(car2); Car car3 = new Car(car1); System.out.println(car3); Car car4 = new Car(car2); System.out.println(car4); System.out.println(); for(int i=0; i<10; i++) { Car car = new Car(car2); System.out.println((i+1) + "번째 차: " + car); } } }
4. 기본 생성자(default constructor)
1) 클래스에는 반드시 최소 하나 이상의 생성자는 존재해야 함
2) 클래스에 생성자를 구현하지 않아도 new 키워드와 함께 생성자를 호출할 수 있음
3) 클래스에 생성자가 하나도 없는 경우 컴파일러가 생성자 코드를 넣어줌
public Time() {}
4) 매개변수 없음, 구현부 없음
5. 생성자 오버로딩
1) 생성자의 매개변수의 개수, 타입, 타입의 순서가 다른 경우
2) 생성자의 매개변수 이름은 영향을 주지 않음
6. 참조 자료형
1) 변수 자료형
- 기본 자료형 : int, long, float, double ...
- 참조 자료형 : String, Date, Student ...
2) 클래스형으로 변수를 선언
3) 기본형은 사용하는 메모리의 크기가 정해져 있지만, 참조 자료형은 클래스에 따라 다름package kr.co.ezenac.constructor; public class Student { // 인스턴스 멤버 변수 선언 private String name; private int age; // 기본 생성자 // 생성자가 하나도 없는 클래스는 기본적으로 컴파일 시에 컴파일러가 기본 생성자를 추가해줌 public Student() { System.out.println("기본 생성자 호출"); } //매개 변수가 있는 생성자 public Student(String name, int age) { System.out.println("매개 변수가 있는 생성자 호출"); this.name = name; this.age = age; } public Student(String name) { System.out.println("매개 변수가 String만 있는 생성자 호출"); this.name = name; } public Student(int age) { System.out.println("매개 변수가 int만 있는 생성자 호출"); this.age = age; } public String getName() { return name; } public int getAge() { return age; } public String toString() { return this.getName() + ", " + this.getAge(); } } public class StudentTest { public static void main(String[] args) { // 기본 생성자 호출 Student student = new Student(); System.out.println(student.getAge()); System.out.println(student.getName()); // 매개 변수가 있는 생성자 호출 Student student2 = new Student("이순신", 30); System.out.println(student2); Student student3 = new Student("류현진"); System.out.println(student3); Student student4 = new Student(35); System.out.println(student4); } }
/* * 참조 자료형 사용하기 * - 학생의 수강 과목 성적 산출 * - 학생(Student)과 과목(Subject)에 대한 클래스를 분리하여 사용하고 * 과목 클래스를 활용하여 수강한 과목들의 변수 타입으로 선언 */ public class Subject { String subjectName; int score; int subjectID; } // 참조 자료형 정의하여 사용하기 public class Student { int studentID; String studentName; Subject korean; Subject math; public Student(int id, String name) { this.studentID = id; this.studentName = name; korean = new Subject(); math = new Subject(); } public void setKoreanSubject(String name, int score) { korean.subjectName = name; korean.score = score; } public void setMathSubject(String name, int score) { math.subjectName = name; math.score = score; } public void showInfo() { int total = korean.score + math.score; System.out.println(studentName + " 학생의 총점은 " + total + "점 입니다."); } } public class StudentTest { public static void main(String[] args) { Student student1 = new Student(20211005, "김광현"); student1.setKoreanSubject("국어", 100); student1.setMathSubject("수학", 91); Student student2 = new Student(20211006, "최지만"); student2.setKoreanSubject("국어", 89); student2.setMathSubject("수학", 90); student1.showInfo(); student2.showInfo(); } }
7. 접근 제어 지시자(access modifier)
1) 클래스 외부에서 클래스의 멤버 변수, 메서드, 생성자를 사용할 수 있는지 여부를 지정하는 키워드
2) private : 같은 클래스 내부에서만 접근 가능 (외부 클래스, 상속 관계의 클래스에서도 접근 불가)
3) 아무것도 없음 (default) : 같은 패키지 내부에서만 접근 가능
4) protected : 같은 패키지나 상속 관계의 클래스에서 접근 가능하고 그 외 외부에서는 접근 불가
5) public : 클래스의 외부 어디서나 접근 가능/* * 접근제어자(Access Modifier)의 종류 * - private : 같은 클래스 내에서만 사용 가능함 * - protected : 같은 패키지, 자손 클래스에서만 접근 가능함 * - (default) : 같은 패키지에서만 접근 가능 * - public : 누구나 다 접근 가능 * * 멤버 변수는 private으로 접근제어자를 설정하고(캡슐화) * 각 멤버 변수에 해당하는 getter()를 제공해주는 방법으로 클래스를 작성함 */ public class Time { private int hour; private int minute; private int second; // getter() : 멤버 변수 값을 읽어가는 메서드 public int getHour() { return this.hour; } // setter() : 멤버 변수 값을 수정하는 메서드 public void setHour(int hour) { // 시에 대한 예외처리 코드 작성 if(hour < 0 || hour > 23) { System.out.println("시간을 잘못 입력했습니다."); return; } this.hour = hour; } /* * Source 메뉴 => Generate Getter and Setter 클릭 후 원하는 멤버 변수를 체크하여 getter, setter를 자동완성하면 됨 */ public int getMinute() { return minute; } public void setMinute(int minute) { // 분에 대한 예외처리 코드 작성 if(minute < 0 || minute > 59) { System.out.println("분을 잘못 입력했습니다."); return; } this.minute = minute; } public int getSecond() { return second; } public void setSecond(int second) { // 초에 대한 예외처리 코드 작성 if(second < 0 || second > 59) { System.out.println("초를 잘못 입력했습니다."); return; } this.second = second; } @Override public String toString() { return this.getHour() + "시 " + this.getMinute() + "분 " + this.getSecond() + "초 입니다."; } } public class TimeTest { public static void main(String[] args) { Time time = new Time(); // 시를 설정 time.setHour(23); // 분을 설정 time.setMinute(55); // 초를 설정 time.setSecond(10); System.out.println(time.toString()); // 같은 결과 System.out.println(time); // 같은 결과 } }
8. 정보 은닉
1) 객체 지향 프로그래밍에서 정보은닉은 필요한 외부에서 접근 가능한 최소한의 정보를 오픈함으로써
객체의 오류를 방지하고 클라이언트 객체가 더 효율적으로 객체를 활용할 수 있도록 해줌
9. 정보 은닉을 활용한 캡슐화(enacpsulation)
1) 꼭 필요한 정보와 기능만 외부에 오픈함
2) 대부분의 멤버 변수와 메서드를 감추고 외부에 통합된 인터페이스만 제공하여 일관된 기능을 구현하게 함
// 2021년 10월 5일입니다. public class BirthDay { private int day; private int month; private int year; private boolean isValid = true; public int getDay() { return day; } public void setDay(int day) { this.day = day; } public int getMonth() { return month; } public void setMonth(int month) { if(month < 1 || month > 12) { isValid = false; } else { this.month = month; } this.month = month; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public void showInfo() { if(isValid) { System.out.println(year + "년 " + month + "월 " + day + "일 입니다."); } else { System.out.println("유효하지 않은 날짜입니다."); } } } public class BirthDayTest { public static void main(String[] args) { BirthDay birthday = new BirthDay(); birthday.setYear(2021); birthday.setMonth(10); birthday.setDay(05); birthday.showInfo(); } }
'개발자 수업 > Java' 카테고리의 다른 글
10. 배열 (0) 2021.10.06 9. 객체지향프로그램3 (0) 2021.10.06 6. Review / 7.객체지향프로그램 (0) 2021.10.04 5. 반복문 (while문, do~while문, for문) (0) 2021.10.01 210930 / if문, if else문, if else if문, switch case문, Math.random() (0) 2021.10.01