ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java-25] 클래스 & 내부클래스 & 익명클래스
    Java 2020. 12. 9. 12:02

    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를 정의하면서 어떻게 활용이 가능한지 알 수 있다.

    🙉 객체 생성부터 변수 생성까지


    IMG_32A7E147AB41-1

    • 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 클래스의 클래스 명을 반환한다.

    댓글

Designed by Tistory.