본문 바로가기

Developer/JAVA

[JAVA] 클래스와 객체2

<this 예약어>

인스턴스 스스로를 가리키는 예약어

 

class BirthDay{
  int day;
  int month;
  int year;
  
  public void setYear(int year) {
    this.year = year;
  }
  
  public void printThis(){
    System.out.println(this);
  }
}

public class ThisExample{
  public static void main(String[] args){
    BirthDay bDay = new BirthDay();
    bDay.setYear(2000);  // 2000년 탄생
    
    // 참조 변수를 출력하면 클래스이름@메모리주소
    System.out.prinln(bDay);  // 참조 변수 출력
    bDay.printThis();  // this 출력 메서드 호출
  }
}

참조 변수와 this 출력 메소드 호출한 클래스이름@메모리주소 값이 동일하다.

클래스 코드에서 사용하는 this는 생성된 인스턴스 자신을 가리키는 역할을 한다.

class Person{
  String name;
  int age;
  
  Person(){
    this("이름 없음", 1); // this를 사용해 Person(String,int) 생성자 호출
  }
  
  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
}

public class CallAnotherConst{
  public static void main(String[] args){
    Person noName = new Person();
    System.out.println(noName.name); // 이름 없음
    System.out.println(noName.age); // 1
  }
}

this 로 다른 생성자를 호출할 때, 호출하는 코드 이전에 다른 코드 넣으면 안된다.

생성자는 클래스가 생성될 때 호출되므로 클래스 생성이 완료되지 않은 시점에 다른 코드가 있다면 오류 발생

this를 활용한 문장이 가장 먼저 와야한다.

 

class Person{
  String name;
  int age;
  
  Person(){
    this("이름 없음", 1); // this를 사용해 Person(String,int) 생성자 호출
  }
  
  Person(String name, int age) {
    this.name = name;
    this.age = age;
  }
  
  Person returnItSelf() { // 반환형은 클래스형
    return this; // this 반환
  }
}

public class CallAnotherConst{
  public static void main(String[] args){
    Person noName = new Person();
    System.out.println(noName.name); // 이름 없음
    System.out.println(noName.age); // 1
    
    Person p = noName.returnItSelf(); // this 값을 클래스 변수에 대입
    
    // 클래스이름@메모리주소 출력
    System.out.println(p);  // noName.returnItSelf()의 반환 값 출력
    System.out.println(noName);  // 참조 변수 출력
  }
}

this를 반환하는 메서드를 사용할 일이 흔하지는 않지만, 클래스 자료형과 상관없이 클래스 내에서 this를 사용하면 자신의 주소 값을 반환 가능

 

<static 변수>

static 변수 == 정적변수

  • static 변수는 클래스 내부에 선언하지만, 다른 멤버 변수처럼 인스턴스가 생성될 때마다 새로 생성되는 변수는 아니다.
  • static 변수는 프로그램이 실행되어 메모리에 올라갔을 때 한 번만 메모리 공간이 할당된다.
  • 모든 인스턴스가 공유한다.
  • static 변수는 인스턴스보다 먼저 생성된다.
  • static 변수는 클래스 이름으로 직접 참조한다.
    • System.out.println(Student.serialNum);
public class Student{
  public static int serialNum = 1000;  // static 변수
  public int studentID;
  public String studentName;
  public int grade;
  public String address;
  
  public String getStudentName(){
    return studentName;
  }
  
  public void setStudentName(String name){
    studentName = name;
  }
}


public class StudentTest1{
  public static void main(String[] args){
    Student studentA = new Student();
    studentA.setStudentName("Alice");
    System.out.println(studentA.serialNum); // 1000
    studentA.serialNum++; // static 변수 증가
    
    Student studentBob = new Student();
    studentBob.setStudentName("Bob");
    System.out.println(studentBob.serialNum); // 1001
    System.out.println(studentA.serialNum);  // 1001
  }
}

 

<클래스 메서드>

public class Student2{
  private static int serialNum = 1000;
  int studentID;
  String studentName;
  int grade;
  String address;
  
  public Student2(){
    serialNum++;
    studentID = serialNum;
  }
  
  public String getStudentName(){
    return studentName;
  }
  
