티스토리 뷰
1. 요약
- OOP(객체지향프로그래밍) : 부품 객체를 먼저 만들고, 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법이다.
- 클래스는 붕어빵 틀이고, 객체는 붕어빵이다.
- 객체 모델링 : 현실세계의 것(ex.사람)을 필드(속성 – 나이, 이름)과 메소드(동작/행위 – 웃다, 먹다)로 구성된 자바 객체로 바꾸는 것.
- 객체의 상호작용 : 객체들은 메소드를 통해서 서로 간에 기능을 이용하고 데이터를 주고 받는다.
2. 객체 지향 프로그래밍
- 객체간 관계의 종류 : 1. 집합관계 2. 사용관계 3. 상속관계
- 1) 사용관계 : 객체가 다른 객체를 사용하는 관계
- 2) 집합관계 : 완성품과 부품의 관계
- 3) 상속관계 : 종류객체와 구체적인 사물 객체 관계 ( 부모객체[기계] – 자식객체[자동차] )
- 상속관계에서 자식객체는 부모객체의 속성(필드)과 행위(메소드)를 물려받는다.
- 그렇게 되면, 자식객체는 부모객체의 속성과 행위 + 자기자신만의 속성과 행위를 갖게 된다.
- OOP 3대 특징 1. 캡슐화(Encapsulation) 2. 상속(Inheritance) 3. 다형성(Polymorphism)
3. 객체 지행 프로그래밍의 특징
- 1 ) 캡슐화 ( Encapsulation – 캡슐화 )
- 노출된 메소드/데이터와 숨긴 데이터/메소드로 구분되어있다.
- 외부 객체는 객체 내부 구조를 알지 못하며, 객체가 노출해 제공하는 필드와 메소드만 이용이 가능하다.
- 필드와 메소드를 캡슐화를 통해 보호하는 이유는 외부의 잘못된 사용으로 객체가 손상되지 않기 위해서이다.
- 자바 언어는 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지 결정하기 위해 접근 제한자 ( Access Modifier )을 사용한다.
- 2 ) 상속 ( Inheritance )
- 상위(부모) 객체의 필드와 메소드를 하위(자식) 객체에게 물려주는 행위
- 하위객체는 상위 객체를 확장해서 추가적인 필드와 메소드를 가질 수 있다.
- 상속 대상 : 필드와 메소드
- 상속의 효과 :
- [1] 상위 객체를 재사용해서 하위 객체를 빨리 개발하는 것이 가능하다.
- [2] 반복된 코드의 중복을 줄여준다.
- [3] 유지 보수의 편리성 제공 ( 부모의 변동이 자식에게도 적용 )
- [4] 상속은 객체의 다향성 구현의 조건이 된다.
- 3 ) 다형성 ( Polymorphism )
- 같은 타입이지만, 실행 결과가 다양한 객체를 대입할 수 있는 성질이다.
- Ex. 타이어라고 하더라도 메이커에 따라서 다른 기능을 발휘한다.
- 부모타입에는 모든 자식 객체가 대입이 가능하다. ( 다향성1 )
- 다향성의 효과 :
- [1] 객체를 부품화시키는 것이 가능해진다.
- [2] 유지보수가 용이하다.
4. 객체와 클래스
- 클래스(A클래스)를 통해서 객체(인스턴스 - A클래스의 인스턴스)를 만드는 과정을 “인스턴스화”라고 부른다.
5. 클래스 선언
- 클래스의 이름은 기본적으로 자바 식별자 작성 규칙에 따른다.
- 단지, 첫번째 단어부터 Camel 기법을 적용하여 대문자로 시작하게 된다.
- 1 ) 클래스 선언과 컴파일
- 소스파일과 public을 붙인 클래스의 이름은 동일해야 한다.
- 소스 작성 : Public class 클래스 이름 { } -> 클래스이름.class
- 소스파일 당 하나의 클래스를 선언하는 것이 관례이지만,
- 두 개 이상의 클래스를 선언하는 것도 가능은 하다.
- + New 클래스 ( ) ; <- 객체를 생성하는 역할을 한다.
- Ex. Student s1 = new Student( );
- => 클래스 변수이름 = new 클래스( );
- 클래스 변수;
- + -> 변수 = new 클래스 ();
- + New 연산자의 역할 3가지 :
- 1. 힙(heap) 영역에 새로운 객체를 생성
- 2. 생성자를 호출해서 힙에 생성된 객체를 초기화(초기값)해준다.
- 3. 초기화까지 완료된 객체의 주소(참조)를 반환한다.
- 이때 new연산자에 의해 반환된 객체의 주소를 저장하는 것을 참조 변수라고 한다.
- 클래스의 용도는 라이브러리용과 실행용으로 구분된다.
- 클래스의 구성 멤버 : 1. 필드(속성) 2. 생성자(초기화) 3. 메소드(행위/동작)
6. 필드
- 변수선언이 class 블록 내에서 선언되게 되면, 이를 필드라고 부른다.
- 필드의 내용 : 객체의 고유 데이터, 객체가 가져야 할 부품 객체, 객체의 현재 상태 데이터 ( 현재 상태는 데이터가 변할 수 있다. – ex. 현재 속도 )
- 초기값으로 지정되지 않은 필드는 객체 생성시 자동으로 기본값으로 초기화된다.
- 필드의 사용은 필드의 사용위치에 따라서 달라진다.
- 같은 클래스 내부 : int speed; -> speed = 10;
- 객체 외부 : Car myCar = new Car ( ); -> myCar.Speed = 60; (*****)
7. 생성자
- New 클래스 ( ); 에서 클래스가 생성자에 해당된다.
- New 연산자에 의해 호출되어 객체의 초기화를 담당한다.
- 필드의 값을 설정해준다.
- 메소드를 호출해서 객체를 사용할 수 있도록 준비해 줄 수도 있다.
- 기본 생성자 :
- 모든 클래스는 생성자가 반드시 존재하며, 1개 이상을 가질 수 있다.
- 생성자 선언을 생략하면 컴파일러가 “ public 클래스명 ( ) { }”과 같은 기본 생성자를 추가해준다.
- 이때 “ public 클래스명 ( ) { } “에서 public은 클래스 이름 앞에 public이 있으면 적히고, 클래스 이름 앞에 public이 없으면 생략해서 “ 클래스명 ( ) { } “가 된다.
- 생성자 선언 :
- 디폴트 생성자 대신 개발자가 직접 선언
- 형식 : 클래스명 ( 매개 변수 선언 ) { // 객체의 초기화 코드 }
- - > 매개 변수에 있는 값으로 객체의 필드에다 넣으라(초기화)는 소리이다.
01. 2차원 배열 - 미리 선언해서 공간확보하기
public class Sample79 {
public static void main(String[] args) {
// 2차원 배열 - 미리 배열 선언해서 공간 확보하기
int[] [] arr = { { 1,2} , {3}, {4,5,6},{}};
// 2차원 배열의 선언은 위처럼 하면 되지만, 원소의 길이가 제각각인 배열의 공간을 미리 확보하기 위해서는
int[] [] arr2 = new int [4] [];
// 일단 첫번째 중괄호{ } 안의 원소가 몇 개인지 파악하여 첫번째 [] 안에 넣고,
// 그 후에 두번째 []에서는 원소의 길이가 다르기에 안에 숫자를 넣지 않고 [] 그대로 두면 된다.
arr2 = new int[] [] { { 1,2} , {3} , { 4,5,6} , {} };
// 선언 성공!
} // main
} // end class
02. 클래스 선언
public class Student {
;; // 아직 코드를 완성하지 못했다는 의미이다.
} // end class
// class가 하나일 때에는 public을 쓰지 않아도 오류가 뜨지는 않는다.
// -> 소스파일 하나 당, 클래스 하나를 선언한다!! ( 기본원칙 ) (***)
//class A { ;; } // end class - A
//class B { ;; } // end class - B
//class C { ;; } // end class - C
// 이렇게 여러 클래스를 생성할 수는 있으나.
// 소스파일의 이름은 public의 이름을 붙인 class의 이름과 동일해야 한다.
// public은 단 1개만 사용이 가능하다.
// 우클릭 - Refactor - Rename을 통해 파일이름을 바꿀 수 있다.
// 하지만 이름을 바꾼 후에 버그가 나타날 수 있으므로, 확인해봐야 한다.
public class StudentExample {
public static void main (String[] args) {
Student s1 = new Student();
System.out.println("s1변수가 Student객체를 참조합니다.");
System.out.println(s1); // Student@372f7a8d가 출력된다. --> Student타입
//
Student s2 = new Student();
System.out.println("s2변수가 Student객체를 참조합니다.");
System.out.println(s2); // Student@2f92e0f4가 출력된다. --> Student타입
//
System.out.println(s1==s2); // false가 출력된다.
System.out.println(s1!=s2); // true가 출력된다.
// new는 항상 새로운 객체를 생성하는 연산자이기 때문이다.
} // main
} // end class
03. 클래스 응용
public class Car {
// 필드 ( 모델링 대상 객체의 속성의 종류와 값을 정의 )
// class 블록에서 변수를 정의하는 것은 변수라고 부르지 않고 "필드"라고 부른다.
// String company = "현대자동차";
// String model = "그랜저";
// String color = "검정";
// ====================================
// 원래 모델링할 때에는 이렇게 선언만 하는 경우가 더 많다.
String company;
String model;
String color;
int maxspeed; // 최대 속도
int speed; // 현재 속도 <-- 초기값을 지정하지 않았기에, 아직까지는 정수타입의 기본값인 0이 들어가 있다.
// 컴파일러가 자동으로 만들어주는 기본 생성자
// public Car() {;;} // 기본 생성자(default constructor)
// 클래스 앞에 public이 붙어 있으면, 생성자 앞에서도 public을 붙어야 한다.
// public이면 외부에서 Car myCar = new Car(); 처럼 코드를 작성하여 이용이 가능하다.
public Car (int maxspeed) {
this.maxspeed = maxspeed; // 외부(CarExample)에서 받은 350이라는 값으로 선언된 maxspeed를 초기화해준다.
// 매개변수는 1개 이상 가능하기 때문에, ( ) 안에 ( int maxspeed, String color, int speed )도 가능하다.
} // 사용자 선언
// 사용자가 선언하여 생성하였을 경우에는 컴파일러가 자동으로 생성해 주지 않는다.
} // end class
public class CarExample {
public static void main (String[] args) { // 클래스 응용 (******)
// 객체 생성 (*****)
Car mycar = new Car(350); // 350을 "전달인자"라고 부르고 영어로는 argument라고 부른다.
// 필드 값 읽기
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);
// 필드 값 변경(write)
mycar.speed=60; // 현재의 속도를 기본값 0에서 60으로 바꾸었다.
System.out.println("수정된 속도 : " + mycar.speed);
}// main
} // end class
04. 클래스 응용2
public class Car1 {
// String color;
// int cc;
Car1(String color, int cc) {
;;
} // user-defined constructor
} // end class
public class Car1Example {
public static void main(String[] args) {
Car1 myCar = new Car1("검정", 3000); // OK!
// Car1 myCar = new Car1(); <---- 이것은 오류가 뜨게 된다.
} // main
} // end class
05. 클래스 응용 3 - this
public class Car2 { // this (******)
// 필드
String Company = "현대자동차";
String model;
String color;
int maxSpeed;
// 중요! : 생성자 오버로딩 ( Constructing Overloading -> 다중정의 ) (****)
// 원칙 : 각 생성자의 매개 변수의 개수, 순서, 타입이 달라야 한다.
// Car2() {
// ;;
// } // 기본생성자
//
// Car2(String model){
// this.model = model;
// } // 생성자1
//
// Car2(String model, String color){
// this.model = model;
// this.color = color;
// } //생성자2
//
// Car2(String model, String color, int maxSpeed){
// this.model = model;
// this.color = color;
// this.maxSpeed = maxSpeed;
// }// 생성자3
// 하지만! 이렇게 되면 중복코딩이 생겨 버린다. 그렇기에 아래처럼 작성하는 것이 좋다.
Car2() {
this(null);
} // 기본생성자 - 생성자 1 호출
Car2(String model){
// this(model,null,0); // 생성자3 호출
// this 키워드의 2번재 용법 (*******) :
// this() 문법을 통해, 다른 생성자를 호출하는 것도 가능하다!! (밑밑의 생성자[생성자3]를 호출한 것이다.)
// 단, 이 방법의 경우 중복코드를 줄일 수는 있으나, 값을 마음대로 정해버린다는 문제가 생겨버린다.
this(model,null); // 생성자2 호출
// 모든 생성자를 생성자3 호출하는 것이 아니라 바로 밑의 생성자를 호출하는 것이 좋다.
} // 생성자1 - 생성자2 호출
Car2(String model, String color){
this(model, color,0);
} //생성자2 - 생성자3 호출
Car2(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}// 생성자3
} // end class
06. 필드의 초기값
public class FieldInitValue {
// 필드
byte byteField;
short ShortField;
int intField;
long longField;
boolean booleanField;
char charField;
float floatField;
double doubleField;
int[] arrField;
String referenceField;
public FieldInitValue () {}
}
public class FieldInitValueExample {
public static void main (String[] args) {
// 개발자도, default 생성자도, 필드의 값을 초기화 해주지 않으면
// 타입별 기본값으로 초기화된다!! ( 정수타입 - 0 실수타입 - 0.0 논리타입 - null 참조타입 - null )
// 타입별로 초기값이 배정되는 이유는 후에 오류가 발생할 수 있으므로, 미리 타입에 맞는 초기값을 배정하는 것이다.
FieldInitValue fiv = new FieldInitValue();
System.out.println("byteField : " + fiv.byteField); // 0
System.out.println("shortField : " + fiv.ShortField); // 0
System.out.println("intField : " + fiv.intField); // 0
System.out.println("longField : " + fiv.longField); // 0
System.out.println("booleanField : " + fiv.booleanField); // false
System.out.println("charField : " + fiv.charField); // 아무것도 출력하지 않는다.
System.out.println("floatField : " + fiv.floatField); // 0.0
System.out.println("doubleField : " + fiv.doubleField); // 0.0
System.out.println("arrField : " + fiv.arrField); // null
System.out.println("referenceField : " + fiv.referenceField); // null
} // main
} // end class
07. this 응용
public class Korean {
// 필드
String nation = "대한민국";
String name;
String ssn;
public Korean ( String name , String ssn ) { // (*****)
this.name = name;
this.ssn = ssn;
// this.name은 필드의 name이고 name;은 매개변수의 name이다.
// this는 생성된 객체의 주소를 가지고 있는 특수한 기능을 수행한다.
// this를 사용하지 않으면 자기 자신안에 자기자신을 넣게 되어 초기화될 수 없다.
System.out.println("this : " + this);
} // constructor
// public Korean (String n, String s ) {
// name = n;
// ssn = s;
// } // constructor <--- 이 방법도 가능은 하지만, 후에 개발하기 불편함을 주기에 위의 방법으로 사용하는 것이 좋다.
} // end class
public class KoreanExample { //(*****)
public static void main(String[] args) {
Korean k1 = new Korean("박자바", "010-1234-5678");
System.out.println("k1.name : " + k1.name);
System.out.println("k1.ssn : " + k1.ssn);
System.out.println("k1 : " + k1); // Korean@372f7a8가 출력되게 되는데, 이는 this와 값이 같다.
// this : Korean@372f7a8d <---- Korean클래스 파일에서 이를 출력하도록 하였기 때문이다.
// k1 : Korean@372f7a8d
// this는 클래스 내에서만 사용이 가능하다.
//
Korean k2 = new Korean("김자바", "010-9876-5432");
System.out.println("k2.name : " + k2.name);
System.out.println("k2.ssn : " + k2.ssn);
System.out.println("k2 : " + k2); // Korean@2f92e0f4가 출력되게 되는데, 이는 this와 값이 같다.
} // main
} // end class
'KH 정보교육원 [ Java ]' 카테고리의 다른 글
KH 11일차 - 정적 초기화 블록과 상수 + 간단한 10일 후기 (0) | 2022.03.11 |
---|---|
KH 10일차 - 생성자 및 인스턴스 / 정적 멤버 (0) | 2022.03.10 |
KH 08일차 - 배열과 열거 (0) | 2022.03.07 |
KH 07일차 - 참조타입 (0) | 2022.03.04 |
KH 06일차 - 조건문과 반복문 (0) | 2022.03.03 |