Programming/JAVA

클래스란?

잇나우 2021. 1. 4. 17:40
반응형

객체지향 프로그래밍

클래스에 대해 알기전에 먼저 객체지향 프로그래밍에 대해 알아보자.

객체지향 프로그래밍(OOP : Object-oriented programming) 은 모든것을 객체(Object) 로 보고 그 객체들끼리 역할, 책임, 협력 등 객체들의 관계를 중심으로 프로그래밍하는 기법을 말한다.

객체지향의 4대 특성

  • 캡슐화(encapsulattion)
    객체의 속성과 행위를 하나로 묶고 구현 내용 일부를 외부에 감추어 은닉할 수 있다.
  • 상속(inheritance)
    상위 클래스의 속성과 행위를 상속 받을 수 있다. 하위 클래스는 필요한 특성을 추가하여 사용할 수 있다.
  • 추상화(abstraction)
    상세한 정보는 무시하고 필요성에 의해 있어야할 정보들만 간추려서 구성하는 것으로 공통점 추출하는 것이다.
  • 다형성(polymorphism)
    같은 타입이지만 실행 결과가 다양한 객체를 대입할 수 있는 성질을 말한다.

클래스

클래스는 객체지향 프로그래밍에서 객체를 생성하기 위한 일종의 설계도와 같다. 보통 붕어빵 비유를 많이 드는데 붕어빵을 만드는 붕어빵 틀은 클래스라고 하고 만들어진 붕어빵은 객체라고 볼 수 있다.
클래스는 객체의 상태와 행위가 정의되어 있는 일종의 설계도이기 때문에 비슷한 구조를 갖지만 상태는 다른 서로 다른 많은 객체를 만들 수 있다.

