객체는 속성(필드)과 기능(메소드)을 가진다.
객체 지향의 특성
캡슐화
- 뭔가를 보호하고 있다는 의미로 볼 수 있음.
- 자바에서는 클래스로 내부의 코드를 보호한다고 볼 수 있다.
위 그림은 동물 클래스를 통해서 사자와 곰 객체를 생성한 것이다.
상속
- 자바의 객체지향에서는 필드와 메소드를 물려주는 것이 상속이다.
- 위 그림에서는 human이 서브 클래스, animal이 슈퍼 클래스로 볼 수 있다.
- 상속받은 human객체를 생성하면 원래 human의 객체와 animal의 특성까지 가져온다.
다형성
- 다형성에는 오버라이딩과 오버로딩이 있다.
- 부모는 같은데 자식 클래스가 내용이 다른 경우 모두 새로운 메소드를 만들어 줘야 한다 - 오버라이딩
- 상속 받아서 메소드를 다르게 구현
절차 지향, 객체 지향 프로그래밍
- 객체 지향에서는 각각의 객체를 생성해놓고, 작동시킨다.
클래스와 객체
- 큰 틀이 클래스고, 그 안의 세부적인 것들이 객체라고 볼 수 있다.
- 각각의 객체에는 필드(이름, 직업 등의 속성)와 메소드(밥 먹기, 걷기 등의 기능)를 부여한다.
클래스 구성
- public : 접근지정자로 public로 있으면 접근에 제한을 받지 않음
- radius와 name은 속성에 해당하는 필드이며, getArea는 기능에 해당하는 메소드
객체 생성과 접근
1. Circle은 클래스 / pizza는 참조변수(아직 객체생성은 되지 않은 상태)
2. 객체 생성(필드 2개와 메소드 1개를 가진 객체)
3. 값 상속받음
4. 메소드로 값을 구한 뒤에 area변수에 값을 대입해줌
<예제>
Circle클래스에 radius와 name필드 2개를 생성한다.
그 다음 면적을 구하는 메소드인 getArea를 만들어주고, 계산식을 넣는다.
생성자 Circle를 선언하고, main 메소드에서 pizza를 생성한다.
<예제>
생성자의 특징
- 클래스 이름
- 오버로딩(같은 이름의 생성자 여러개 사용)
- 객체를 생성할 때 new연산자를 사용하는데 이때, 생성자를 한번 호출함.
- 생성자에는 리턴 타입이 없다.
기본 생성자
위 public Circle가 기본 생성자로 컴파일 할 때 자동으로 생성되서 호출함.
매개변수도 없고, 리턴 타입도 없음
기본 생성자가 자동 생성 안되는 경우
위 코드에서 10의 매개변수가 있는 객체를 생성할 때는 마찬가지로 매개변수가 있는 생성자를 호출한다.
매개변수가 없는 객체를 생성할 때는 컴파일 할 때 기본 생성자를 자동으로 만들어서 호출해야 하는데, 이 때 생성자가 하나라도 있으면, 자동으로 생성자를 만들지 않아서 오류가 난다.
this 레퍼런스
* 필드 = 멤버 변수 / 메소드 = 멤퍼 함수
현재 왼쪽 코드는 클래스1개, 필드 2개, 메소드 1개
필드에 .으로 접근하는 것은 객체로, 저 위의 this는 radius자기 자신의 객체이다.
여기서 this를 주는 이유는 필드 이름도 radius이고, 매개변수 명도radius이기 때문에 둘을 구분해주기 위해서다.
객체 속에서의 this
위 코드는 필드 1개, 메소드 1개를 가지고 있다. 그 이유는 생성자 형태의 메소드와 메인 메소드를 제외하고 말하기 때문.
jvm : public 클래스 - main 메소드 순으로 찾아가서 실행시킴
객체를 생성하는 ob1의 참조변수에 1이 들어가고 이는 매개변수를 1개 가진 public Circle생성자를 호출해서 this.radius에 1이 들어가게 된다.
따라서 int radius에 1 값이 들어가면서 ob1은 1이 된다.
객체 생성 단계에서 ob1~3까지는 모두 위와 같은 단계를 거치면서 반지름에 모두 값이 들어갔다.
아래의 3개는 값을 바꿔치는 단계다.
객체.메소드()의 형태를 가진 것으로, set메소드를 호출하고, ob1.set(4)는 자기자신 객체에 4 값을 넣는 것으로 기존에 1 값을 가졌던 것을 4로 교체한다는 것이다.
즉, 처음에는 객체를 생성하면서 초기값을 세팅하고 나중에 메소드를 불러와 값을 교체한 것이다.
this() 사용 실패 예
this가 나올때는 무조건 첫 번째 줄에 나와야 하며, 그 이외에는 오류가 난다.
예제
1.
2.
3.
첫 번째 생성자는 아무것도 나타나지 않는 값을 구하기 위한 의미를 가지고 있다.
4.
만약 생성자에서 매개변수명을 위의 변수명과 똑같이 사용했다면 this를 사용하면 된다.
<문제>@@@@@
<문제>
- 멤버 변수는 보통 private으로 생성한다. (private int math와 같이)
- 그리고 저기서 class가 2개가 나와있는 것도 약간 문제다. 아래의 public class Grade를 가장 위로 올려야 함
class를 2개 쓸 필요가 없었다.
객체 치환
ob1은 참조변수로 new를 통해서 객체가 하나 생성된다. 객체 안에는 필드 1개와 메소드 1개가 있다.
Circle ob1 = new Circle(1);은 생성자를 호출하며, 이때 호출되는 생성자는 매개변수가 있는 생성자인 가장 위의
Public Circle(int radius)이다.
이 생성자의 중괄호 안에는 this.raidus = radius가 있는데, 이는 자기 자신을 가리키는 것으로, 이 객체의 radius에 주어진 매개변수의 값을 넣는 다는 것이다.
동일한 루트로 ob2에는 현재 2의 값이 들어가 있다.
Circle s는 Circle클래스의 s 참조변수를 선언한 것이다. 그리고 이 s는 ob2를 바라보고 있다.
ob1 = ob2도 있는데, 이는 ob1이 ob2를 바라보게 되는 것으로 원래 바라보고 있던 연결이 끊기고 ob2로 가게되는데, 이때, 자기가 가지고 있던 값을 가지고 가는 것이 아니라 그냥 연결을 끊고 바라보게 된다.
마지막 출력문을 보면 ob1, ob2를 따로 출력시키는데 값은 똑같다.
왜냐하면 위에서 ob1도 ob2를 바라보도록 만들었기 때문이다.
객체 배열
- 객체 배열을 잘 사용하면 자르지 못할 데이터가 없게된다.
객체 배열은 말 그대로 객체를 배열 형태로 사용하는 것이다.
기존의 배열은 int, String 등의 데이터 타입을 원소로 사용했는데, 여기서는 객체를 원소로 사용하는 것이다.
위에서 Circle이라는 클래스의 배열이 c로 되어 있는데, 객체배열의 참조변수 c가 된 것이다.
위 내용에서는 c 안에는 참조변수 5개가 만들어진 것이며, 이들은 각각의 객체를 생성할 수 있다.
for반복문을 통해서 객체를 생성하는데, 위 반복문에서는 5번을 반복하면서 5개의 객체를 만들었다.
c[0]~c[4]까지는 각각의 객체를 참조하는 참조변수의 역할이다.
두번째 for문에서는 5개의 객체에 해당하는 원의 면적을 구하는 출력문이라고 볼 수 있다.
객체 배열 선언과 생성 과정
Circle c에서 만든 5개의 객체에 각각 c의 인덱스 값들을 참조한다?
<예제>
<예제>
인자 전달
1. 기본 타입의 값 전달 : int, double 등 - 값이 복사가 되어 전달
2. 객체 혹은 배열 전달 : 복사가 되는 것이 아니라 참조하는 것이 달라짐(가리키는 것이 달라짐)
int n에 10을 넣고, 이를 increase메소트에 넘김.
이를 옆으로 넘겨서 계산하면 11이 나옴
출력하면 10
pizza객체를 increase메소드에 넘김
Circle m에 pizza객체를 받고, m이 pizza를 가리키게 됨
pizza객체에 반지름이 있다고 봤을 때, 반지름에 1을 증가시키는 식이다.
왼쪽에서 생성자를 호출할 때 반지름은 10으로 설정되었고, 이를 오른쪽에서 계산하면 11이 나오게 된다.
이때 왼쪽에서 출력을 하게 되면 10이 아니라 11이 나오게 된다.
이유는 참조하는 객체가 달라졌기 때문.
인자 전달 - 배열이 전달되는 경우
위와 마찬가지로 값이 복사가 되는 것이 아니라, 참조하는 것이 달라진다.
increase메소드를 ㅎ ㅗ출하면서 배열을 넘김
a참조변수는 array참조변수가 가리키는 곳을 바라보게 됨
오른쪽의 increase메소드에서 1씩 증가시킨 값이 되었고, 따라서 이를 왼쪽의
for문에서 출력하면 기존의 1 2 3 4 5가 아니라 1씩 증가된 2 3 4 5 6이 출력됨
<예제>
여기서 static을 넣어주는 이유는 main메소드에서 따로 객체 생성을 하지 않고 사용하기 위함이다.
따로 객체생성을 하지 않으면 다른 메소드를 가져와서 사용할 수 없는데, static을 사용하면 공유가 가능하기 때문에
main메소드에서 사용이 가능하다.
랜덤
<문제>@
<문제>
메소드 오버로딩
1은 메소드 이름이 같지만 매개변수의 갯수가 다르기 때문에 같은 메소드 이름을 사용 가능하다.
매개변수의 갯수가 같아도 그 매개변수의 타입이 다르면 오버로딩이 가능하다.
2는 매개변수의 갯수도 같고 타입도 같아서 오류
(이때, 리턴 타입은 상관 없음 - 빨간색)
오버로딩된 메소드 호출
a는 1,2,3 중에서 2를 찾아간다.(매개변수의 갯수가 3개이기 때문)
b는 3을 찾아간다.(매개변수 갯수가 2개인게 2개지만 같은 타입 double로 찾아간다.)
c는 1을 찾아간다.(b의 경우 처럼 같은 타입인 int로 찾아간다.)
가비지 컬렉션
레퍼런스(참조)가 하나도 없는 객체는 사용할 수 없기 때문에 가비지 컬렉션에서 수거하여 메모리 공간 확보 하는데, 이는 일정한 시간이 되면 jvm에 있는 가비지 컬렉터가 자동으로 가비지를 수집
참조변수 a,b와 이들을 참조하는 객체가 2개 있다.
근데 객체 생성 이후, b를 a로 치환했기 때문에 성춘향을 가진 객체와 b의 연결이 끊어져서
성춘향 객체는 가비지가 되고, 이를 가비지 컬렉션에 반납.
자바 패키지 개념
- 응용 프로그램을 프로젝트라고 볼 수 있음
<문제>
각각의 패키지에 넣는다.
새로운 객체를 만들때 class Calc를 가져올 수 있음
이 때 Calc클래스에 public을 안넣어주면 오류가 뜬다.
접근 지정자
접근 지정자에는 클래스나 멤버가 있다.
멤버에는 멤버 변수(필드)와 멤버 함수(메소드)가 있다.
- public : 접근 제한이 없음
- protected : 디폴트에 허용되는 것은 포함하면서, 자식 클래스에도 허용
* 상속했을 때 부모에 protected가 있으면, 자식이 다른 패키지에 있더라도 접근 가능
- private : 자기 클래스 안에서만 접근 가능
- 디폴트 : 자기 클래스 안에서 접근할 수 있고, 같은 패키지 안에서만 접근 가능
클래스 접근 지정
Q패키지에 클래스가 3개 P에 1개가 있다.
클래스 A에서 B객체를 생성해서 패키지 Q에서 퍼블릭 클래스로
클래스 c는 디폴트 클래스로 여기서 b클래스 접근하려고 하면 가능 - b는 퍼블릭이니까
클래스 d에서 클래스 c에 접근하려고 하면 가능 - 같은 패키지 안에 있으면, 디폴트 접근 가능
클래스 a에서 c는 안됨(다른 패키지니까)
멤버 접근 지정자 이해
public
패키지 p에 클래스 b,c가 있고, 다른 패키지에 클래스 a가 있음
b클래스는 퍼블릭이고, 그 내부의 멤버(필드)도 퍼블릭이다.
같은 패키지의 c클래스에서 b객체 생성도 문제 없고, 멤버 생성도 문제 없음 - b가퍼블릭이니까
a클래스에서도 b의 값을 할당하고, 호출하는데 문제 없음 - b가 퍼블릭이니까
private
b클래스는 퍼블릭이지만 멤버 2개는 private.
같은 패지지의 c클래스에서 b객체 생성은 문제 없지만, 멤버에 접근하는 것은 불가능하다.
private의 경우는 같은 클래스 안에서만 접근 가능하기 때문
디폴트
b클래스는 퍼블릭이고, 멤버는 디폴트
c클래스에서 b객체를 생성하고 멤버에 접근하는 것은 같은 패키지 안에 있기 때문에 문제 없음.
a클래스에서 b객체를 생성하는 것은 가능하지만, 멤버에 접근은 불가능 - 디폴트는 같은 패키지 안에서만 가능
protected
같은 패키지 c에서 b의 객체 생성과 멤버의 접근 가능하다. - 디폴트를 포함하기 때문에
다른 패키지에 있는 a클래스에서는 퍼블릭인 b객체 생성은 가능하지만, protected접근 지정자 멤버들에겐 접근x
다른 패키지의 d클래스에서는 b의 멤버에 접근이 가능한데 그 이유는 extends키워드로 b클래스를 상속받았기 때문.
따라서 부모 클래스에 있는 protected 멤버들에 접근 가능하다.
static
스태틱은 공유의 의미로 볼 수 있다.
non - static 멤버와 static 멤버의 차이
스태틱 멤버는 데이터 타입 앞에 스태틱이 붙는다.
공간적 특성
1은 객체를 생성할 때마다 객체 안에 별도의 공간이 존재한다.(객체 안에서만 존재)
2는 클래스 샘플이라는 클래스를 선언할 때 객체를 생성하기 전에 별도의 공간 안에 멤버가 들어간다.
(여기선 m, g)
따라서 객체가 생성될 때마다 이들을 공유한다.
시간적 특성
1은 객체를 생성할 때 객체 내부에 공간이 생성된다.
2는 객체를 생성하기 전에 클래스만 선언되도 별도의 공간안에 멤버가 존재한다.
공유의 특성
1은 객체 안에서만 가능
2는 객체를 생성하면 별도의 공간안에 있는 스태틱 멤버를 공유해서 사용할 수 있다.
static 멤버를 객체의 멤버로 접근하는 사례
스태틱샘플의 s1, s2는 참조변수 선언.(점만 존재)
아직 객체를 생성하기 전에 스태틱 샘플 안에 멤버가 5개 존재한다.
이 중에서 스태틱 멤버는 2개이고, 논스태틱은 3개다.
*스태틱 멤버는 m, f / 논스태틱 멤버는 n, g, h
객체를 생성하기도 전에 별도의 공간에 이 스태틱 멤버 2개가 생겨난다.
이제 s1참조변수가 가리키는 객체를 생성한다.
이 객체는 논스태틱 멤버를 가지고 있으며, 공유된 스태틱 멤버도 가지고 있어 5개의 멤버를 모두 가지고 있다.
객체의 n멤버에 접근하여 5를 할당한다.(객체 뒤의 .은 객체에 접근하는 것)
g메소드도 접근하며, 이 메소드는 논스태틱 멤버로 20의 값을 가지고 있어 m에 20을 할당하는데, m은 스태틱 멤버라서 할당하는데 무리가 없다.
다음으로 m에 50을 할당하는데, 이는 스태틱 멤버에 바로 값을 집어 넣는 것으로 20의 값을 가지고 있던 m의 값을 50으로 변경한다.
이제 s2객체를 생성한다. 이 객체 역시 논스태틱 멤버를 가지면서 스태틱 멤버를 공유하게 된다.
s2객체의 n에 8을 할당하고, h메소드를 넣는데 이 값은 30으로 m에 30을 할당한다.(논스태틱->스태틱 값 변경)
또 s2객체에 f메소드를 할당하는데 이 값은 5가 된다. 따라서 m값은 5가 된다.
이 과정 이후에 s1객체의 m 값을 출력하면 5가 나오게 된다.(스태틱은 공유하는 값이기 때문)
static 멤버를 클래스 이름으로 접근하는 사례
여기서는 시작하자마자 .을 바로 찍어서 스태틱 멤버의 m에 10을 할당한다.
스태틱 멤버이기 때문에 객체를 생성하지 않고도 값을 할당한 것.
*위는 스태틱 멤버에 스태틱샘플이라는 클래스 이름으로 접근한 것이다.
다음으로 스태틱샘플의 참조변수 s1을 선언하고, s1객체도 생성한다.
다음 s1의 m값을 출력하면 10이 나오게 된다.
다음으로 s1객체에 f메소드가 접근하고, 이를 통해서 s1의 m 값은 5로 바뀌게 된다.
다음 스태틱샘플 클래스에 f메소드를 접근하면, 이미 5로 바뀐 것에 또 5를 넣은 것으로 같은 값이다.
static 활용
클래스 앞에 final이 붙어 있는데 이는 상속할 수 없다는 뜻으로 객체를 생성하려고 하면 오류가 난다.
이런 경우에는 2의 경우처럼 이 클래스의 스태틱 멤버에 접근하여 사용하면 된다.
<예제>
static 메소드의 제약 조건
static / non-static 오류가 난 이유
s1, s2는 스태틱 메소드다. 스태틱은 클래스를 선언할 때 별도의 공간이 생성이 된다고 했었다. 이들에게는 매개변수 x가 있다.
먼저 s1메소드를 살펴보면 이 x를 n에다가 넣었다. 이 n은 non-static 멤버변수다. 논스태틱은 객체가 생성될 때 그 객체 안에 자기의 공간이 생기게 된다. 여기서 오류가 나는 이유는 스태틱과 논스태틱이 만들어지는 시점이 다르기 때문이다. 즉, 아직 논스태틱은 만들어지지도 않았는데, 스태틱의 값을 넣으려고 해서 문제가 발생하는 것이다.
s2에서는 논스태틱 메소드 f1에 3을 넣으려고 하는데 이 역시 시점이 다르기 때문에 오류가 발생한다. 아직 클래스 밖에 선언되지 않아서 객체가 만들어지지 않았고, 이에 따라 논스태틱 멤버는 현재까지 없다.
위에서 오류가 나지 않은 이유는 처음건 같은 논스태틱이라 시점 차이가 없고, 다음건 이미 만들어진 논스태틱에 스태틱을 넣는 것이기 때문이다
아래의 2개 역시 같은 스태틱으로 시점이 같을 때 만들어지기 때문에 오류가 없다.
this 오류 이유
this는 객체가 생성될 때 만들어지는데, 스태틱 메소드는 이와 만들어지는 시점이 다르다. 오류1은 n이 논스태틱에다가 this라서 오류다.
오류2는 this 때문에 오류가 발생(시점차이). this객체가 만들어지기도 전에 스태틱 메소드에 this 객체로 접근했기 때문에 오류가 발생했다는 뜻.
final
클래스 오류
final클래스는 상속이 불가능한데, extends는 상속시키는 것이라서 오류
메서드 오류
부모와 자식 클래스인 슈퍼와 서브가 있다. 여기서 오류는 오버라이딩 과정에서 생긴 문제로, final이 붙으면 오버라이딩 불가능하다
마지막
final이 붙은 정수의 값을 변경하려다가 오류 발생 - 상수는 값 변경 못함
<예제>
'학원 > JAVA - 학원' 카테고리의 다른 글
(상속) 추상 클래스 / 추상 메소드 / 인터페이스 (0) | 2022.02.16 |
---|---|
상속 (0) | 2022.02.11 |
예외 처리(Exception) (0) | 2022.02.04 |
배열 (0) | 2022.02.01 |
반복문(loop), 분기문 (0) | 2022.01.24 |