Unicorns

All the things

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java Study] - java class(클래스) - 객체,생성자, this 키워드
    Java 2021. 11. 8. 09:55

    객체 지향 프로그래밍(OOP , Object - Oriented Programming)

    객체 지향 프로그래밍에서는 모든 데이터를 객체(Object)로 취급하며, 이러한 객체가 바로 프로그래밍의 중심이 된다.

     

     

    객체(object) 란 간단히 이야기하자면 실생활에서 우리가 인식할 수 있는 사물을 지칭하는 데,

    상태(state) , 행동(behavior) , 정체성(identity)로 구성 되어 있다.

    • State  : 객체의 속성을 표현하고 반영한다.
    • Behavior : 객체의 메서드로 표현 되는데 ,  객체들 간의 메시지를 반영한다.  
    • Identity :  객체의 고유한 이름을 제공한다. 이를 통해 객체들 간의 상호작용이 가능하다. 

    ex)

    이러한 객체의 상태(state) 와 행동(behavior) 그리고 정체성(Identity)을 구체화하는 형태의 프로그래밍이 바로 객체 지향 프로그래밍이다.

     

    이때 객체를 만들어 내는 설계도와 같은 개념을 클래스(class) 라고 한다.

    클래스(class)

    자바에서 클래스(class) 란? 객체를 정의하는 틀 또는 설계도와 같다고 보면 된다.

     

    클래스 선언

    사용하고자 하는 객체를 구상했다면, 그 객체의 대표 이름을 하나 결정하고 이것을 클래스 이름으로 한다.

     

    클래스 작성 규칙

    작성 규칙
    하나 이상의 문자로 이루어져야 한다. Car, SportsCar
    첫 번째 글자는 숫자가 올 수 없다. Car ( o ) , 3Car ( x )
    '$','_' 외의 특수 문자는 사용할 수 없다. $Car ( o ),  _Car ( o )  , @Car ( x )  , #Car ( x ) 
    자바 키워드는 사용할 수 없다. int ( x ) , for ( x )

    관례적으로 클래스 이름이 단일 단어이면 첫 자를 대문자로 하고 나머지는 소문자로 작성한다.

    만약 서로 다른 단어가 혼합된 이름을 사용하면 각 단어의 첫 머리 글자는 대문자로 작성하는 것이 관례이다.

    ex)

    Calcualtor , Person , Animal , Client, LottoShop

     

    선언

    public class 클래스이름 {
    
    }

    public class 는 소문자로 작성해야 한다.

    클래스 이름 뒤에 중괄호를 붙여 주는데,  '{' 로 클래스 선언의 시작을 알려주고

    '} ' 로 클래스 선언의 끝을 알려 준다.

     

     

    보통 소스 파일 당 하나의 클래스를 선언하지만,  

    두 개 이상 선언하는 것도 가능하다.

    public class Car {
    }
    
    class Tire {
    
    }

    두 개 이상 클래스가 선언된 소스 파일을 컴파일 하면 선언한 클래스 수만큼 바이트 코드(.class) 파일이 생성된다.

     

    javac Car.java

     

    Car.class , Tire.class 파일 생성

     

    여기서 파일 이름과 public class 키워드가 붙은 클래스는 일치해야 한다.

    만약 파일이름과 일치하지 않는 클래스 선언에 public 접근 제한자를 붙이면 컴파일 에러가 발생한다.

     

     

     

    클래스의 구성 요소

    자바에서 클래스는 멤버(member)로 속성을 표현하는 필드(field)와 기능을 표현하는 메서드(method)를 가진다.

    또한, 클래스는 생성된 객체의 필드를 초기화해주는 특별한 메서드인 생성자(constructor)를 가진다.

     

     

    필드(field)

    클래스의 필드(field) 란 클래스에 포함된 변수(variable)를 의미하는데,

    객체의 고유 데이터, 객체의 현재 상태 데이터 등을 저장한다.

     

    클래스 내에서 필드는 선언된 위치에 따라 다음과 같이 구분 된다.

     

    1. 클래스 변수(static variable) :  static 키워드를 가지는 변수

    2. 인스턴스 변수(instance variable) :  클래스 영역에 위치한 변수 중 static 키워드를 가지지 않는 변수

    3. 지역 변수(local variable) : 메소드나 생성자, 초기화 블록 내에 위치한 변수

     

     

    클래스 변수와 인스턴스 변수는 초기화를 하지 않아도 변수의 타입에 맞게 자동으로 초기화가 되지만

    지역 변수는 사용하기 전에 초기화 하지 않으면 , 컴파일 오류가 발생한다.

    public class Car {
        static boolean isUsed; // 클래스 변수
        String model; // 인스턴스 변수
    
        void run() {
            int speed = 100; // 지역 변수
            System.out.println(speed);
            //초기화 하지 않으면 컴파일 에러가 발생한다.
        }
        public static void main(String[] args) {
            Car myCar = new Car();
            System.out.println(myCar.model); // 타입에 맞는 기본 초기값 출력
            System.out.println(Car.isUsed); // 타입에 맞는 기본 초기값 출력
        }
    }

    실행

    null
    false

    초기화

    public class Car {
        static boolean isUsed = true; // 클래스 변수
        String model = "소나타"; // 인스턴스 변수
    
        {
            isUsed= false; // 클래스 초기화 블럭
        }
    
        {
            model = "제네시스"; // 인스턴스 초기화 블럭
        }
    
        void run() {
            int speed = 100; // 지역 변수
    
        }
        public static void main(String[] args) {
            Car myCar = new Car();
            System.out.println(myCar.model);
    
        }
    }

    출력

    제네시스

     

     

    필드를 초기화할 때 데이터 타입과 필드를 선언하고 값을 바로 대입 할 수도 있지만

    초기화 블럭을 이용하여 값을 초기화 할 수 도 있다.

     

    초기화 블럭안에 조건문이나 반복문 등을 넣을 수 있기 때문에 

    조건문이나 반복문을 사용한 뒤 필드를 초기화 하고 싶을 때 사용한다.

     

     

    인스턴스(instance)

    클래스의 객체가 생성될 때, 그 클래스는 인스턴스화되었다고 한다.

    그리고 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance) 라고 한다. 

    즉, 인스턴스란 메모리에 할당된 객체를 의미한다.

     

    자바에서는 하나의 클래스로부터 여러 개의 인스턴스를 생성할 수 있다.

    이렇게 생성된 인스턴스는 독립된 메모리 공간에 저장된 자신만의 필드를 가질 수 있다.

    하지만 해당 클래스의 모든 메서드는 해당 클래스에서 생성된 모든 인스턴스가 공유하게 된다.

     

     

    객체 생성 (new 키워드)

    클래스로부터 객체를 생성할 때  new 연산자를 사용한다.

    new 클래스이름();

    new 연산자로 생성된 객체는 메모리 힙(heap) 영역에 생성된다.

    new Car();

    Car 객체를 하나 생성하였다.

     

    생성된 Car 객체를 메모리에 할당하고 객체의 참조 주소를 반환한다.

     

    이제 생성한 객체를 사용하기 위해 반환한 주소를 담을 변수가 필요하다.

    참조변수를 선언하고 생성한 객체의 주소를 저장하자

    Car myCar;
    myCar = new Car();

     

    이때 참조변수 선언를 하고 생성한 객체를 저장하는 작업을 동시에 할 수도 있다.

    Car myCar = new Car();

    Car 클래스는 하나지만 new 연산자를 사용한 만큼 객체가 메모리에 생성된다.

     

     

    생성자(Constructor)

    이름에서 알 수 있듯이, 프로그램에서 무언가를 생성하기 위해 사용된다. 바로 객체를 생성할 때이다.

    생성자는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성하고 동시에 인스턴스 변수를 원하는 값으로 초기화 할 수있다. 

     

    생성자는 메서드와 비슷하게 보이지만 , 메서드와 구분되는 특징이 있다.

    • 생성자는 반드시 클래스 이름과 같아야 하지만, 메서드는 그렇지 않아도 된다.
    • 생성자는 어떠한 타입도 반환하지 않지만, 메서드는 지정된 타입을 반환하거나 , 반환값이 없을 경우 void를 선언해야 한다.

     

    기본 생성자(dafault constructor)

    자바의 모든 클래스에는 하나 이상의 생성자가 정의되어 있어야 한다.

    만약 클래스 내부에 생성자를 생략했다면 컴파일러가 자동으로 기본 생성자를 생성한다.

     

    Person.java

    public class Person {
    }

    Person.class

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package step5;
    
    public class Person {
        public Person() {
        }
    }

    소스 파일에 생성자를 생략하였지만, 컴파일러가 자동으로 기본 생성자를 추가해준다.

    public class Application {
        public static void main(String[] args) {
            Person person = new Person();
        }
    }

     

    컴파일러가 자동으로 추가해줬기 때문에 위와 같이 기본 생성자를 호출할 수 있게된다. 

     

     생성자 선언

    기본 생성자 대신에서 생성자를 명시적으로 선언할 수 있다.

    클래스(매개변수 , ..) {
      // 객체의 초기화 코드
    }

    생성자는 위와 같이 반환값이 없지만,  반환 타입을 void 형으로 선언하지 않는다.

    매개 변수 선언은 생략할 수도 있고, 여러 개를 선언할 수 도 있다.

     

    Person.java

    public class Person {
        public Person(String name , int age) {
        }
    }

    바이트 코드를 살펴보면 

    Person.class

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package step5;
    
    public class Person {
        public Person(String var1, int var2) {
        }
    }

    매개 변수가 2개인 생성자가 생성되었다.

    클래스 내부에 생성자가 있기 때문에 이제는 파일러가 자동으로 기본 생성자를 추가하지 않는다.

     

    기본 생성자 호출 시 컴파일 에러가 발생한다.

     

     

    생성자는 초기화를 위한 데이터를 인수로 전달 받을 수 있다

     Person person = new Person("코니", 28);

     

     

    생성자 블록 내부에는 객체 초기화 코드가 작성되는데,  일반적으로 필드에 초기값을 저장하거나 메소드를 호출하여

    객체 사용 전에 필요한 준비를 한다. 

     

    public class Person {
        String nation = "한국"; // 필드 선언과 동시에 초기화
        String name; // 선언만 하고 초기화 X
        int age; // 선언만 하고 초기화 X
    
        public Person(String name , int age) {
            this.name = name; // 생성자에서 name 필드 초기화
            this.age = age;  // 생성자에서 age 필드 초기화
        }
    }

    .Person 클래스에서 객체를 생성 

    이때 name 과 age 값을 초기화 하는 생성자를 호출 

    public class Application {
        public static void main(String[] args) {
            Person person = new Person("코니" , 28); 
            System.out.println(person.nation); // 
            System.out.println(person.name);
            System.out.println(person.age);
        }
    }

     

     객체를 초기화하는 방법이 여러 개 존재할 경우에 하나의 클래스가 여러 개의 생성자를 가질 수 있다.

    public class Person {
        String nation;
        String name;
        int age; 
    
        // name 과 age 필드를 초기화 하는 생성자
        public Person(String name , int age) { 
            this.name = name; 
            this.age = age;  
        }
    
        // nation 필드만 초기화 하는 생성자
        public Person(String nation) {
            this.nation = nation;
        }
    
        // age 필드만 초기화 하는 생성자
        public Person(int age) {
            this.age = age;
        }
    
        // 모든 필드를 초기화 하는 생성자
        public Person(String nation, String name, int age) {
            this.nation = nation;
            this.name = name;
            this.age = age;
        }
    }

    외부에서 제공되는 다양한 데이터를 이용해서 객체를 초기화 하기 위해 생성자도 다양하게 추가해야 할 때가 있다.

    기본생성자 뿐만 아니라 외부에서 들어오는 다양한 데이터를 생성하기 위해 자바는 생성자 오버로딩(Overloading)을 제공한다.

     

    생성자 오버로딩이란 매개 변수를 달리하는 생성자를 여러 개 선언하는 것 을 말한다.

     

    다른 생성자 호출  - this()

    생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있는데, 

    이때 필드 초기화 내용은 한 생성자에 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 

    생성자를 호출하는 방법을 사용할 수 있다. 

     

    생성자에서 다른 생성자를 호출 할 때는 this() 키워드를 사용한다.

     

    public class Person {
        String nation;
        String name;
        int age;
    
        public Person() {
            this(28);
            System.out.println("기본 생성자 호출 됨");
        }
    
        public Person(int age) {
            this("코니", age);
            System.out.println("age 필드 매개변수 생성자 호출 됨");
        }
    
    
        public Person(String name, int age) {
            this("한국",name,age);
            System.out.println("name 과 age 매개변수 생성자 호출 됨");
        }
    
        public Person(String nation, String name, int age) {
            this.nation = nation;
            this.name = name;
            this.age = age;
            System.out.println("모든 필드를 초기화 하는 생성자 호출 됨");
        }
    }

    this() 키워드는 다른 생성자를 호출하는 코드로 생성자 첫줄에서만 사용 할 수 있다. 

    this()의 매개값은 호출 되는 생성자의 매개 변수 타입에 맞게 제공해야 한다. 

     

     

    기본 생성자 호출

    public class Application {
        public static void main(String[] args) {
            Person person = new Person();
        }
    }

    실행

    모든 필드를 초기화 하는 생성자 호출 됨
    name 과 age 매개변수 생성자 호출 됨
    age 필드 매개변수 생성자 호출 됨
    기본 생성자 호출 됨

     

    this() 다음에 추가적인 실행문이 올 수 있는데,

    호출된 생성자가 먼저 실행되고 실행이 끝나면 원래 생성자로 돌아와서 다음 실행문을 진행한다.

     

    public class Application {
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println(person.nation);
            System.out.println(person.name);
            System.out.println(person.age);
        }
    }

    기본 생성자만 호출하였지만, 기본 생성자에서 필드 값을 초기화하는 다른 생성자들을 점차적으로 호출 하였기 때문에

    필드 값이 지정된 값으로 초기화 되었다.

     

    실행

    모든 필드를 초기화 하는 생성자 호출 됨
    name 과 age 매개변수 생성자 호출 됨
    age 필드 매개변수 생성자 호출 됨
    기본 생성자 호출 됨
    한국
    코니
    28

     

     

    java 의 this 키워드 

    java 에서 객체를 생성한 후에 사용할 수 있는 필드와 메소드를 인스턴스(instance) 멤버라고 하는데,

    객체 외부에서 인스턴스 멤버를 사용하기 위해 참조변수를 사용하는 것처럼,

    객체 내부에서도 인스턴스 멤버에 접근하기 위해 this 를 사용할 수 있다.

     

    즉, 객체 안에서 자기 자신을 가리킬 때 this를 사용한다.

    (위에서 살펴본 생성자 호출 키워드 this() 와 다르다.)

     

    예를 들어

    public class Person {
        String nation;
        String name;
        int age;
    
        public Person(int age) {
            age = age;
        }
    
    }

    age 필드를 초기화 하기 위한 생성자를 추가하였다.

    이때,  필드로 선언된 age 와 생성자로 전달받은 매개변수 age가 같기 때문에

     

    구분할 수 가 없다.

    필드를 가리키는지 매개변수를 가리키는지 모호하다.

     

    결과적으로 생성자를 호출하면

    public class Application {
        public static void main(String[] args) {
            Person person = new Person(28);
            System.out.println(person.age);
        }
    }

     

    실행

    0

    age를 매개변수로 인식하기 때문에 필드가 초기화 되지 않는다.

     

    이때 this 키워드를 사용하면 문제를 해결할 수 있다.

    this 가 객체 인스턴스 자신을 가리키기 때문에

    현재 클래스 인스턴스 필드를 참조한다.

    public class Application {
        public static void main(String[] args) {
            Person person = new Person(28);
            System.out.println(person.age);
        }
    }

    실행

    28

     

    필드 뿐만 아니라 인스턴스 메서드도 참조한다.

     

    public class Person {
        String nation;
        String name;
        int age;
    
        public Person(int age) {
            this.age = age;
        }
    
        void study() {
            System.out.println("java 공부 시작");
        }
    
        void wake() {
            System.out.println("기상");
            study();
        }
    }

    wake() 메서드에서 study() 메서드를 호출 하는데

     

    메서드를 호출할 때 자바 컴파일러가 자동으로 this 키워드를 추가해준다.

     

    javac Person.java  = >   Person.class 

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package step5;
    
    public class Person {
        String nation;
        String name;
        int age;
    
        public Person(int var1) {
            this.age = var1;
        }
    
        void study() {
        }
    
        void wake() {
            this.study(); // 자바 컴파일러가 자동으로 추가해줌
        }
    }

     

     

     

     

     

    REFERENCE

    http://tcpschool.com/java/java_class_intro
    http://tcpschool.com/java/java_class_component
    https://www.geeksforgeeks.org/classes-objects-java/
    https://www.javatpoint.com/this-keyword
    이것이 자바다

     

    댓글

Designed by Tistory.