  public void setStudentname(String name){
    studentName = name;
  }
  
  public static int getSerialNum(){
    int i = 10;  // 메서드 내부에서 선언했기 때문에, 메서드가 호출될 때 메모리에 생성되어 메서드가 끝나면 사라지는 변수
    studentName = "Alice";  // 오류 발생 : Student2 클래스의 멤버변수로, 인스턴스가 생성될 때 만들어지는 인스턴스 변수를 사용할 수 없다.
    return serialNum;
  }
  
  public static void setSerialNum(int serialNum){
    Student2.serialNum = serialNum;
  }
}


public class StudentTest2{
  public static void main(String[] args){
    Student2 studentA = new Student2();
    studentA.setStudentName("Alice");
    System.out.println(Student2.getSerialNum()); // 1001
    System.out.println(studentA.studentName + studentLee.studentID); // Alice 1001
    
    Student2 studentB = new Student2();
    studentB.setStudentName("Bob");
    System.out.println(Student2.getSerialNum()); // 1002
    System.out.println(studentB.studentName + studentB.studentID); // Bob 1002
  }
}
  • 클래스 내부에서는 인스턴스 변수 사용 불가
  • 클래스 메서드 내부에서 지역 변수와 클래스 변수는 사용할 수 있지만, 인스턴스 변수는 사용할 수 없다.
  • 클래스 메서드에서 인스턴스 변수를 사용할 수는 없지만, 일반 메서드에서 클래스 변수를 사용할 수는 있다.
    • 일반 메서드는 인스턴스가 생성될 때 호출되는 메서드이고, 클래스 변수는 이미 만들어진 변수이기 때문에 일반 메서드에서도 클래스 변수 호출 가능

 

<변수 유효 범위>

지역 변수(로컬 변수, local variable) : 함수나 메서드 안에서만 사용 가능

  • 함수나 메서드 내부에 선언하기 때문에 함수 밖에서 사용 불가
  • 하나의 함수에 선언한 지역 변수는 다른 함수에서 사용 불가
  • 지역변수가 생성되는 메모리 : 스택 (stack)

멤버 변수(인스턴스 변수, instance variable) : 클래스 안에서 사용 가능

  • 클래스가 생성될 때 힙(heap) 메모리에 생성되는 변수
  • 힙에 생성된 인스턴스가 가비지 컬렉터에 의해 수거되면 메모리에서 사라짐

static 변수(클래스 변수, class variable) : 여러 인스턴스에서 공통으로 사용 가능

  • 인스턴스 변수는 객체가 생성되는 문장 즉 new가 되어야 생성되지만, static 변수는 클래스 생성과 상관없이 처음부터 데이터 영역 메모리에 생성
  • 인스턴스 변수와 static 변수는 사용하는 메모리가 다름
변수 유형 선언 위치 사용 범위 메모리 생성과 소멸
지역 변수
(로컬 변수)
함수 내부에 선언 함수 내부에서만 사용 스택 함수가 호출될 때 생성되고 함수가 끝나면 소멸
멤버 변수
(인스턴스 변수)
클래스 멤버 변수로 선언 클래스 내무에서 사용하고 private이 아니면 참조 변수로 다른 클래스에서 사용 가능 인스턴스가 생성될 때 힙에 생성되고, 가비지 컬렉터가 메모리를 수거할 때 소멸
static 변수
(클래스 변수)
static 예약어를 사용하여 클래스 내부에 선언 클래스 내부에서 사용하고 private이 아니면 클래스 이름으로 다른 클래스에서 사용 가능 데이터 영역 프로그램이 처음 시작할 때 상수와 함께 데이터 영역에 생성되고 프로그램이 끝나고 메모리를 해제할 때 소멸

 

<static 응용 - 싱글톤 패턴>

싱글톤 패턴(singleton pattern) : 객체 지향 프로그램에서 인스턴스를 하나만 생성하는 디자인 패턴

 

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

[JAVA] 배열과 ArrayList  (0) 2021.07.08
[JAVA] 클래스와 객체1  (0) 2021.06.14
[JAVA] 조건문, 반복문 (if, for)  (0) 2021.05.17
JAVA 변수 선언하기  (0) 2021.05.14