어떤 대상(객체)를 가지고 프로그래밍한다.
절차지향 vs 객체지향
절차지향프로그래밍은 순서대로 일어나는 일을 시간순으로 프로그래밍하는 것
객체지향프로그래밍은 객체 정의하고 객체 간 협력을 프로그래밍하는 것
객체지향프로그램은 클래스를 기반으로 프로그래밍한다.
클래스 = 객체의 속성 + 기능
(접근 제어자) class 클래스명 {
멤버 변수;
메서드;
}
ex) 학생 클래스 만들기
public class Student {
// 멤버 변수 → 기본 자료형 또는 참조 자료형(다른 클래스형)으로 선언 가능
// 참조 자료형 ex) String, Date, Person(다른 클래스명) 등
int studentID; // 학번
String studentName; // 학생 이름
int grade; // 학년
String address; // 사는 곳
// 메서드
public void showStudentInfo(){
System.out.println(studentName+","+address);
}
}
클래스 파일의 묶음으로, 계층구조를 가질 수 있음!
// 패키지 선언
package classpart;
메서드는 함수의 한 종류이다!
하나의 기능을 수행하는 일련의 코드
함수반환형 함수이름 (매개변수1, 매개변수2, ...){
자료형 변수명1;
...
return 반환값;
}
public class Exam {
public static void main(String[] args) throws Exception{
int n1 = 10;
int n2 = 20;
int sum = add(n1, n2);
System.out.println(n1+" + "+n2+" = "+sum);
}
public static int add (int num1, int num2){
int result;
result = num1 + num2;
return result;
}
}
함수 호출하면 그 함수만을 위한 메모리 공간이 할당되는데, 이 메모리 공간을 스택(stack)
이라고 부름
멤버 변수 사용하여 클래스의 기능 구현
public class Student {
// 멤버 변수
int studentID; // 학번
String studentName; // 학생 이름
int grade; // 학년
String address; // 사는 곳
// 메서드
// 학생 이름 반환하는 메서드
public String getStudentName(){
return studentName;
}
// 학생 이름을 멤버 변수에 대입하는 메서드
public void setStudentName(String name){
studentName = name;
}
}
main()
함수는 자바 가상 머신(JVM)이 프로그램을 시작하기 위해 호출하는 함수로, 클래스의 메서드X
[main() 함수에서 클래스 사용하는 방법]
1. 만든 클래스 내부에 main() 함수 만드는 것
package classpart;
public class Student {
// 멤버 변수
int studentID; // 학번
String studentName; // 학생 이름
int grade; // 학년
String address; // 사는 곳
// 메서드
// 학생 이름 반환하는 메서드
public String getStudentName(){
return studentName;
}
// 학생 이름을 멤버 변수에 대입하는 메서드
public void setStudentName(String name){
studentName = name;
}
public static void main(String[] args){
Student studentAhn = new Student(); // Student 클래스 생성
studentAhn.studentName = "안경";
System.out.println(studentAhn.studentName); // 안경
System.out.println(studentAhn.getStudentName()); // 안경
}
}
package classpart;
public class StudentTest {
public static void main(String[] args) throws Exception{
Student studentAhn = new Student(); // Student 클래스 생성
studentAhn.studentName = "안경";
System.out.println(studentAhn.studentName); // 안경
System.out.println(studentAhn.getStudentName()); // 안경
}
}
클래스형 변수이름 = new 생성자;
인스턴스: 실제로 사용할 수 있도록 생성된 클래스
참조변수: 인스턴스를 가리키는 클래스형 변수
ex) Student studentAhn = new Student();
package classpart;
public class StudentTest {
public static void main(String[] args) throws Exception{
Student student1 = new Student(); // 첫 번째 학생 생성
student1.studentName = "홍길동";
System.out.println(student1.getStudentName());
Student student2 = new Student(); // 두 번째 학생 생성
student2.studentName = "김철수";
System.out.println(student2.getStudentName());
}
}
참조변수.멤버변수
참조변수.메서드
new Student()를 선언하면 Student 하나가 생성되는데 각 Student는 studentID, studentName 등의 멤버 변수를 가지고 있음! 이 변수들을 저장하는 공간을 힙 메모리
라고 함
힙 메모리
힙(heap)은 프로그램에서 사용하는 동적 메모리 공간
- 일반적으로 프로그램은 스택, 힙, 데이터 세 영역을 사용하는데, 객체가 생성될 때 사용하는 공간을 힙
- 힙은 동적으로 할당되며 사용이 끝나면 메모리 해제해 주어야 하는데, C나 C++은 프로그래머가 직접 메모리 해제해주어야 하지만, 자바는 가바지 컬렉터가 자동으로 메모리 해제해줌
즉, 클래스 생성자가 하나 호출하면 인스턴스가 힙 메모리에 생성됨
package classpart;
public class StudentTest {
public static void main(String[] args) throws Exception{
Student student1 = new Student(); // 첫 번째 학생 생성
student1.studentName = "홍길동";
System.out.println(student1); // classpart.Student@7a81197d -> 클래스이름@주소값
Student student2 = new Student(); // 두 번째 학생 생성
student2.studentName = "김철수"; //classpart.Student@5ca881b5
System.out.println(student2);
}
}
용어 | 설명 |
---|---|
객체 | 객체 지향 프로그래밍의 대상, 생성된 인스턴스 |
클래스 | 객체를 프로그래밍하기 위해 코드로 만든 상태 |
인스턴스 | 클래스가 메모리에 생성된 상태 |
멤버 변수 | 클래스의 속성, 특성 |
메서드 | 클래스의 기능 |
참조 변수 | 메모리에 생성된 인스턴스를 가리키는 변수 |
참조 값 | 생성된 인스턴스의 메모리 주소 값 |
생성자
: 클래스를 처음 만들 때 멤버 변수나 상수를 초기화하는 것
package classpart;
public class Person {
String name; // 이름
int height; // 키
double weight; // 몸무게
char gender; // 성별
boolean married; // 결혼 여부
// 자바 컴파일러가 자동으로 제공하는 디폴트 생성자
public Person() {}
}
필요한 경우 프로그래머가 직접 생성자 구현 가능
package classpart;
public class Person {
String name; // 이름
int height; // 키
double weight; // 몸무게
char gender; // 성별
boolean married; // 결혼 여부
// 생성자 만들기
public Person(String pname){
name = pname;
}
}
package classpart;
public class PersonTest {
public static void main(String[] args){
Person person = new Person(); // 오류 발생
}
}
package classpart;
public class Person {
String name; // 이름
int height; // 키
double weight; // 몸무게
char gender; // 성별
boolean married; // 결혼 여부
// 디폴트 생성자 추가
public Person(){}
// 생성자 만들기
public Person(String pname){
name = pname;
}
}
클래스에 생성자가 두 개 이상 제공되는 경우로, 필요에 따라 매개변수가 다른 생성자를 여러 개 만들 수 있음
package classpart;
public class Person {
String name; // 이름
int height; // 키
double weight; // 몸무게
char gender; // 성별
boolean married; // 결혼 여부
// 디폴트 생성자
public Person() {}
// 이름을 매개변수로 입력받는 생성자
public Person(String pname) {
name = pname;
}
// 이름, 키, 몸무게를 매개변수로 입력받는 생성자
public Person(String pname, int pheight, double pweight){
name = pname;
height = pheight;
weight = pweight;
}
}
클래스 자료형으로 선언
package classpart;
public class Student {
int studentID;
String studentName; // String이 JDK에서 제공하는 참조 자료형
int koreaScore;
int mathScore;
}
만약 위 클래스에 과목의 이름 변수도 함께 추가할 경우
package classpart;
public class Student {
int studentID;
String studentName; // String이 JDK에서 제공하는 참조 자료형
int koreaScore;
int mathScore;
String koreaSubject;
String mathSubject;
}
위 같이 작성하면, 학생에 대한 클래스인데 과목에 대한 변수도 늘어나고 있음
따라서, 과목의 이름과 성적을 Subject 클래스로 분리하고, 학생에 Subject 변수를 각 과목별로 추가
// 과목 클래스
package classpart;
public class Subject {
String subjectName;
int scorePoint;
}
package classpart;
public class Student {
int studentID;
String studentName; // String이 JDK에서 제공하는 참조 자료형
Subject korean; // Subject형 사용하여 선언
Subject math; // Subject형 사용하여 선언
}
접근 제어자
: 예약어를 사용해 클래스 내부의 변수나 메서드, 생성자에 대한 접근 권한 지정 가능
public
: 선언한 변수나 메서드는 외부 클래스에서 접근 가능private
: 선언한 변수나 메서드는 외부 클래스에서 사용 Xprotected
: 같은 패키지 내부와 상속 관계의 클래스에서만 접근 가능default(아무것도 없는 경우)
: 같은 패키지 내부에서만 접근 가능package classpart;
public class Student {
int studentID;
private String studentName; // private으로 선언
Subject korean; // Subject형 사용하여 선언
Subject math; // Subject형 사용하여 선언
}
package classpart;
public class StudentTest {
public static void main(String[] args) throws Exception{
Student student = new Student();
student.studentName = "aa"; // 오류 발생 private으로 선언된 변수에 접근할 수 없음
}
}
get()
, set()
메서드package classpart;
public class Student {
int studentID;
private String studentName; // private으로 선언
Subject korean; // Subject형 사용하여 선언
Subject math; // Subject형 사용하여 선언
// private 변수인 studentName에 접근해서 값 가져오는 public get() 메서드
public String getStudentName(){
return studentName;
}
// private 변수인 studentName에 접근해서 값 지정하는 public set() 메서드
public void setStudentName(String studentName){
this.studentName = studentName;
}
}
package classpart;
public class StudentTest {
public static void main(String[] args) throws Exception{
Student student = new Student();
// student.studentName = "aa"; // 오류 발생
student.setStudentName("aa");
System.out.println(student.getStudentName()); // aa
}
}
정보은닉
클래스 내부에서 사용할 변수나 메서드는private
으로 선언해서 외부에서 접근하지 못하도록 하는 것
❓ 변수를 public으로 선언하는 것과 변수를 private으로 선언하고 나서 그 변수를 사용할 수 있도록 public 메서드 제공하는 것의 차이는 무엇인가?
package classpart;
public class MyDate {
public int day;
public int month;
public int year;
}
package classpart;
public class MyDateTest {
public static void main(String[] args){
MyDate date = new MyDate();
date.month = 2;
date.day = 31; // 2월은 31일이 없지만, 그래도 값이 넣어짐!
date.year = 2018;
}
}
package classpart;
public class MyDate {
private int day;
private int month;
private int year;
public void setDay(int year, int month, int day){
if(month==2) {
if(day<1 || day>28){
System.out.println("오류 입니다.");
}else{
this.year = year;
this.month = month;
this.day=day;
System.out.println(year+"년 "+month+"월 "+day+"일");
}
}
}
}
package classpart;
public class MyDateTest {
public static void main(String[] args){
MyDate date = new MyDate();
date.setDay(2018,2,31); // 오류 입니다.
date.setDay(2018,2,28); // 2018년 2월 28일
}
}