실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다.
객체지향 이론 (캡상추다)
관점 3가지
코드 작성시 유의사항
프로그래밍 : 설계 + 코드작성
객체지향 개념에 얽매여서 프로그램을 작성하기보다 프로그램을 기능적으로 완성한 다음 어떻게 하면 보다 객체지향적으로 코드를 개선할 수 있을지를 고민하여 점차 개선해 나가는 것이 좋다.
프로그래밍에서의 객체는 클래스에 정의된 내용대로 메모리에 생성된 것을 뜻함
클래스로부터 객체를 만드는 과정 : 클래스의 인스턴스 화
어떤 클래스로 부터 만들어진 객체 : 그 클래스의 인스턴스
< Class 의 구성 >
Class Tv {
String color; // 속성
Boolean power; // 인스턴스 멤버 변수
Int channel;
void power(); // 기능
void channelUp(); // 인스턴스 멤버 함수
void channelDown();
int method(int a, int b) { // a, b 는 메소드의 매개변수(parameter)
Result = a + b
return Result;
}
Public static void main(String[] args) {
method(3,7); // 3, 7 args(아규먼트) 라고한다.
}
}
※ 참고
인스턴스(인스턴스 멤버변수, 인스턴스 멤버함수)는 참조변수를 통해서만 다룰 수 있다.
참조변수의 타입은 인스턴스 타입과 일치해야한다.
참조변수에는 하나의 값(주소)만이 저장 될 수 있고, 둘 이상의 참조변수가 하나의 인스턴스를 가리키는(참조하는) 것은 가능하지만 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 가능하지 않다.
(1) 하나의 인스턴스르 여러 개의 참조변수가 가리키는 경우(가능)
(2) 여러 인스턴스를 하나의 참조변수가 가리키는 경우(불가능)
목적 : 많은 수의 객체를 다뤄야 할때, 배열로 다루면 편리
객체 배열 안에 객체가 저장되는 것은 아니고, 객체의 주소가 저장된다.
객체 배열 생성 방법
방법 ①
Tv[] tvArr = new Tv[3]; // 참조변수 배열(객체 배열)을 생성
// 객체를 생성해서 배열의 각 요소에 저장
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
방법 ②
Tv[] tvArr = {
new Tv(),
new Tv(),
new Tv(),
};
```
방법 ③ (객체 수가 많을 때)
Tv[] tvArr = new Tv[100];
for(int i=0; i<tvArr.length; i++){
tvArr[i] = new Tv();
}
방법 ④ (서로 다른 객체를 배열에 넣고 싶을 때)
Class Tv {
String color;
boolean power;
int channel;
void power(){
power = !power;
};
void channelUp(){
++channel;
};
void channelDown(){
--channel;
};
}
Class TvTest4{
public static void main(String args[]){
Tv [] tvArr = new Tv[3];
for(int i=0; i< tvArr.length; i++){
tvArr[i] = new Tv();
tvArr[i].channel = i + 10;
}
for(int i=0; i< tvArr.length; i++){
tvArr[i].channelUp();
System.out.println("tvArr[%d].channel=%d%n", i, tvArr[i].channel);
}
}
}
객체 배열 생성시 주의할점
관점 2가지
객체 지향 이론 : 클래스는 객체를 생성하기 위한틀, 클래스는 속성과 기능으로 정의 되어 있다. 객체로 정의되어 있다. 설명되어 있다.
프로그래밍 관점 : 관점 2가지 데이터와 함수의 결합, 사용자 정의 타입
클래스 - ① 데이터와 함수의 결합
변수 : 하나의 데이터를 저장할 수 있는 공간
배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
구조체 : 서로 관련된 여러 데이터를 종류에 관계 없이 하나의 집합으로 저장 할 수 있는 공간
클래스 : 데이터와 함수의 결합 (구조체 + 함수)
프로그래밍 언어에서 데이터를 처리를 하기윈한 데이터 저장형태의 발전과정
클래스 - ② 사용자 정의 타입
Class Time {
int hour;
int minute;
float second;
int[] hour = new int[3];
int[] minute = new int[3];
float[] second = new float[3];
}
// 위 식을 아래 식으로 변경
Class Time {
int hour;
int minute;
float second;
}
Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();
Time[] t = new Time[3];
t[0] = new Time();
t[1] = new Time();
t[2] = new Time();
변수의 종류, 선언 위치, 생성 시기
// 3.1, 3.2 변수에 대한 정리 한번에
① 문장들을 묶어 놓은 것
② 값(입력)을 받아서 처리하고, 결과를 반환(출력)
※ 참고 : 함수 vs 메소드
int add (int a, int b) { // 선언부
int result = a + b; // 구현부
return result;
}
메서드이름(값1, 값2, …);
메서드의 실행 흐름
① MyMath mm = new MyMath(); // 먼저 인스턴스를 생성
② long value = mm.add(1L, 2L); // 메서드를 호출한다.
③ long add(long a, long b) {
long result = a + b;
return result;
}
① main 메서드에서 add를 호출한다. 인수 1L과 2L이 메서드 add의 매개변수 a,b에 각각 복사(대입)된다.
② 메서드 add의 괄호{}안에 있는 문장들이 순서대로 수행된다.
③ 메서드 add의 모든 문장이 실행되거나 return문을 만나면, 호출한 메서드(main메서드)로 되돌아와서 이후의 문장들을 실행한다.
① 실행중인 메서드를 종료하고 호출한 곳으로 되돌아간다.
② 반환값
※ return 문 주의할점
① 반환 타입이 void가 아닌 경우, 반드시 return문 필요
② 생성자는 return 문을 필요로 하지 않는다.
메서드영역
힙영역
호출 스택
메모리 구조에 대한 이해 자세히
기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.
코드에 따른 메모리구조 자세히
Call by value vs Call by reference
매개변수 뿐만 아니라 반환타입도 참조형이 될 수 있다.
반환 타입이 참조형이라는 것은 반환하는 값의 타입이 참조형이라는 얘긴데, 모든 참조형 타입의 값은 '객체의 주소'이므로 그저 정수값이 반환되는 것일 뿐 특별할 것이 없다.
재귀호출 : 메서드의 내부에서 메서드 자신을 다시 호출하는 것
void method() {
method(); // 재귀호출
}
다음과 같이 작성하면 무한히 자기 자신을 호출하기 때문에 무한 반복에 빠진다.
무한 반복문이 조건문과 함께 사용되어야 하는 것 처럼, 재귀호출도 조건문이 필수적으로 따라다닌다.
void method(int n){
if(n==0)
return; // n의 값이 0 일떄, 메서드를 종료한다.
System.out.println(n);
method(--n);
}
인스턴스 메서드 : 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다 .
인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는)메서드를 클래스 메서드(static 메서드)로 정의한다.
① 클래스를 설계할 때, 멤버 변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
② 클래스 변수(static변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
③ 클래스 메서드(static메서드)는 인스턴스 변수를 사용할 수 없다.
④ 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야 하는 것이 있는 살펴보고 있으면, static을 붙여준다.
작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙일 것을 고려한다.
클래스멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야한다.
why? 클래스멤버는 객체생성없이 호출이 가능하다. 하지만 인스턴스 멤버는 객체를 생성해야 호출이 가능하기 때문에 호출하고자 하는 경우에는 인스턴스를 생성해야한다.
이와관련된 관계 코드 실습
Q&A 정리
Q1. static 메서드는 static 메서드 호출가능?
네
Q2. static 메서드는 인스턴스 변수 사용가능?
아니오
Q3. static 메서드는 인스턴스 메서드 호출 가능?
아니오
Q4. 왜? static 메서드는 인스턴스 멤버를 쓸 수 없나요?
static 메서드 호출 시 객체 iv 묶음 가 없을 수도 있어서
한 클래스 안에 같은 이름의 메서드 여러개 정의 하는 것
void println()
void println(boolean x)
void println(char x)
void println(double x)
void println(char[] x)
void println(String x)
void println(Object x)
① 메서드 이름이 같아야 한다.
② 매개변수의 개수 또는 타입이 달라야 한다.
③ 반환 타입은 영향 없다.
<보기1>
조건1 : method 이름 동일
조건2 : 매개변수갯수 동일, 타입 동일
조건3 : 반환 타입은 영향을 미치지 않는다
그러므로 중복정의
<보기2>
조건1 : method 이름 동일
조건2 : 매개변수갯수 동일, 타입 동일
조건3 : 반환 타입은 영향을 미치지 않는다
그러므로 중복정의
<보기3>
조건1 : method 이름 동일
조건2 : 매개변수갯수 동일, 타입 다름
조건3 : 반환 타입은 영향을 미치지 않는다
여기서 add(3,3); 하면 컴퓨터가 보기3번을 인식하지 못한다. 컴파일러가 어느것을 사용할 것인지 에러가난다. (ambiguous error 모호하다.)
같은 이름의 메서드들을 오버로딩하면 해당 기능은 같은 기능을 하겠구나 라고 생각을 하게된다.
또한 메서드의 이름을 절약 할 수 있다는 것이다.
오버라이딩 : 조상 클래스로 부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩 (덮어쓰다, 재정의한다.)
오버로딩 : 메서드의 기능이 동일한 것
????????
생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다.
< 조건 >
※ 생성자도 메서드이기 때문에 리턴 값이 없다는 의미의 void를 붙여야 하지만, 모든 생성자가 리턴값이 없으므로 void를 생략 할 수 있게 한 것이다.
class Card {
Card() {
// 기본 생성자
}
Card(String k, int num) {
// 매개변수가 있는 생성자.
// 생성자 오버로딩
}
}
강조
연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.
생성자는 단순히 인스턴스를 변수들의 초기화에 사용되는 조금 특별한 메서드 일뿐이다.
생성자는 인스턴스 객체를 생성할때마다 생성된다.
모든 클래스에는 반드시 하나 이상의 생성자가 정의 되어 있어야 한다.
class Car {
String color;
String gearType;
int door;
Car() { }
Car(String c, Sting g, int d) {
color = c;
gearType = g;
door = d;
}
}
위의 코드처럼 class를 내부에 생성자를 생성해두면 다음과 같이 인스턴스의 초기화를 진행할 경우 편리하게 코드를 관리할 수 있다.
Car c = new Car("white", "auto", 4); 초기화 생성자
예를들어
Car(String color) { // 새로운 생성자의 정의
door = 5;
Car(color, "auto", 4); // 위에 예제의 생성자 호출
// 두 번째 줄이므로 에러 발생
// 또한, this(color, "auto", 4);로 해야함
}
해당 코드의 이해를 반드시 해야함.
또한 this() 와 this.인스턴스멤버변수의 차이를 식별해야함
< 정리 >
this 인스턴스 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다. 모든 인스턴스메서드에 지역변수로 숨겨진 채로 존재한다.
this(), this(매개변수) 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.
※ 참고
this와 this()는 비슷하게 생겼을 뿐 완전히 다른 것이다. this는 '참조변수' 이고, this()는 '생성자'이다.
현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.
포인트
하나의 클래스로부터 생성된 모든 인스턴스의 메서드와 클래스변수는 서로 동일하기 떄문에 인스턴스간의 차이는, 인스터스마다 각기 다른 값을 가질 수 있는 인스턴스 변수일 뿐이다.
여기서의 포인트는 실행결과의 4번째줄과 5번째줄이다.
c1.door의 인스턴스 멤버변수의 리터럴 값을 변경했음에도 c2.door의 값이 변하지 않았다는 의미
의미는 c1.door c2.door의 각각 따로 주소값이 저장되어있는 메모리에 값이 인풋 되어진 것이기 때문에 에초에 객체를 새로 생성했다는 의미로 받아들여야 된다. 자바의 에서의 포인트는 객체를 생성할 뿐이지 객체를 복사했다고해서 그 값을 서로 공유한다는 것은 아니다.
인스턴스를 생성할 때는 다음의 2가지 사항을 결정해야한다.
1. 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
2. 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?
변수의 초기화 : 변수를 선언하고 처음으로 값을 저장하는 것
변수의 초기화는 경우에 따라서 필수적이기도 하고 선택적이기도 하지만, 가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다.
① 멤버변수는 초기화를 하지 않아도 자동적으로 변수의 자료형에 맞는 기본값으로 초기화가 이루어짐
② 지역변수는 사용하기 전에 반드시 초기화 해야한다.
선택적 : 클래스변수, 인스턴스 변수, 배열
필수적 : 지역변수(수동초기화)
멤버변수(클래스변수와 인스턴스변수)와 배열의 초기화는 선택적이지만,
지역변수의 초기화는 필수적이다.
지역변수를 선언하는 방법 여러가지 경우의 수
멤버변수의 초기화는 지역변수와 달리 여러 가지 방법이 있다.
< 정리 >
cv, iv 초기화
① 자동초기화 (자동컴파일 0으로 해주는것)
② 간단초기화 (대입연산자 사용하여 초기화 = 명시적 초기화)
③ 복잡초기화
명시적 초기화(=) 대입연산자를 사용하여 초기화하는것이 명시적 초기화 이다.
class Car {
int door = 4; // 기본형 변수의 초기화
Engine e = new Engin(); // 참조형 변수의 초기화
}
when ? : 복잡한 초기화 {} 안에 여러 문장을 넣을 수 있다.
초기화 블럭 (초기화하기 복잡할 때 쓴다.)
class StaticBlockTest {
static int[] arr = new int[10]; // 명시적 초기화(간단초기화)
static { // 클래스 초기화 블럭 - 배열 arr을 난수로 채운다.
for(int i=0; i< arr.length; i++) {
arr[i] = (int)(Math.random)*10) + 1; // 복잡초기화
}
}
}
클래스 변수 초기화 시점 : 클래스가 처음 로딩될때 단 한번 (메모리에 올라갈때)
인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때 마다 (각각 저장공간이 초기화된다)
class InitTEST {
static int cv =1; // 명시적 초기화
int iv = 1; // 명시적 초기화
static { cv = 2; } // 클래스 초기화 블럭
{ iv = 2; } // 인스턴스 초기화 블럭
InitTest() { // 생성자
iv = 3;
}
}
명심해야 할것
InitTest it = new InitTest(); 를 다른 클래스에서 객체를 생성할때 클래스 초기화는 더이상 되지않고 인스턴스 초기화는 해당되는 인스턴스가 객체화 될때마다 초기화가 진행된다.
그림보면서 파악해야되는것
변수가 생성되는것,
변수가 변경되는것 구분할줄알아야함
어떤 초기화를 사용했는지 구분
어느 시점에서 초기화 되었는지
1,2,3 은 새로 생성된 변수
4,5,6,7 의 경우는 인스턴스변수가 계속 변경되는 것
① CV → iv
② 초기화 순서가 자동(0) → 간단(=) → 복잡(static{}, 생성자)