05AM

[Java] 키워드 정리 - this, super, static, final, 기본/참조 타입 본문

Programming Language/Java

[Java] 키워드 정리 - this, super, static, final, 기본/참조 타입

_05AM 2023. 4. 21. 18:26

this : 참조 변수

인스턴스가 바로 자기 자신을 참조하는데 사용하는 변수
해당 인스턴스의 주소를 가리키고 있다.

 

예시로, 생성자의 매개변수 이름과 인스턴스 변수의 이름이 같을 경우에는 인스턴스 변수 앞에 this 키워드를 붙여 구분해만 한다.

Class Car {
    private double speed;
    private String size;
    private String color;
    
    public Car(double speed, String size, String color) {
        this.speed = speed;
        this.size = size;
        this.color = color;
    }
}

 

java에서는 this 참조 변수를 사용하여 인스턴스 변수에 접근할 수 있다. 이러한 this 참조 변수를 사용할 수 있는 영역은 인스턴스 메소드뿐이며, 클래스 메소드에서는 사용할 수 없다.

모든 인스턴스 메소드에는 this 참조 변수가 숨겨진 지역 변수로 존재하고 있다.

this() 메소드

같은 클래스의 다른 생성자를 호출할 때 사용하는 메소드
생성자 내부에서만 사용 가능하다.

 

this() 메소드에 인수를 전달하면, 생성자 중에서 메소드 시그니처━메소드의 이름과 메소드의 원형에 명시되는 매개변수 리스트━가 일치하는 다른 생성자를 찾아 호출해 줍니다.

 

Class Car {
    private double speed;
    private String size;

    Car(double speed, String size, String color) {
        this.speed = speed;
        this.size = size;
        this.color = color
    }
    
    Car(String color) {
    	this(100.0, "mid", color);		// 파라미터가 일치하는 생성자 호출
    }
}

 

이렇게 내부적으로 다른 생성자를 호출하여 인스턴스 변수를 초기화할 수 있다.

단, 한 생성자에서 다른 생성자를 호출할 때에는 반드시 해당 생성자의 첫 줄에서만 호출할 수 있다.

super : 참조 변수

상속받은 부모를 가리키는 참조 변수

 

자식 클래스는 부모 클래스를 상속받았기에 부모의 모든 속성을 사용할 수 있지만, 자식과 부모의 속성 사이의 구분이 되어야 한다. 자식 클래스와 부모 클래스의 멤버가 동일한 이름을 갖고 있다면 그것을 부모로부터 구분해 낼 수 있어야한다는 의미이다.

super() 메소드

상속받은 부모의 생성자를 호출하는 메소드

 

상속에서 부모 생성자는 상속되지 않는다. 따라서 부모 클래스의 멤버를 초기화하기 위해서는 부모 클래스의 생성자를 호출해야 한다. 즉, 자식 클래스의 생성자를 호출할 때 부모 클래스의 생성자를 먼저 호출해야할 필요가 있다.

 

자바 컴파일러는 부모 클래스에 오버로딩한 생성자가 없을 경우, 자식 클래스 생성자 호출 시 자동으로 super() 메소드를 추가해준다.

하지만 부모 클래스에 기본 생성자가 없이 오버로딩한 생성자만 있을 경우, 자식 클래스의 생성자에 자동으로 super() 메소드가 추가되지 않으므로 조치를 취하지 않으면 에러가 발생한다.

 

이에 대한 해결 방법은 부모 클래스에 기본 생성자를 선언하거나, 부모 클래스의 오버로딩된 생성자에 맞춰 super()의 인자를 맞춰 호출하는 방법이 있다.

static

클래스 멤버를 설정하는 키워드
선언 시 static 키워드가 붙은 변수와 메소드 : 클래스 멤버(정적 멤버)

 

정적 멤버(정적 필드와 정적 메소드)는 컴파일 시 static area에 저장되며 프로그램이 시작할 때 적재되어 종료될 때까지 메모리에 남아있다.

 

정적 멤버는 인스턴스에 소속된 멤버가 아니라 클래스에 고정된 멤버이다. 때문에 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리된다. 따라서 정적 멤버는 별도의 인스턴스 생성 없이도 클래스의 로딩이 끝나는 즉시 바로 사용 가능하다.

 

프로그램 종료까지 어디서나 사용 가능하지만, 전역 변수이므로 무분별하게 많이 사용하게 되면 메모리가 부족하게 되는 문제가 발생할 수 있고, 프로젝트가 커지고 시스템이 오랜 시간 돌아가게 되면 시스템 운영속도가 느려질 수 있다.

따라서 static은 여러 번 참조해야하는 상수나 유틸리티 같은 경우에만 선언하는 것이 좋다.

 

인스턴스에 따라서 변하지 않는 값이 필요한 경우

인스턴스를 생성할 필요가 없는 값을 클래스에 저장하고 싶은 경우

-  값의 변경 사항을 모든 인스턴스가 공유해야 하는 경우

 

static 변수는 명시적인 초기화가 안된 경우 0으로 초기화 된다.

또한 객체 참조 없이 바로 사용할 수 있기 때문에 인스턴스 필드나 메소드, this 키워드를 사용할 수 없다.

Static vs Stack vs Heap

