주말이 지나 월요일이 왔다. 코드스테이츠를 시작하면서
1일1커밋이라는 Study라는 공부 모임에 가입했다. (코드스테이츠 內)

하루에 한번 커밋해서 잔디를 빼곡하게 심는데
의미있는 내용을 커밋해야하고 조를 만들어 서로서로
커밋한 내용이 제대로 되었는지 검수?해주면서 발전해나가는 스터디다.

주말에 하루에 한번 커밋을 위해서 알고리즘 문제를 풀고 GitHub에 커밋을 했다.
약속이 있었지만 저녁에와서 컴퓨터를 키고 하나라도 문제를 푸는 습관을 가지니
간단하지만 무언가 뿌듯한 느낌이 ?

image

나 자신에게 박수 👏👏

서서히 프로그래머로서의 역량과 부지런함 그리고 발전해나가는 모습으로 성장해보자!
오늘도 화이팅하며 공부 시작!


저번주에는 참 배운 것이 많다.
Git부터 시작해서 Java에 대한 문법 그리고 객체지향에 대한 내용들.
바로 이전시간에는 클래스와 필드,메서드 등에 대해 공부를 했고
이번 시간에는 생성자와 내부 클래스(inner Class)에 대해

공부 해볼 시간이다.

생성자(Constructor)

Car avante = new Car():
앞에서 사용했던 위와 같은 문구가 있다고 할 때
맨 오른쪽에 Car();부분이 생성자이다.
생성자는 인스턴스 변수들을 초기화하는 데 사용되는 특수한 메서드이다.

생성자는 크게 두가지 특징이있다.

1). 생성자의 이름은 반드시 클래스와 이름이 같아야한다.
2). 생성자는 리턴 타입이 없다.

선언방법

접근제어자 클래스명(매개변수) { // 생성자 기본 구조
	...생략...
}

위와 같이 클래스명과 반드시 같아야하고 리턴해주는 리턴타입이 없다.
접근제어자는 생략해도 된다.

사용 예제를 한번 들어보자

class Car {
    Car() { 
        System.out.println("1번 생성자");
    }

    Car(String str) { 
        System.out.println("2번 생성자");
    }

    Car(int a, int b) {
        System.out.println("3번 생성자");
    }
}

위와 같이 Car라는 클래스가 있으면
생성자를 만들어주려면 클래스명과 동일한 메서드를 만들면 된다.
위와 같은 경우는 매개변수가 다른 3개의 생성자를 만든 것이고
이를 각각 호출할 수 있다.

여기서 생성자는 두가지 타입으로 나누어진다.
1번 생성자의 경우를 매개변수가 없는 생성자라고하고
2번,3번 생성자의 경우 매개변수가 있는 생성자라고한다.

여기서 유의할 점은
클래스안에 아무런 생성자가 없을 경우
컴파일러가 기본 생성자를 자동으로 추가해줬기 때문에
우리가 인스턴스를 만들 수 있었던 것이다.
이런 생상자를 기본 생성자라고 한다.


this() vs this.

this()

this();도 다른 메서드와 동일하다.
생성자를 상호 호출해주는 메서드로
자신이 속한 클래스에서 다른 생성자를 호출한는 경우에 사용한다.

public class prac {
    int test = 0;
    prac() {
        System.out.println("연습");
    }
    prac(int x,int y){
        this();
        System.out.println(x+y);
    }
}
public class Main{
    public static void main(String args[]) {
        prac ins1 = new prac();
        prac ins2  = new prac(1,2);
    }
}
// 출력내용
연습
연습
3

위와 같은 클래스가 있다고 가정할때.
Main 클래스에서는 생성자를 2개를 이용해 인스턴스 2개를 만들었다.

각각의 내용들은 기본생성자는 “연습”이라는 내용을 출력하고
매개변수를 가진 생성자는 this(); 메스드 호출 후
매개변수끼리 더하는 내용을 출력하게된다.

위와 같이 내용이 출력되게 되어지고 this();는 기본 생성자를 호출하는
모습을 볼 수 있다. 반대로 매개변수를 가진 생성자를 호출할 경우
this(1,2); 이렇게 호출할 수 있다.


this.

this. 키워드는 매개변수와 인스턴스 변수를 구분하기 위한 용도로 사용되는 방법이다.

class Car {
    private String modelName;
    private String color;
    private int maxSpeed;

    public Car(String modelName, String color, int maxSpeed) {
        this.modelName = modelName;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
}

예제를 살펴보자

modelName, color, maxSpeed라는 3가지의 인스턴스 변수가
선언되어 있다. 이변수를 생성자에서 초기화를 하고싶을 경우
this.라는 키워드를 가져다 사용하게되어야 매개변수와 혼동되지 않는다.

매개변수도 이름이 동일하기 때문!
만약 this.라는 키워드를 사용하지 않게되면
지역변수로 인식하게 된다.


내부 클래스(Inner Class)

말 그래도 클래스 내에 선언된 클래스이다.
내부 클래스를 사용하면 외부 클래스의 멤버들이 쉽게 접근이 가능하고
코드의 복잡성을 줄일 수 있다고 한다.

선언방법

class Outer { // 외부 클래스
	