클래스의 구조

  • 필드(field)
    필드란 클래스에 포함된 변수를 의미한다. 객체의 상태(state) 속성을 나타내며, 멤버변수라고도 한다.

    • 인스턴스 변수 (instance variable)

        인스턴스가 갖는 변수, 인스턴스가 생성될 때 생성된다. 서로 독립적인 값을 갖고있어 heap영역에 할당되고 `GC`에 의해 관리된다.
    • 클래스 변수 (static variable)
      static키워드가 인스턴스 변수앞에 붙여진 변수를 말한다. 해당 클래스에서 파생된 인스턴스는 클래스 변수를 공유한다. 인스턴스가 생성되지 않아도 사용이 가능하다. this 참조변수의 사용은 불가능하다. heap 영역이 아닌 static 영역에 할당되며 GC에 관리받지 않는다. public 키워드까지 붙인다면 전역변수라고 볼수도 있다.

    • 지역변수(local variable)

        특정 메서드 내에서만 사용되는 변수
  • 메서드(method)
    해당 객체의 행위(동작)를 나타낸다. 자바에서는 모든 메서드가 클래스에 존재하기 때문에 모든 함수가 메서드이다.

    • 인스턴스 메서드(instance method)
      인스턴스와 연관된 작업을 하는 메서드로 인스턴스 생성후에 사용이 가능하다. 인스턴스 메서드 내부에서 클래스 변수와 인스턴스 변수 모두 사용이 가능하다.

    • 클래스 메소드(static method)
      static키워드를 가지고 있는 메서드 인스턴스와 관계가 없어 인스턴스를 생성하지 않아도 사용할 수 있다. 클래스 메서드 내부에서는 인스턴스 변수를 사용할 수 없고 클래스 변수와 지역변수만 사용가능하다.

      메서드 정의

        접근제어자 반환타입 메서드이름 (매개변수 리스트) - 선언부
        {
            - 구현부
        }    
        public void test1() {
            // 메소드 내용
        }
      
        public int test2() {
            // 메소드 내용
            return 5;
        }
      
        public String test3(String str) {
            return str;
        }
      • *반환타입 *
        메서드가 작업을 수행하고 반환할 데이터의 타입을 명시
    • 메서드 이름
      메서드명은 동사여야 하며, camelCase 명명법을 따르고 뜻이 분명해야한다.

    • 메서드 시그니처
      메서드이름과 매개변수 리스트를 메서드 시그니처라고 부른다. 컴파일러는 메서드 시그니처를 보고 구별할 수 있기 때문에 메서드 오버로딩(method overloading) 을 지원한다. 반환타입은 메서드 시그니처가 아니기 때문에 반환 타입만 다른경우에는 오버로딩을 할 수 없다.

  • 생성자(constructor)
    인스턴스를 생성해주고 클래스의 객체를 초기화하는데 사용되는 특수한 메서드라고 할 수 있다. 메서드와 달리 반환 값(반환타입이 없다)이 없기 때문에 return도 사용하지 않는다. 클래스와 이름이 같아야하며 최소 1개 이상의 생성자를 가질 수 있다. 생성자가 한 개도 정의되지 않는 경우 default생성자를 자동으로 추가한다. 반대로 한개라도 생성된 경우 dafault생성자는 생성되지 않는다. 객체 초기화 방법이 여러개일 경우 여러개의 생성자를 가질 수 있다.

    생성자 생성

      class Con {
          private int number;
    
          // default 생성자
          public Con() {
              // 인스턴스 변수를 초기화할 수 있다.
          }
    
          // 여러가지 파라미터를 받을 수도 있다.
          // 인스턴스 변수의 타입들이 다를 경우에만 1개의 인자를 받을 수 있다.
          public Con(int number) {
          // 파라미터를 이용하여 인스턴스 변수를 초기화할 수 있다.
              this.number = number;
          }
      }

    생성자 호출

      public static void main(String[] args) {
          // new 키워드를 이용하여 생성자를 호출할 수 있다.
          Con con = new Con();
          Con con = new Con(55);
      }

    new 연산자

    new 키워드는 새로운 객체(인스턴스)에 메모리를 할당하고 메모리에 대한 참조값을 반환하여 클래스를 인스턴스화 한다. 일반적으로 객체가 메모리에 할당되면 인스턴스라고 부른다.

    객체의 생성과정

    1. new 연산자가 메모리 영역에 저장공간을 할당 받는다.
    2. 생성자가 객체를 초기화한다.
    3. new 연산자가 새로 생긴 객체의 주소를 변수에 저장한다.
    4. 변수를 통해 해당 객체에 접근한다.
  • 초기화 블록(initializer)
    초기화 블록 내에서는 조건문, 반복문과 같은 제어문을 사용해 인스턴스 및 클래스 변수를 초기화 할 수 있다.

    • 클래스 초기화 블록
      클래스 변수를 초기화 할 수 있다.

    • 인스턴스 초기화 블록
      인스턴스 변수를 초기화 할 수 있다.

      class Class {
       static String classVariable;
       String instanceVariable;
      
       // 클래스 초기화 블록
       static {
           classVariable = "Class Variable";    
       }
      
       // 인스턴스 초기화 블록
       {
           instaceVariable = "Instance Variable";
       }
      }

      static, public 이런 키워드를 제어자(modifier)라고 하며, 클래스나 멤버 선언시 부가적인 의미를 부여한다.

      • 접근제어자
        접근지시자, 접근지정자 등 많은 이름으로 불리운다. 해당 클래스 또는 멤버 (변수, 메서드)를 정해진 범위에서만 접근할 수 있게 해준다.
  • 클래스에 경우 publicdefault 접근제어자만 사용이 가능하다.* default의 경우는 아무것도 명시하지 않았을때를 의미한다. 접근 제어자의 범위는 여기를 참조하면 된다.

  • static

    • 객체를 생성하지 않아도 고정된 메모리 영역을 할당받는다.(Static영역).
    • 객체를 생성하지 않아도 static변수와 static 메소드를 사용할 수 있다.
    • static으로 선언된 변수와 메서드등은 모든 객체가 공유할 수 있다.
  • final

    • 클래스 앞에 붙으면 해당 클래스는 상속될 수 없다.
    • 변수 또는 메서드 앞에 붙으면 수정이나 오버라이딩을 할 수 없다.
  • abstract

    • 클래스 앞에 명시하면 추상 클래스가 되어 객체 생성이 불가능하다. 접근을 위해선 상속 받아야한다.
    • 변수 앞에는 명시할 수 없다.
    • 메서드에 명시할 경우 추상 클래스(abstract class) 내에서만 가능하다. 추상 메서드는 선언만하고 추상 클래스를 상속한 클래스에서 구현해야한다.
  • transient
    변수 또는 메서드가 포함된 객체를 직렬화(Serialize)할 때 해당 내용은 무시된다. (데이터를 전송하고 싶지 않을때)

  • synchronized
    메서드는 한 번에 하나의 쓰레드에 의해서만 접근이 가능하다.

  • volatile
    자바 변수를 메인 메모리에 저장하겠다라는 것을 명시하는 것.

