클래스와 인스턴스
1. 클래스란 무엇인가?
- 자바의 최소 단위, 클래스는 상태와 행동을 가짐
- 상태와 행동이란 무엇인가?
- 자바에서 상태는 속성들의 집합, 행동은 메서드로 정의할 수 있음
- 변수는 그 자체로 상태라기보다는 하나의 속성!
- 속성이 메서드에서 어떤 행동들을 하게 되고 -> 그러면 어떤 상태라고 정의할 수 있다.
- 상태와 행동이란 무엇인가?
2. 인스턴스란 무엇인가?
- 클래스는 인스턴스(객체)를 생성하기 위한 틀.
- 클래스 자체로는 어떤 작업을 할 수 없음. 인스턴스 생성해서, 인스턴스를 통해 작업을 수행하는 것
- 즉, 인스턴스가 메모리(heap) 영역에 올라가서 실제로 작업이 되는 것.
public class Person {
// 필드(속성)
private String name;
private int age;
// 생성자(Constructor)
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 메소드(Method)
public void introduce() {
System.out.println("My name is " + name + " and I am " + age + " years old.");
}
public static void main(String[] args) {
//Person 객체 생성
Person yujeong = new Person("yujeong", 25);
// yujeong 객체의 메소드 호출
yujeong.introduce(); // 출력: My name is yujeong and I am 25 years old.
}
}
yujeong이라는 객체를 통해 클래스에 있는 메소드들과 속성들로 작업수행이 가능하다~~
변수
3. 참조 자료형과 기본 자료형은 무엇이 다른가?
- 기본 자료형 8가지(byte, short, int, long, float, double, char) 제외하고 모두 참조자료형
- 참조자료형은 인스턴스임
- 즉, 기본자료형은 그냥 Java에서 제공하는 자료, 참조자료형은 클래스 기반의 인스턴스
- 인스턴스(객체)는 상태와 행동으로 구성됨, 그니까 참조자료형을 통해서 더 많은 행동을 할 수가 있음
- ex) int와 Integer
- Integer를 통해 더 편의성 있는 작업이 가능
- 메모리 영역을 이해 해야함, Stack과 Heap 영역
- Heap - 런 타임에 크기가 결정되며, 사용자가 동적 할당을 함 -> new 키워드를 통해 객체를 생성하면 heap 영역에 올라감
- 인스턴스 변수들은 heap 영역에 저장 -> 객체의 생명주기와 함께하기 때문!
- 힙 영역은 가비지 컬렉터의 대
- Stack - 컴파일에 크기가 결정되며, 정적 할당
- 함수 호출하면, 그 함수만을 위한 메모리 공간이 할당됨 -> stack 이 영역에서 사용되는 변수를 지역변수라고 함
4. static 키워드
- 프로그램 시작할 때 메모리에 올라가고, 프로그램이 끝나야 해제됨
- 데이터 영역에 올라감 (정적 변수) -> 가비지 컬렉터의 대상이 아님
- 남용하면 프로그램에 악영향을 끼칠 수 있다.
- 객체를 생성하지 않아도 접근이 가능
- 객체는 new 키워드를 통해 heap에 할당이 되는건데, static은 이미 프로그램이 시작될 때부터 메모리에 올라가 있음 -> 즉 객체 생성하지 않아도 사용할 수 있음
- ex) Integer.valueOf() - Integer 클래스의 static 메소드
int value = 42;
Integer integerValue = Integer.valueOf(value);
Integer 클래스의 인스턴스 생성 안 해도, 호출이 가능함.
-> 이처럼, 태초부터 뭔가 없는데(Integer) Integer를 만들어야 함... 이런 경우에 static 메소드를 씀
public class Main {
public static void main(String[] args) {
// 생성자를 사용하여 Integer 객체를 생성
Integer integerValue = new Integer(42);
// valueOf 메서드를 호출하여 Integer 객체를 생성
Integer valueOfInteger = Integer.valueOf(42);
// 두 객체를 비교하여 동일성 확인
System.out.println("integerValue == valueOfInteger: " + (integerValue == valueOfInteger));
}
}
5. 다형성
- 하나의 객체가 다양한 타입을 가질 수 있음!
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
public void wagTail() {
System.out.println("Dog wags tail");
}
}
public class Main {
public static void main(String[] args) {
// 업 캐스팅
Animal animal = new Dog(); // Dog 객체를 Animal 타입으로 업 캐스팅
// 다형성을 이용하여 부모 클래스의 메서드 호출
animal.sound(); // 출력: Dog barks
// 다운 캐스팅
Dog dog = (Dog) animal; // Animal 타입을 다시 Dog 타입으로 다운 캐스팅
// 다운 캐스팅을 통해 자식 클래스의 메서드 호출
dog.wagTail(); // 출력: Dog wags tail
}
}
이처럼 타입이 Animal 부모 타입으로 선언돼도, 실제 수행되는건 new Dog(); 객체의 메소드!
Parent parent = new Child(); - 가능
Child child = new Parent(); - 불가능
--> 자식 클래스는, 부모 클래스의 모든 속성과 메소드를 사용할 수 있지만,(자식한테 상속해주는거다~~)
부모클래스는 자식클래스의 모든 메소드 사용 불가!
6. 오버로딩과 오버라이딩
- 오버로딩은 메소드의 이름만 같고, 타입, 매개변수 등이 달라도 됨
- 오버라이딩은 모든 시그니처가 같아야 하고, 구현만 다르게 하는 것
7. 추상클래스와 인터페이스
- 인터페이스는 선언만, 추상클래스는 구현된 메소드가 있어도 됨
- 추상 클래스는 클래스들 간에 구현이 같은 공통된 동작이 확실하게 있을 때
- 인터페이스는 클래스들 간에 공유할 동작이 있지만, 구현은 다르거나, 확실치 하고 명시적으로 선언만 할
- 인터페이스 implements로 받음, 즉 인터페이스에 선언된 모든 메소드를 '구현' 해야 함! -> 오버라이딩
객체지향에서 최우선으로 고려해야할 건, 어쨌든 객체의 내부 구현을 외부에 너무 노출시키면 안됨.
너무 많은 관계를 갖지 않는 것. 최대한 캡슐화 하고, 은닉화 해야 함
느슨한 관계를 가질수록 결합이 줄고 -> 확장성이 높아지는 것!
'JAVA' 카테고리의 다른 글
[이펙티브 자바] 객체 생성과 파괴 (0) | 2024.07.13 |
---|---|
싱글톤 패턴과 프록시 패턴 (1) | 2024.05.01 |
IoC, DI, AOP 와 Spring (1) | 2024.05.01 |
자바의 제네릭(Generic) (0) | 2024.04.08 |