	class Inner {
		// 인스턴스 내부 클래스	
	}
	
	static class StaticInner {
		// 정적 내부 클래스
	}

	void run() {
		class LocalInner {
		// 지역 내부 클래스
		}
	}
}

내부 클래스는 3가지 나뉠 수 있다.

1). 인스턴스 내부 클래스
2). 정적 내부 클래스
3). 지역 내부 클래스

위에 보는 것과같이 외부 클래스가 기존 처럼 있고
그안에 클래스를 정의하면 내부클래스가 된다.

여기서 static을 붙여주면 정적 내부클래스가되며,
클래스 안에 메소드 안에 클래스가 있으면, 지역 클래스가 되어진다.


인스턴스 내부 클래스

public class prac { // 외부 클래스
    private int x = 3;
    private static int y = 5;
    private InPrac InPrac;
    public  prac(){ // 외부 클래스 생성자
        InPrac = new InPrac();
    }
    class InPrac{ // 인스턴스 내부 클래스
        void Test(){
            System.out.println(x);
            System.out.println(y);
        }
    }
    public void testClass(){
        InPrac.Test();
    }
}
public class Main {
    public static void main(String[] args) {
        prac test = new prac();
        System.out.println("외부 클래스 사용하여 내부 클래스 기능 호출");
        test.testClass(); // 내부 클래스 기능 호출
    }
}

//출력값
외부 클래스 사용하여 내부 클래스 기능 호출
3
5

위와 같이 예제를 보면 InPrac라는 인스턴스 내부클래스를 생성했다.
이제 이안에 있는 Test(); 매소드를 호출하는 방법은 위와같이
prac클래스의 생성자를 통해 인스턴스를 만들어준 다음 포인트 연산자를 통해 호출이 가능하다.

여기서 중요한점은 접근제어자 private를 사용하고 있음에도
내부에서 외부 클래스의 인스턴스 변수와 정적 변수에 접근하여 사용하고 있다는 점이다.
즉, 내부 클래스는 기본적으로 외부 클래스 존재에 의존하고 있다.


정적 내부 클래스

내부 클래스가 외부 클래스의 존재와 무관하게 정적변수를 사용할 수 있다.

public class prac {
    private int x = 3;
    private static int y = 5;
    static class InPrac{
        void test(){
            System.out.println(x); // 에러 발생. 정적멤버가아니므로 사용 불가
            System.out.println(y);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        prac.InPrac sample = new prac.InPrac(); //정적 이너 클래스의 객체 생성
        sample.test();
    }
}

// 출력 (에러부분 삭제후)
5

위의 예제로 보면 인스턴스 내부 클래스와 동일한 예제지만
호출하는 방법이 조금 달라졌다.
그리고 정적 내부클래스로 함수를 만들었다는 점.
x는 인스턴스 변수이기때문에 접근이 안되며 에러가 발생한다.


지역 내부 클래스

public class prac {
    private int x = 3;
    private static int y = 5;
    void test() {
        class InPrac { //지역 내부 클래스
            void getPrint() {
                System.out.println(x);
                System.out.println(y);
            }
        }
        InPrac test = new InPrac();
        test.getPrint();
    }
}
public class Main {
    public static void main(String[] args) {
        prac test = new prac();
        test.test();
    }
}

// 출력
3
5

지역 내부클래스도 위와 동일한 예저로 들자면
void test();라는 메서드 내부에 내부 클래스가 존재하는 점이 달라진 점이다.
함수를 호출하기 위해 getPrint();라는 메서드를 만들어 x,y라는 값으 출력하게 두었다.
동일한 방법으로 InPrac클래스의 test라는 인스턴스를 만들어 getPrint();를 호출.

그리고 Main 클래스에서 외부 클래스인 prac의 test 인스턴스를 만들어
외부클래스의 test();메서드를 호출하면 지역내부클래스도 호출할 수 있다.



마치며

오늘은 생성자와 이너클래스에대해 알아 보았다.
이너클래스의 개념이 다소 생소하고 난해한데 조금 더 공부를 해야할 것 같다.

우선 호출하는 방법과 해당 내부클래스의 위치가 어떻게
위치하는지 알 수 있는 시간이었고
너무나도 많은 개념들이 머리에 둥둥 떠다니고있다

인스턴스,멤버,클래스,객체,이너클래스,인자,매개변수~~ 등등
각각 하나만 5초이상 생각하면 떠오르는데
한문자으로 쭉 이야기하면 머리가 뒤죽박죽되어버린다.

그 말은 즉 내가 제대로 개념을 이해하지 못하고 있다는 뜻인 것 같다.
앞으로 계속 이런 단어들에 노출되면 기억될거라 믿으며
하루에 한번씩 자바 용어에 대한 내용들을 읽고 시작해야할 것 같다.


오늘의 커피량: ☕️ ☕️ ☕️ ☕️️️️
오늘의 점심: 떡볶이, 공기밥