this 키워드

this키워드는 인스턴스 자신을 가리키는 명령어이다. 인스턴스가 생성되지 않고도 사용할 수 있기 때문에 클래스 메서드에서는 this를 사용할 수 없다.

  • 클래스의 속성과 매개변수의 이름이 같을 때 사용할 수 있다.

     public class Test{
         private int num;
    
         public Test(int num) {
             this.num = num;
         }
     }

    인스턴스 변수의 num과 매개변수의 이름이 같기 때문에 명시적으로 어떤 변수를 가리키는지 적어준다.

  • 객체 자신의 참조값을 전달하고 싶을때 사용할 수 있다.

     public class Test {
         int a;
    
         public Test(int a) {
             this.a = a;
         }
    
         public Test getTeset() {
             return this;
         }
     } 

    this()는 해당 클래스의 생성자를 호출할 수 있다.생성자를 재사용하는데 쓰인다. (생성자 체이닝)

    public class Test {  
     int a;  
     int b;  
    
    public Test(int a) {  
     this.a = a;  
    }  
    
    public Test(int a, int b) {  
     this(a);  
     this.b = b;  
    }  
    }

중첩 클래스 Nested Class

자바에서는 한 클래스 내부에 다른 클래스를 선언할 수가 있다. 이러한 클래스를 중첩 클래스 Nested Class라고 부른다.
static키워드를 사용한 경우 static nested class라고 부른다.
반대로 static을 사용하지 않은 경우 inner class라고 부른다.

public class OuterClass {
    static class StaticNestedClass {

    }

    class InnerClass{

    }
}

