클래스 멤버와 인스턴스 멤버

주8·2023년 1월 9일
0

this

this는 인스턴스 자신을 가리키는 참조 변수로 인스턴스의 참조값이 저장되어 있다.

  • 모든 인스턴스 메서드 실행시 Stack에 지역변수로 숨겨진 채 존재한다.
  • this.변수, this.메소드() 형태로 사용한다.
  • this(), this(argument list) 형태로 자신의 다른 생성자를 호출할 때 사용한다.
  • this는 메서드 호출시 인수로 전달될 수 있다.
  • this는 인스턴스 변수와 지역변수를 구별하기 위해서도 사용된다.
  • 소스와 같이 parameter 변수명과 인스턴스 변수명이 동일한 경우 사용할 변수가 인스턴스 변수라는 것을 “this.멤버변수”를 통해 모호성 문제를 해결해준다.
  • 현재 클래스 인스턴스 변수를 참조하는데 사용할 수 있다.
  • 현재 객체 메서드를 호출하거나 클래스 인스턴스를 리턴하는데 사용할 수 있다.
  • 생성자내에서 this() 생성자 호출은 첫 번째 명령문이어야 한다.
public class LowerClass{
	int x;
	int y;
    
	public LowerClass(){
		x = 20;
		y = 20;
	}
  
	public LowerClass(int x){
		this(); //자신의 Default constructor를 호출한다
		this.x = x;
 	}
    
   	public LowerClass(int x, int y){
   		this.y = y;
   		//오버로딩 생성자 호출시 생성자문은 첫번째로 호출되어야 한다
   		this(x); //컴파일 오류 발생 - Call to 'this()' must be first statement in constructor body
   	}
}
  • this 키워드를 사용하여 현재 클래스의 메서드를 호출할 수 있다.
  • this 키워드를 사용하지 않으면 컴파일러는 this 키워드를 자동으로 추가한다.
Class TestA{
	void method1(){
		System.out.println("method1 call");
	}
	void method2(){
		System.out.println("method2 call");
		//컴파일러가 자동으로 this를 추가한다
		method1(); //this.method1();
	}
}

public class TestThisEx2{
	public static void main(String[] args){
		TestA test = new TestA();
		test.mwthod2();
	}
}

[결과]
method2 call
method1 call
  • 생성자를 통해 this 키워드를 전달할 수 있다.
  • 여러 클래스간의 하나의 객체를 전달해서 사용해야 하는 경우에 유용하다.
  • 메서드를 통해서도 this를 리턴할 수 있다.
class TestA3{
	TestA3 getTestA3(){
		return this;
	}
	void msg(){
		System.out.println("TestA3 msg() 호출");
	}
}

public class TestThisEx4{
	public static void main(String[] args){
		new TestA3().getTestA3().msg();
	}
}
  • 일반적으로 getter/setter 메서드에서 내부값을 할당하거나 접근할 때 사용한다.
String name;

public String getName(){
	return name;
}
public void setName(String name){
	this.name = name;
}
public static void main(String[] args){
	TestThisEx5 obj = new TestThisEx5();
	//setter/getter 메서드 호출
	obj.setName("홍길동");
	System.out.println("obj.name : "+obj.getName());
}

변수의 scope

this는 각 인스턴스 메소드의 Stack Frame에 this라는 로컬변수로 메모리 영역에 존재한다.


static


정적 변수(static variable)

  • 회사나 대학 이름 등과 같이 모든 객체의 공통 속성을 참조하는데 사용할 수 있다.
  • 정적 Object 변수, 상수는 Java 8버전 이전에는 PermGen 메모리 영역에 저장되었으나 Java 8버전 이후에는 Heap 영역으로 옮겨져 최대한 GC의 대상이 되도록 변경되었다.
    • 대량 데이터의 저장으로 OutOfMemory error가 발생하는 경우들이 있었다.
  • 정적 변수는 클래스 로딩시 클래스 영역에서 한 번만 메모리에서 가져온다.
  • 정적 변수의 장점은 변수 하나로만 관리되기 때문에 메모리를 절약하고 효율적으로 관리할 수 있다.

