자바 기본 개념 정리
혹시 잘못 알고있거나, 틀린 개념이있다면 언제나 리뷰해 주세요~~!!
1. 클래스, 객체, 인스턴스
1-1. 클래스 란?
- 객체를 만들어 내기 위한 설계도로서, 변수와 메서드의 집합이다.
1-2. 객체 란?
소프트웨어 세계에서 구현할 대상으로서, 클래스에서 선언된 설계도의 모양대로 생성된 실체
클래스의 인스턴스 라고도 부른다.
1-3. 인스턴스 란?
- 설계도를 바탕으로 소프트웨어 세계에 수현된 구체적 실체
- 객체를 실체화 시키면 인스턴스라고 부르며, 실체화 된 인스턴스는 메모리에 할당 된다.
객체 > 인스턴스 → 인스턴스는 객체에 포하된다고 생각 하면 된다.
opp에서 객체가 메모리에 할당되어 사용될 때를 ‘인스턴스’라고 부른다.
//클래스
public class Animal{
...
}
//객체의 인스턴스
public class Main{
public static void main(String[] args){
Animal cat, dog; //객체
//인스턴스화
cat = new Animal();
dog = new Animal();
//cat 과 dog 는 Animal 클래스의 인스턴스 (객체를 메모리에 할당)
클래스 vs 객체
클래스는 ‘설계도’ / 객체는 ‘설계도로 구현한 모든 대상’
객체 vs 인스턴스
객체는 ‘실체’ / 인스턴스는 ‘관계’ 에 초점을 맞추고 객체를 클래스의 인스턴스라고 부른다.
2. 클래스의 3요소 또는 객체 모델링이라고도 부른다 (필드, 생성자, 메소드)
객체는 속성과 동작으로 나뉘어 진다.
객체에서 속성 → 필드
동작 → 메소드 라고한다.
사람이라는 객체에서 이름, 나이 라는 속성 이 필드가 되고, 먹다 자다 라는 동작이 메소드가 된다.
public class Person {
// 필드
private String name;
private int age;
// 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 메소드
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
// 인스턴스 생성
Person person = new Person("Alice", 25);
// 필드 접근
String name = person.getName();
int age = person.getAge();
2-1. 필드
- 필드는 클래스, 또는 인스턴스의 데이터를 나타내고 ‘클래스의 멤버 변수라고 한다’
- 필드는 객체의 데이터가 저장되는 곳으로 각각의 필드는 이름과,데이터 타입을 가지고 있다.
- 필드 선언 → 변수를 선언하는 방법과 동일
- 초기값을 제공하지 않으면 기본값 초기화
- 필드 사용 → 필드값을 읽고 변경한다는 것
2-2 생성자
- 객체를 초기화하는 특별한 종류의 메소드, 생성자는 class 이름과 동일하며 객체를 만들 때 호출되며, 객체를 초기화 하는대 사용된다.
- 생성자는 일반적으로 ‘public’ 접근 제어자를 가지며 반환 타입이 없다.
- 위에서 Person 클래스에서 name과 age 필드를 초기화 하는 생성자를 정의할 수 있다.
- 클래스를 선언할때 생성자가 선언되지 않으면 컴파일러는 기본 생성자를 바이트코드 파일에 자동으로 추가 시킨다.
- 객체 초기화 → 필드 초기화 후 메소드를 호출하여 객체를 사용할 준비를 하는것.
2-3 메소드
- 메소드는 객체가 수행할 동작으로서, 다른 언어에서는 함수라고 불리지만, 객체 내부의 함수는 메소드라고 불린다.
- 메소드는 객체의 동작을 정의하고, 객체의 상태를 변경하고, 객체간의 상호작용을 하기 위해 호출된다.
- 메소드 선언 → 객체의 동작을 실행 블록으로 정의 하는것
- 메소드 호출 → 실행블록을 실제로 실행 하는것
번외)
- 필드와 변수의 차이
구분 | 필드 | 변수 |
---|---|---|
선언 위치 | 클래스 선언 블록 | 생성자, 메소드 선언 블록 |
존재 위치 | 객체 내부 | 생성자, 메소드 호출 시에만 |
사용 위치 | 객체 내,외부 어디든 | 생성자, 메소드 블록 내부에서만 사용 |
- 필드, 생성자, 메소드
필드 : 객체의 데이터를 저장하는 곳
생성자 : 객체를 생성할 때 객체의 초기화 역할, 선언 형태의 경우 메소드와 비슷하지만 리턴 타입이 없고 이름은 클래스와 동일하다.
메소드 : 객체가 수행하는 동작, 객체 내부의 함수를 메소드라고 부르며 객체간의 상호작용을 위해 호출된다.
3. 오버로딩
궁극적으로 오버로딩(Overloading)이란?
→ 메소드의 이름은 같지만, 매개 변수의 수, 타입, 순서를 다르게 여러개 정의하는것.
why? 오버로딩을 하는지?
→ 다양한 매개 변수 조합에 대해 하나의 메소드 이름을 사용할 수 있기때문에 사용한다.
3-1. 생성자 오버로딩
- 생성자 인데 매개변수의 타입, 개수, 순서를 다르게 여러개 선언 하는것 → 매개값으로 객체의 필드를 다양하게 초기화 하기 위해서
3-2. 메소드 오버로딩
- 메소드의 이름은 같되 매개변수의 타입 갯수 순서를 다르게 선언 하는것 → 다양한 매개값을 처리하기 위하여
(Example)
대표적을 System.out.print() 메소드가 대표적으로 오버로딩 된 메소드 중 하나,
4. 인스턴스 멤버 vs 정적 멤버
→ 정적 멤버 > 인스턴스 멤버의 느낌.
→ 인스턴스 멤버 = 인스턴스 필드 + 인스턴스 메소드
→ 정적 멤버 = 정적 필드 + 정적 메소드
- 소유 객체가 다르다.
- 인스턴스 멤버는 객체에 소속된 멤버 → 객체를 생성해야만 사용가능.
- 정적 멤버는 클래스에 소속되어 있다 → 객체 없이도 사용 가능.
- 메모리에 할당되는 시기가 다르다.
- 인스턴스 멤버는 객체 생성시에 메모리에 할당.
- 정적 멤버는 클래스가 로딩될 때 메모리에 할당.
- 접근 방법이 다르다
- 인스턴스 멤버는 객체를 통해서만 접근 가능.
- 정적 멤버는 클래스 이름으로 직접 접근 가능.
- 생명 주기가 다르다.
- 인스턴스 멤버는 객체가 생성되고 소멸될 때까지 유지.
- 정적 멤버는 클래스가 로딩되고 언로딩될 때까지 유지.
- 멤버 변수의 초기값이 다르다.
- 인스턴스 멤버는 변수가 초기화 되지 않은면 기본값으로 초기화.
- 정적 멤버는 변수가 초기화 되지 않으면 0 or null값.
- 상속에서의 차이
- 인스턴스 멤버는 상속되는 경우 자식 클래스에도 인스턴스 멤버로 유지.
- 정적 멤버는 상속시 자식클래스에서도 정적 멤버로 유지.
주로 인스턴스 멤버는 객체마다 다른 값과, 다른 동작을 할때 사용, 정적 멤버는 모든 객체에서 공유해야 할 값을 저장하거나 모든 객체에서 공통적으로 사용되는 메서드를 작성할 때 사용 static 키워드 이용
public class Calculator{
String color; //인스턴스 필드
void setColor(String color) { this.color = color;} //인스턴스 메소드
/* 인스턴스 멤버를 사용하기위해선 객체가 있어야 한. */
static int plus(int x ,int y){return x+y;}//정적 메소드
static int minus(int x, int y){return x-y;} //정적 메소드
}
//오류
public class Car{
int speed;
void run(){...}
public static void main(String[] args) {
speed = 60;
run();
}
} //컴파일에러
//올바른 사용법
public static void main(Stringp[] args){
//객체를 생성한다.
Car mycar = new Car();
mycar.speed = 60;
mycar.run();
}
5. final 필드와 상수
- 인스턴스 멤버와, 정적 멤버는 언제든지 값을 변경할 수 있다.
→ 그러나 값을 변경하는것을 막고 읽기만 허용해야할 때가 있다. 이떄 final 필드와 상수를 선언하여 사용한다.
(사용 방법)
- 필드 선언시에 초기값에 대입을 하고 final 키워드사용.
- 생성자에서 초기값을 대입하고 fianl 키워드 사용.
6. 접근 제한자
- 자바에서 접근제한자는 public, protected, private 3가지존재
접근 제한자 | 제한 대상 | 제한 범위 |
---|---|---|
public | 클래스, 필드, 생성자, 메소드 | 없음 |
protected | 필드, 생성자, 메소드 | 같은 패키지 이거나, 자식 객체만 사용 가능 |
(default) | 클래스, 필드, 생성자, 메소드( 이는 default값 이므로 아무것도 붙지않은 상태) | 같은 패키지 |
private | , 생성자, 메소드 | 같은 클래스 내부 |
7. Getter, Setter
- 객체의 필드를 외부에서 마음대로 읽고 변경할 경우 객체의 무결성이 깨질수도 있다. 따라서 이떄 Getter와 Setter를 사용한다.
Getter → 어떤 메소드에서 값을 가지고 오는 것.
Setter → 어떤 메소드가 값을 변경하는 것.
(example)
public class Car{
private int myCarPrice;
// getter 값을 가지고 온다.
public int getMyCarPrice(){
//만약 내차가 10대있으면 1대가격만 구해서 10가져오기
return myCarPrice * 10;
}
// Setter 값을 수정해 준다.
public void setMyCarPrice(int price){
//가격은 음수일수 없다 음수이면 0 return
if(price<0){
this.myCarPrice = 0;
return;
}else{
this.myCarPrice = price;
}
}
}
Car myCar = new Car();
myCar.setMyCarPrice(10_000); // setter를 통해 한대당 가격이 10_000
int totlaPrice = myCar.getMyCarPrice();
// getter를 통해 10대가격 가져오고 그거를 totalprice에 저장
8. 오버라이딩(Overriding)
- 오버라이딩은 상위 클래스에서 정의된 메소드를 하위 클래스에 재정의 하는 것을 말한다. 즉, 상위 클래스에서 정의된 메소드를 하위 클래스에 덮어씌우는것
- 오버라이딩을 하게 되면 상위 클래스에서 정의한 메소드 대신 하위 클래스에서 정의한 메소드가 호출된다. 이때 하위 클래스에서 재정의한 메소드는 상위 클래스의 메소드와 동일한 이름, 매개변수 타입, 반환 타입을 가져야 한다. 또한 하위 클래스에서 재정의한 메소드는 상위 클래스에서 정의된 메소드와 같은 접근 제어자나 더 높은 접근 제어자를 가져야 한다.
→ 더 높은 접근 제어자 → 가장 높은 접근 제어자 pulbic
9. 오버 로딩과 오버라이딩 공통점
- 둘 다 메소드 이름이 같은 경우를 다루며, 다형성 구현 방법 중 하나이며, 객체 지향 프로그래밍의 중요한 개념 이다.
10. 객체지향 프로그래밍의 4가지 특징
- 캡슐화, 상속, 다형성, 추상화
10-1 캡슐화 (Encapsulation)
- 객체의 데이터와 메서드를 하나로 묶어서 외부에서의 접근을 제한하고, 객체 내부의 상태를 보호하기위함. 이는 객체 내부 구현을 외부로부터 숨기고 객체 간의 상호작용을 안전하게 유지하는 데 도움을 준다.
10-2 상속 (Inheritance)
- 이미 존재하는 클래스를 기반으로 새로운 클래스를 작성할 수 있다. 이를 통해 코드의 재사용성을 높이고, 유지보수성을 용이하게 할 수 있다.
10-3 다형성(Polymorphism)
- 서로 다른 객체가 같은 동작을 명령 받았을 때 각자의 특성에 맞는 방식으로 동작하는것. 다형성은 코드의 재사용성과 확장성을 높여주고 객체지향 패러다임의 핵심이기도 하다.
- OPP에서는 오버라이딩과 오버로딩 메서드가 같은 이름으로 존재할 수 있다는 것을 말하기도 하는데, 오버라이딩(overriding)은 같은 이름의 메서드가 여러개의 클래스에서 다른 기능을 수행하는 것, 오버로딩(overloading)은 메서드의 이름은 같지만 다른 매개변수들로 다른 기능을 수행하는 것.
10-4 추상화(Abstraction)
- 객체의 복잡한 내부 구조를 숨기고, 필요한 부분만을 간추려서 표현하는 것을 말한다. 추상화는 객체를 단순화시키고, 객체 간의 관계를 명확하게 해준다.
11. 객체지향 프로그래밍의 5가지 원칙
- SRP (Single Responsibility Principle) : 단일 책임 원칙
- OCP (Open-Closed Principle) : 개방 폐쇄 원칙
- LSP (Liskov Substitution Principle) : 리스코프 치환 원칙
- ISP (Interface Segragation Principle) : 인터페이스 분리 원칙
- DIP (Dependencty Inversion Principle) : 의존성 역전의 원칙
11-1 SRP 단일 책임 원칙 (Single Responsibility Principle)
- 클래스는 단일 책임을 가져야 하며, 클래스를 변경할 이유는 그 책임 때문이어야 한다는 원칙
- 이는 클래스 변경 시 생기는 사이드 이펙트를 제거함으로써 유지보수성을 높이기 위한 것 이다. 따라서 각 클래스와 모듈은 단일 작업에 중점을 두어야 하며, 같은 클래스안에 다른 이유때문에 변경될 메서드를 넣어선 안된다.
11-2 OCP 개방 폐쇄 원칙 (Open-Closed Principle)
- 소프트웨어 요소(클래스, 모듈, 함수등)은 확장에 열려있어야 하고, 변경에는 닫혀 있어야 한다는 원칙
→ 어떤 클래스를 수정할 때 그 클래스를 이용하는 코드들을 고쳐야 한다면 유지보수성이 떨어지게 된다. 따라서 OCP원칙에 따라 추상화와 다형성 등을 이용해 기존 코드를 수정하지 않고 기능을 확장할 수 있어야 한다.
11-3 LSP 리스코프 치환 원칙 (Liskov Substitution Principle)
- 자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다는 원칙
→ 즉 OPP의 4가지 특징중 상속관계가 성립해야 한다는 것
11-4 ISP 인터페이스 분리 원칙 (Interface Segregation Principle)
- 몇 개의 큰 인터페이스가 있는 편 보다, 작은 인터페이스가 많은 편이 더 바람직 하다.
11-5 DIP 의존성 역전의 원칙 (Dependency Inversion Principle)
- 추상화된 것은 구체적인 것에 의존하면 안 된다는 원칙. 구체적인 것이 추상화된 것에 의존해야 한다. → 고수준의 모듈은 저수준의 모듈 구현에 의존하면 안되고, 구체적인 클래스 보다 추상적인 클래스에 의존해야 한다.
→ 구체적인 것에 의존하게 된다면 유연성이 떨어지기 때문이다. 즉 추상화 특성을 지키면서 저수준의 모듈이 변경 되어도 고수준의 모듈은 변경될 필요가 없어야 한다.
12 얕은 복사 vs 깊은 복사
12-1 얕은 복사 (Shallow Copy)
- “주소 값”을 복사한다는 의미 따라서 실제 값은 동일하다.
- 주소에 의한 참조 즉 Call-by-reference와 비슷한 개념
12-2 깊은 복사 (Deep Copy)
- “실제 값” 을 새로운 메모리 공간에 복사하는 것을 의미한다.
- 복사하려는 원본 객체에 대해 새로운 객체를 만들어 모두 복사하여 원본과 독립적인 객체를 만드는 것, 즉 새로운 객체가 원본 객체 자체를 Copy 하는 것 Call-by-values와 비슷한 개념
얕은 복사 | 깊은 복사 | |
---|---|---|
장점 | 빠르고 간결하다. | 객체 자체를 복사하기 때문에 독립된 새로운 객체로 다형성을 부여하거나 재정의 할 수 있다. |
단점 | 원본 객체가 수정된다면 복사 객체 역시도 동일하게 변동이 일어난다. | 모든 인스턴스 값을 가져오므로 얕은 복사에 비해 메모리가 많이들고, 느리다 |
13. 자바 메모리 영역
- 자바에서는 크게 5개의 JVM메모리 영역을 사용한다.
13-1 메서드(Method) 영역
- 바이트 코드 파일을 읽은 내용이 저장되는 영역.
- 클래스 파일의 상수, 정적 필드, 메서드 코드, 생성자 코드 등이 저장된다.
13-2 힙(Heap) 영역
- 객체와 배열이 저장되는 동적 메모리 영역.
- 모든 객체와 배열은 힙 영역에 생성되며, JVM에서 자동으로 메모리를 할당하고 해제한다.
13-3 스택(Stack)영역
- 각 스레드마다 하나씩 존재하는 영역, 지역 변수, 매개변수, 리턴 값, 연산 시 일시적으로 사용되는 임시 값 등이 저장된다.
- 메서드의 실행이 끝나면 스택 프레임이 제거 된다.
13-4 PC 레지스터(Program Counter Register)
- 스레드마다 하나씩 존재하는 영역으로, 현재 실행 중인 JVM 명령어의 주소를 가지고 있다.
13-5 네이티브 메서드 스택 (Native Method Stack)
- 자바 외부에서 작성된 네이티브 코드(C, C++, 어셈블리 등)을 실행하는 데 사용되는 스택 영역
→ 각 영역들은 JVM에서 자동으로 관리하며 개발자는 메서드 영역과 힙 영역에 직접적으로 접근하지 않고, 객체 생성과 호출을 통해 자동으로 메모리를 할당하고 관리하도록 해준다.
(참고) 각 스레드 마다란?
→ 각 스레드마다는 독립적인 실행 흐름을 가지고 있다. 이 실행 흐름에는 필요한 메모리 공간을 가지고 있다. 스레드는 프로그램 내에서 동시에 여러 작업을 수행할 수 있도록 하는 것 이며, 이를 가능하게 하는 것이 바로 스레드 스케줄러 이다.
스레드 스케줄러는 스레드가 실행, 종료 시점을 결정하며 이를 위해 각 스레드에게 일정 시간 동안 CPU를 할당한다. 이 때, 각 스레드 마다 자신만의 실행 흐름과 메모리 공간을 가지고 있기 때문에 다른 스레드의 영향을 받지 않고 독립적으로 작동할 수 있다.
==
자바에서는 각 스레드 마다 스택(stack) 메모리와 PC(Program Counter)레지스터를 할당 한다. 스택 메모리는 각 스레드마다 독립적으로 할당되며, 메서드 호출 시 지역 변수와 매개 변수를 저장하는 데 사용된다. PC 레지스터는 현재 실행 중인 스레드가 다음에 실행할 명령어의 주소를 가지고 있다. 따라서 각 스레드는 자신만의 실행 흐름과 메모리 영역을 가지고 독립적인 실행 흐름을 갖는다.
'JAVA > 이것이 자바다' 카테고리의 다른 글
[Chapter 06] 클래스 (0) | 2022.12.31 |
---|---|
[Chapter 05] 참조 타입 (0) | 2022.12.31 |
[Chapter 04] 조건문과 반복문 (0) | 2022.12.03 |
[Chapter 03] 연산자 (0) | 2022.12.03 |
[Chapter 02] 변수와 타입 (0) | 2022.12.03 |
댓글