중첩 클래스는 중첩 클래스를 둘러싼 클래스의 멤버이기 때문에 OuterClass 필드에 접근이 가능하다. (private 접근지정로 되어있어도 접근할 수 있다. 하지만 StaticNestedClass 경우 필드에 접근이 불가능하다.

중첩 클래스를 사용하는 이유

  • 한 곳에서만 사용하는 클래스들을 논리적으로 그룹화할 수 있다.
  • 캡슐화를 증가 시킨다.
  • 읽기 쉽고 유지보수하기 쉬운 코드로 이어질 수 있다.

중첩 클래스 종류

  • Static Nested Class
    OuterClass의 변수나 메서드에 직접 접근이 불가능하다. 접근하기 위해서는 그 클래스의 객체 참조를 사용해야 한다. Static Nested Class 는 일반적으로 선언하는 클래스처럼 사용할 수 있다. 다른 클래스에서 Static Nested Class에 접근하기 위해서는 OuterClass를 통해 접근할 수 있다.

     public class OuterClass {
         public static class StaticNestedClass {
         }
     }
    
     public class AnotherClass {
         public static void main(String[] args) {
             OuterClass.StaticNestedClass staticNestedClass = new OuterClass.StaticNestedClass();
         }
     }
    • Inner Class
      객체의 필드나 메서드에 바로 접근이 가능하지만 인스턴스의 멤버변수로서 정의가 되기 때문에 static 멤버변수를 가질 수 없다. OuterClass에 대한 인스턴스를 여러개 생성할 경우 어떤 인스턴스의 static 멤버 변수 값이 옳은지 알 수 없기 때문에 일반적으로는 가질수 없다. 하지만 final키워드를 사용할 경우 컴파일 시점에 결정되고 변수의 값을 변경될 수 없기 때문에 사용이 가능하다.

      public class OuterClass{
         public class IneerClass{ 
             static int number = 2;  // 컴파일 에러 (X)
             static final int number = 2 // 선언할 수 있음 (O)
         }
      }

      Inner 클래스를 인스턴스화 하기 위해서는 먼저 OuterClass를 인스턴스화 해야한다. 그 다음 OuterClass의 인스턴스를 이용하여 InnerClass의 객체를 만들 수 있다.

      public class OuterClass {
         private int number = 10;
      
         public class InnerClass {
             private int number = 20;
      
             public void method(int number) {
                 System.out.println(number);  // 30 출력
                 System.out.println(this.number);  // 20 출력 
                 System.out.println(OuterClass.this.number);   // 10 출력
             }
         }
      }
      
      public class AnotherClass {
         public static void main(String[] args) {
             OuterClass outerClass = new OuterClass();
             outerClass.InnerClass innerClass = outerClass.new InnerClass();
      
             innerClass.method(30);
         }
      }

      InnerClass와 OuterClass의 같은이름의 인스턴스 변수가 존재한다면 (OuterClass).this.(변수)로 OuterClass의 변수에 접근할 수 있다.

  • Local Class
    코드 블럭 {}안에 정의된 클래스를 의미하여 메서드에서 정의된 클래스를 말한다. 특정 메서드에서만 어떤 객체가 필요할때 주로 사용된다.

    • Anonymous Class
      이름이 없다는 것만 빼면 Local Class와 동일하다. Local Class를 한 번만 사용해야하는 경우에 사용할 수 있다. 선언과 동시에 인스턴스화가 가능하다. Anonymous Class는 표현식이기 때문에 다른 표현식에서 사용이 가능하다.

      
      public class AnonymousClassExam {
      
          interface myInteface {
              public void greet();
              public void greetSomeone(String someone);
          }
      
          public void sayHello() {
      
              // 선언과 동시에 인스턴스화 할 수 있다.
              myInteface myInterface = new myInteface() {
                  String name = "tout le monde";
                  public void greet() {
                      greetSomeone("tout le monde");
                  }
                  public void greetSomeone(String someone) {
                      name = someone;
                      System.out.println("Salut " + name);
                  }
              };
      
              myInterface.greet();
              myInterface.greetSomeone("Fred");
          }
      
          public static void main(String... args) {
              AnonymousClassExam myApp =
                      new AnonymousClassExam();
              myApp.sayHello();
          }
      }

      Anonymous Class 표현식은 다음으로 구성된다.

      • new 연산자

      • 구현할 인터페이스 또는 클래스의 이름

      • 구현하고자하는 클래스의 생성자와 동일한 인자를 가진 괄호, 인터페이스에 경우 빈 괄호

      • 클래스를 정의한 body 부분, 메서드는 선언할 수 있지만 명령어는 선언할 수 없음.

      • Anonymous Class 제약사항

      • Anonymous Classfinal or effectively final이 아닌 지역 변수에 접근할 수 없다.

      • 중첩 클래스 처럼 OuterClass의 변수와 동일한 이름으로 선언시 OuterClass의 변수를 숨기게 된다.

      • static 초기화 블록 및 멤버 interface를 선언할 수 없다.

      • 상수 변수에 한해서만 static 멤버를 가질 수 있다.

      • 생성자를 정의할 수 없다.

      • OuterClass의 멤버에 접근할 수 있다.

      • 필드, 추가 메서드, instance 초기화 블럭, Local Class를 선언할 수 있다.

참고
https://ko.wikipedia.org/wiki/%EC%BA%A1%EC%8A%90%ED%99%94
https://webclub.tistory.com/137
https://webclub.tistory.com/156?category=501048
https://jeeneee.dev/java-live-study/week5-class/
https://ahnyezi.github.io/java/javastudy-5/
https://blog.naver.com/swoh1227/222174170682
https://github.com/ByungJun25/study/tree/main/java/whiteship-study/5week#class
https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

반응형

'Programming > JAVA' 카테고리의 다른 글

패키지란?  (0) 2021.01.21
상속이란?  (0) 2021.01.07
JUnit이란?  (0) 2020.12.31
제어문이란?  (0) 2020.12.29
연산자란?  (0) 2020.12.22