[Java-25] 클래스 & 내부클래스 & 익명클래스

Java Class
🐵 Java 클래스
🙈 클래스?
어떤 객체지향 언어에서든지, 클래스라는 개념을 한번쯤은 들어봤을 것이다. 먼저 간단한 코드를 분석해보자,
- 자바에서 클래스를 선언
public class App {
}정말 쉽다, 이런식으로 public + class + name 다음과 같이 만들면 클래스 하나가 생성된 거다.
이제 클래스를 직접 만들어보면 애완동물 클래스인 Pet을 만들고, 여기에 변수도 넣어보자
public class Pet {
String kind; // 펫의 종류
String name; // 펫 이름
Integer age; // 펫 나이
}이렇게 만들어 놓은 클래스는 우리가 마음대로 찍어낼 수 있다, 내가 강아지를 키우고 있다면 클래스를 변수로 선언하여, 클래스에다가 마음대로 집어넣을 수 있다. 마치 C의 구조체와 같이 말이다.
public static void main(String[] args) {
Pet pet = new Pet();
pet.age = 10;
pet.kind = "dog";
pet.name = "복실이";
System.out.println(pet.toString());
}
toString : 객체가 가진 정보를 String 으로 만들어 주는 함수 @Overriding 해야함
이 Pet 클래스를 선언함으로 써, 유저가 원하는 다양한 객체를 클래스를 통해서 선언이 가능해진다.
우리는 이 과정을 인스턴스 화 라고 한다.결과 콘솔
> Pet{kind='dog', name='복실이', age=-10}
🙉 이런 클래스를 가진 OOP 의 특징이 있다.
무결성, 은닉성, 캡슐화
- 이들의 특징과 장점은 나중에 알아보도록 하고, 이런게 있구나하고 넘어가도록 하자, Getter를 왜 사용하는지
- Setter를 왜 사용하는지, 그리고 class안에 method를 정의하면서 어떻게 활용이 가능한지 알 수 있다.
🙉 객체 생성부터 변수 생성까지

Class 는 이미 생성된 상황에서, 원하는 클래스에 Data 를 타입에 맞게 넣어놓고 객체를 생성할 수 있다. 책에서는 이 과정을 인스턴스 화 한다고 얘기한다.
이렇게 저장된 데이터는 JVM 메모리 영역의 Heap 에 올라가게 된다.
🐵 내부 클래스 (Inner Class)
🙈 내부 클래스?
내부 클래스는 말 그대로 클래스 안에 클래스가 있다는 소리다. 한가지 예를 들어보자
Java 로 구현한 Stack 코드 using Node
public class ListNodeStack { // 일반적인 클래스, 외부 클래스
Node topNode; // 내부클래스 Node 객체를 생성
@Getter
class Node{ // 내부 클래스
int data;
Node next;
public Node (int data){
this.data = data;
}
}
}ListNodeStack 이라는 클래스 안에서, Stack 을 구현하기 위한 Node를 내부 클래스로 선언을 했다. 즉, 내부클래스는 일반적으로, 상위 클래스와 밀접환 연관이 있을 때 사용한다.
캡슐화
public class Computer{
Cpu cpu;
Memmory memory;
class Cpu{
String company;
Integer price;
String model;
Double hz;
}
class Memory{
String company;
Integer memorySize;
String model;
}
...
}- 이렇게 서로 연관되어있는 클래스를 이너클래스로 구현하여, 캡슐화의 근간이 된다.
🐵 익명 클래스
public class Pet{
String name = "돼지";
public String getName(){
return name;
}
}
public static main(String args[]){
Pet pet = new Pet(); // 인스턴스 선언
}
🙈 익명 클래스
- 이번에는 익명클래스에 대해서 알아보는 시간을 가져보도록 하자
- 익멸 클래스는 이름이 지정되어 있지 않은 클래스를 의미한다.
정확히 익명클래스를 선언하는 방법에는 2가지가 있다.
🙉 익명클래스를 사용하는 방법
1. Interface를 implemets 를 받아 사용한다.
2. Class를 상속 받아서 사용한다.
1. 인터페이스 implements 사용법
public interface Monster{
String getName();
}
public static void main(String args[]){
Monster monster = new Monster(){
String name;
public String getName(){
return name;
}
};
System.out.println(monster.getName());
}
이 형식 어디서 많이 보지 않았는가? 만약 쓰레드를 공부했다면 Runnable 과 같은 형태라는 걸 눈치채챌 수 있다. 나중에 설명하겠지만 Runnable, Thread 선언 하는 이 두가지 방법도 비슷한 방식이라고 생각 하면된다. Thread는 조만간 다뤄보도록 하자 : D
2.익명 클래스 상속 사용법
public class Pet{
String name = "돼지";
public String getName(){
return name;
}
}
public static void main(String[] args){
Pet pet = new Pet(){
String name = "익명 돼지";
@Override
public String getName(){
return name;
}
};
System.out.println(pet.getName()); // 결과 : 익명 돼지
}
이렇게 클래스를 직접 상속 받아서, getName() 을 오버라이딩 해서 사용하는 방법이 있다. 그러면 이런 생각을 할 수 있다. "야 지금 이거 상속이고 뭐고, 그냥 pet 클래스 아니야?" 일단 이 질문에는 아니다. 언뜻보면, 그냥 Pet 클래스를 선언에서 오버라이드 좀 한걸로 볼 수 있지만 그렇지 않다.
🙉 Pet 익명클래스는 Pet 클래스가 아니다. 간단한 확인
🙈 생성된 인스턴스의 클래스 이름 확인 'instance.getClass().getName'
public static void main(String[] args) {
Pet pet = new Pet();
Pet pet2 = new Pet();
System.out.println(pet.getClass().getName()); // 결과 Pet
System.out.println(pet2.getClass().getName()); // 결과 Pet
}
- 이 클래스들 pet 과 pet2는 일반적인 방법으로 객체를 생성한 것이다. 그럼 이 클래스의 이름은 뭐라고 뜰까?
🙈 생성된 인스턴스의 클래스 이름 확인 'instance.getClass().getName'
public static void main(String[] args) {
Pet pet = new Pet(){ //익명 클래스 1개 선언
//@Override
};
Pet pet2 = new Pet(){ //익명 클래스 2개 선언
//@Override
};
System.out.println(pet.getClass().getName()); // 결과 Pet$1
System.out.println(pet2.getClass().getName()); // 결과 Pet$2
}
결과 값이 신기하지 않은가? Pet + $ + n(생성된 몇번 째) 이런식의 클래스 이름이 나온다. 그러니깐 결론은, 자바에서는 이 서로 두개의 클래스를 같은 클래스로 보고 있지 않다는 것이다.
🙈 인터페이스로 선언된 익명 클래스는 현재 main에 속해있는 클래스 이름을 반환
public interface Monster {
String getName();
}
public static void main(String[] args) {
Monster mon = new Monster(){ //익명 클래스 1개 선언
//@Override
};
Moster mon2 = new Moster(){ //익명 클래스 2개 선언
//@Override
};
System.out.println(mon.getClass().getName()); // 결과 Pet$1
System.out.println(mon2.getClass().getName()); // 결과 Pet$2
}
현재 클래스로 구현되어있기 때문에 지금 속해있는 main 클래스의 클래스 명을 반환한다.