Stack 영역은 지역 변수와 매개변수의 데이터 값이 저장되는 공간이다. 해당 지역 변수가 포함된 메서드가 호출될 때 메모리에 할당되고, 종료되면 메모리에서 사라진다.

원시 타입 변수의 값들은 Stack 영역에 저장되고, 참조 타입 변수는 참조값만 저장된다. 참조값에는 해당 인스턴스 주소 값이 들어간다.

 

Heap 영역은 참조형의 데이터 타입을 갖는 객체의 데이터 값이 저장된다. 이때, 변수(객체, 객체 변수, 참조 변수)는 Stack 영역의 공간에서 실제 데이터가 저장된 Heap 영역의 참조값(reference key = 메모리에 저장된 주소를 연결해주는 값)을 new 연산자를 통해서 리턴 받는다.

즉, 실제 데이터를 가지고 있는 Heap 영역의 주소 값을 Stack 영역의 객체가 갖는다.

 

어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면, Garbage Collector에 의해 메모리에서 사라지게 된다.

 

[출처] [Java] static변수와 static 메소드 - MangKyu's Diary (tistory.com)

final

변경하지 못하게 제한한다는 의미

 

해당 클래스가 설계대로 돌아가느냐 마느냐는 기능이 잘 돌아가느냐보다는 추후 유지보수를 위해 사용하게 되는 키워드이다.

Variable(변수)

변수에 final을 붙이면 이 변수는 수정할 수 없다는 의미를 가진다. 수정할 수 없기에 선언 시 초기화를 필수로 해야한다.

수정할 수 없다는 범위는 그 변수의 값에 한정된다. 즉, 다른 객체를 참조하거나 할 때 참조하는 객체 내부의 값은 변경할 수 있다는 의미이다. 기본형 변수는 값을 변경하지 못하고, 참조형 변수는 그 객체 내부의 값은 변경할 수 있지만 가리키는 객체를 변경하지 못한다. final 키워드는 stack 영역에만 영향을 미친다.

Method(메소드)

메소드에 final을 붙이면 override를 제한하게 된다. 클래스를 상속하게 되면 해당 클래스의 protected, public의 접근 제어자를 가진 메소드를 상속해서 재구현할 수 있는데, 해당 메소드를 수정해서 사용하지 못하도록 한다.

Class(클래스)

클래스에 final 키워드를 붙이면 상속이 불가능한 클래스가 된다. 즉, 다른 클래스에서 상속하여 재정의할 수 없다.

대표적인 클래스로 Integer와 같은 wrapper 클래스가 있다. 클래스 설계 시 재정의 여부를 생각해서 재정의 불가능하게 사용하고 싶다면 final로 등록하는게 추후 유지보수차원에서 용이하다.

static final

클래스에 존재하는 상수

 

객체마다 값이 바뀌는 것이 아닌 클래스에 존재하는 상수이다. 마찬가지로 선언과 동시에 초기화를 해주어야 한다.

기본형 타입 : Primitive type

Java는 총 8가지의 기본형 타입을 미리 정의하여 제공한다.

 

-  기본값이 있기 때문에 Null이 존재하지 않는다. 만약 기본형 타입에 Null을 넣고 싶다면 wrapper class를 활용한다.실제 값을 저장하며 Stack 메모리에 저장된다.-  컴파일 시점에 담을 수 있는 크기를 벗어나면 컴파일 에러가 발생한다.

 

  타입 할당 메모리 크기 기본값 데이터 표현범위
논리형 boolean 1 byte false true, false
정수형 byte 2 byte 0 -128 ~ 127
short 2 byte 0 -32,768 ~ 32,767
int 4 byte 0 -2,147,483,648
~ 2,147,483,647
long 8 byte 0L  -9,223,372,036,854,775,808
~ 9,223,372,036,854,775,807
실수형 float 4 byte 0.0F (3.4 X 10-38)
~ (3.4 X 10
38) 의 근사값
double 8 byte 0.0 (1.7 X 10-308)
~ (1.7 X 10
308) 의 근사값
문자형 char 2 byte(유니코드) '\u0000' 0 ~ 65,535

참조형 타입 : Reference type

기본형 타입을 제외한 모든 타입들

 

- 빈 객체를 의미하는 Null이 존재한다.-  값이 저장되어 있는 곳의 주소값을 저장하는 공간으로 Heap 메모리에 저장된다.-  실행 시 발생하는 런타임 에러가 발생한다. 예를 들어 객체나 배열을 Null 값으로 받으면 NullPointException이 발생하므로 변수값을 넣어야 한다.

 

타입 기본값 할당 메모리 크기
배열(Array) Null 4 byte (객체의 주소 값)
열거(Enumeration)
클래스(Class)
인터페이스(Interface)

참고

코딩의 시작, TCP School

Static, Stack, Heap / Java 메모리 영역의 구조와 특징 (tistory.com)

[Java] 자바 static의 의미와 사용법 (tistory.com)

클래스 맴버와 인스턴스 맴버 - 생활코딩 (opentutorials.org)

java. super와 super() 완벽하게 이해하기 (velog.io)

[Java] final 키워드에 대해서 알아보자 (tistory.com)

[Java] final 과 static fin.. : 네이버블로그 (naver.com)

자바의 데이터 타입(Primitive type, Reference type) (tistory.com)

Comments