정적 메서드(static method)

  • 클래스의 객체가 아니라 클래스에 속한다.
  • 클래스의 인스턴스를 만들지 않고도 호출할 수 있다.
  • 정적 데이터 멤버에 접근할 수 있고, 해당 값을 변경할 수 있다.

static initializers

static{ }으로 만들고(static 변수만 사용할 수 있음) 생성자보다 먼저 실행됨

클래스 변수에 대한 초기화에 사용

class load → static initializer 실행 → main method 실행 → 초기화 block 실행 → constructor 호출


언제 static을 붙여야 할까?

  • 속성(멤버 변수) 중에 공통 속성에 static을 붙인다.
  • 인스턴스 멤버(iv(instance variable), im(instance method))를 사용하지 않는 메서드에 static을 붙인다.
class MyMath2{
	long a, b;
    
    long add(){
    	return a+b; //a, b는 인스턴스 변수
    }
    
    static long add(long a, long b){
    	return a+b; //a, b는 지역 변수
    }
}

Java 7과 8버전의 메타데이터 영역 비교

구분Java 7 (PermGen)Java 8 (Metaspace)
Class 메타 데이터저장저장
Method 메타 데이터저장저장
Static Object 변수, 상수저장Heap area로 이동
메모리 튜닝Heap, Perm 영역 튜닝(부족시)Heap 튜닝, Native 영역은 OS가 동적 조정
메모리 옵션-XX:PermSize
-XX:MaxPermSIze-XX:MetaspaceSize
-XX:MaxMetaspaceSize

Singleton Design Pattern

오직 하나의 company sigleton object를 client object가 사용하도록 하는 것이다.
싱글톤패턴 사용시 주의사항으로는 Thread-safe하게 개발해야 한다는 것이다.

public class Company{
	private static Company instance = new Company();
    private String name;
    
    //Company 인스턴스를 얻을 수 있는 유일한 메서드
    public static Company getInstance(){
    	return instance;
    }
    
    //생성자는 private 접근제어자로 선언하여 외부에서 객체 생섣을 차단
    private Company(){}
}

class CompanySingletonTest{
	public static void main(String[] args){
    	Company c = Company.getInstance();
    }
}

static import

  • static import로 import문을 선언하면 static member를 호출할 때 클래스명을 생략할 수 있으며, java 1.5버전부터 지원한다.
  • 사용 예)
    import static <pkg_list>.<class_name>.<member_name>;
    또는
    import static <pkg_list>.<class_name>.*;
import static java.lang.System.out;
import static java.lang.Math.*;

class StaticImportEx extends Object{
	public static void main(String[] args){
		//System.out.println(Math.random());
		out.println(random());

		//System.out.println("Math.PI :"+Math.PI);
		out.println("Math.PI :"+PI);
	}
}

변수 종류


인스턴스 변수(instance variable)

인스턴스를 생성할 때 생성되고, 참조 변수가 없을 때 가비지 컬렉터에 의해 자동 제거

인스턴스 변수는 생성 시점에 각 타입의 기본값(0, null …)으로 자동 초기화된다.

public class A{
	int instanceVariable; //인스턴스 변수

	static void main(String[] args){
		A a = new A();
		int b = a.instanceVariable; //b는 참조 변수
	}
}

클래스 변수(class variable) 또는 static variable

같은 클래스의 모든 인스턴스들이 공유하는 변수(public일 경우 모든 클래스에서 접근 가능)

클래스가 로딩될 때 생성되고 프로그램이 종료될 때 소멸

public class A{
	static int classVariable; //클래스 변수

	static void main(String[] args){
		int b = A.classVariable;
	}
}

지역 변수(local variable)

메서드 내에 선언되며, 메서드의 종료와 함께 소멸되고 사용 전에 꼭 초기화 해야 한다.

public int solution(int n){
	int answer = 0; //answer은 지역 변수
	return answer;
}
profile
웹퍼블리셔의 백엔드 개발자 도전기

0개의 댓글