클래스와 객체2

Minji Lee·2025년 3월 19일
0

JAVA

목록 보기
9/13

this 예약어

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

package thisex;

class BirthDay {
    int day;
    int month;
    int year;

    public void setYear(int year){
        this.year = year; // 태어난 연도를 지정하는 메서드
    }
    public void printThis(){
        System.out.println(this); // this 출력 메서드
    }
}

public class ThisExample {
    public static void main(String[] args){
        BirthDay bDay = new BirthDay();
        bDay.setYear(2000); // 태어난 연도를 2000으로 지정
        System.out.println(bDay); // 참조변수출력 thisex.BirthDay@7a81197d
        bDay.printThis(); // this 출력 메서드 호출 thisex.BirthDay@7a81197d
    }
}

생성자에서 다른 생성자 호출하는 this

package thisex;

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 ThisExample {
    public static void main(String[] args){
        Person noName = new Person();
        System.out.println(noName.name); // 이름 없음
        System.out.println(noName.age); // 1 
    }
}
  • Person 클래스 내에 디폴트 생성자와 Person(String, int) 생성자 존재
  • 디폴트 생성자가 호출되는 경우에는 초깃값으로 "이름 없음"과 1 대입
  • 디폴트 생성자 코드 안에 직접 써도 되지만, 이미 다른 생성자에 작성되어 있으므로 this 활용해서 다른 생성자 호출
  • 주의점! this를 이용해 생성자 호출할 때 this 활용한 문장이 가장 먼저 와야함!
Person() {
	this.name = "noname"; 
	this("이름 없음", 1); // 에러 발생
}
Person() {
	this("이름 없음", 1); // this 먼저 작성
    this.name = "noname";
}

자신의 주소 반환하는 this

생성된 클래스 자신의 주소 값을 반환할 수 있음

  • 인스턴스 주소값을 반환할 때는 this를 사용하고, 반환형은 클래스 자료형 사용
클래스형 메서드명() {
	return this; // this 반환
}
package thisex;

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 ThisExample {
    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();
        System.out.println(p); // thisex.Person@7a81197d
        System.out.println(noName); // thisex.Person@7a81197d
    }
}

객체 간 협력

ex) 학생이 학교에 가기 위해 버스나 지하철 타고 갈 수 있을 때 학생, 버스, 지하철 세 객체 만들고 협력 확인

학생 클래스 구현

package cooperation;

public class Student {
    public String studentName; // 학생 이름
    public int grade; // 학년
    public int money; // 학생이 가지고 있는 돈
    
    // 학생 이름과 가진 돈을 매개변수로 받는 생성자
    public Student(String studentName, int money){
        this.studentName = studentName;
        this.money = money;
    }
    
    public void takeBus(Bus bus){
        bus.take(1000); // 학생이 버스를 타면 1000원 지불
        this.money -= 1000;
    }
    
    public void takeSubway(Subway subway){
        subway.take(1500); // 학생이 지하철 타면 1500원 지불
        this.money -= 1500;
    }
    
    public void showInfo(){
        System.out.println(studentName+"님의 남은 돈은"+money+"입니다.");
    }
}

버스 클래스 구현

package cooperation;

public class Bus {
    int busNumber; // 버스 번호
    int passengerCount; // 승객 수
    int money; // 버스 수입
    
    public Bus(int busNumber){
        this.busNumber = busNumber; // 버스 번호를 매개변수로 받는 생성자
    }
    
    public void take(int money){
        this.money += money; // 버스 수입 증가
        passengerCount++;
    }
    
    public void showInfo(){
        System.out.println("버스 "+busNumber+"번의 승객은 "+passengerCount+"명이고, 수입은 "+money+"입니다.");
    }
}

지하철 클래스 구현

package cooperation;

public class Subway {
    String lineNumber; // 지하철 노선
    int passengerCount; // 승객 수
    int money; // 수입액

    public Subway(String lineNumber){
        this.lineNumber = lineNumber; // 지하철 노선 번호를 매개변수로 받는 생성자
    }

    public void take(int money){
        this.money += money; // 수입 증가
        passengerCount++;
    }

    public void showInfo(){
        System.out.println(lineNumber+"의 승객은 "+passengerCount+"명이고, 수입은 "+money+"입니다.");
    }
}

버스와 지하철 타기

package cooperation;

public class TakeTrans {
    public static void main(String[] args){
        Student student1 = new Student("James", 5000);
        Student student2 = new Student("Tomas", 10000);

        Bus bus100 = new Bus(100); // 노선 번호가 100번인 버스 생성
        student1.takeBus(bus100); // James가 100번 버스를 탐
        student1.showInfo(); // james 정보 출력 James님의 남은 돈은4000입니다.
        bus100.showInfo(); // 버스 정보 출력 버스 100번의 승객은 1명이고, 수입은 1000입니다.

        Subway subwayGreen = new Subway("2호선"); // 노선 번호가 2호선인 지하철 생성
        student2.takeSubway(subwayGreen); // Tomas 가 2호선 탐
        student2.showInfo(); // Tomas 정보 출력 Tomas님의 남은 돈은8500입니다.
        subwayGreen.showInfo(); // 지하철 정보 출력 2호선의 승객은 1명이고, 수입은 1500입니다.
    }
}

static 변수

static 변수(=정적 변수=클래스 변수)는 클래스에서 공통으로 사용하는 변수
static 자료형 변수이름;

  • static 변수는 클래스 내부에 선언하지만, 다른 멤버 변수처럼 인스턴스가 생성될 때마다 새로 생성되는 변수는 X
  • static 변수는 프로그램이 실행되어 메모리에 올라갔을 때 딱 한 번 메모리 공간이 할당되고, 그 값은 모든 인스턴스가 공유
  • 즉, 일반 멤버 변수는 인스턴스가 생성될 때마다 새로 생성되어 각각 다른 주소를 가지지만, static으로 선언한 변수는 인스턴스 생성과 상관없이 먼저 생성되고 그 값을 모든 인스턴스가 공유
package staticex;

public class Student {
    public static int serialNum = 1000; // 인스턴스 생성과 상관없이 먼저 생성
    public int studentID;
    public String studentName;
    public int grade;
    public String address;

    public String getStudentName(){
        return studentName;
    }

    public void setStudentName(String name){
        studentName = name;
    }
}
package staticex;

public class StudentTest1 {
    public static void main(String[] args){
        Student student1 = new Student();
        student1.setStudentName("홍길동");
        System.out.println(student1.serialNum); // 1000
        student1.serialNum++;

        Student student2 = new Student();
        student2.setStudentName("신짱구");
        System.out.println(student2.serialNum); // 1001
        System.out.println(student1.serialNum); // 1001
    }
}

학번 자동 부여하기

package staticex;

public class Student {
    public static int serialNum = 1000;
    public int studentID;
    public String studentName;
    public int grade;
    public String address;
    
    public Student(){
        serialNum++; // 학생 생성될 때마다 증가
        studentID = serialNum; // 증가된 값을 학번 인스턴스 변수에 부여
    }

    public String getStudentName(){
        return studentName;
    }

    public void setStudentName(String name){
        studentName = name;
    }
}
package staticex;

public class StudentTest1 {
    public static void main(String[] args){
        Student student1 = new Student();
        student1.setStudentName("홍길동"); // 1001
        System.out.println(student1.serialNum);
        System.out.println(student1.studentName+" 학번:"+student1.studentID); // 홍길동 학번:1001

        Student student2 = new Student();
        student2.setStudentName("신짱구");
        System.out.println(student2.serialNum); // 1002
        System.out.println(student2.studentName+" 학번:"+student2.studentID); // 신짱구 학번:1002
    }
}

❗️static 변수는 인스턴스가 아닌 클래스 이름으로 참조하여 사용 가능

  • static 변수는 인스턴스 생성이 아닌 클래스 선언할 때 특정 메모리에 저장되므로
package staticex;

public class StudentTest1 {
    public static void main(String[] args){
        Student student1 = new Student();
        student1.setStudentName("홍길동"); // 1001
        System.out.println(Student.serialNum);
        System.out.println(student1.studentName+" 학번:"+student1.studentID); // 홍길동 학번:1001

        Student student2 = new Student();
        student2.setStudentName("신짱구");
        System.out.println(Student.serialNum); // 1002
        System.out.println(student2.studentName+" 학번:"+student2.studentID); // 신짱구 학번:1002
    }
}

static 메서드 = 클래스 메서드

package staticex;

public class Student {
    private static int serialNum = 1000;
    public int studentID;
    public String studentName;
    public int grade;
    public String address;

    public Student(){
        serialNum++; // 학생 생성될 때마다 증가
        studentID = serialNum; // 증가된 값을 학번 인스턴스 변수에 부여
    }

    public String getStudentName(){
        return studentName;
    }

    public void setStudentName(String name){
        studentName = name;
    }
    
    public static int getSerialNum(){
        int i = 10;
        return serialNum;
    }
    
    public static void setSerialNum(int serialNum){
        Student.serialNum = serialNum;
    }
}
package staticex;

public class StudentTest1 {
    public static void main(String[] args){
        Student student1 = new Student();
        student1.setStudentName("홍길동"); // 1001
        System.out.println(Student.getSerialNum());
        System.out.println(student1.studentName+" 학번:"+student1.studentID); // 홍길동 학번:1001

        Student student2 = new Student();
        student2.setStudentName("신짱구");
        System.out.println(Student.getSerialNum()); // 1002
        System.out.println(student2.studentName+" 학번:"+student2.studentID); // 신짱구 학번:1002
    }
}

클래스 메서드와 인스턴스 변수

  • 클래스 메서드 내부에서는 인스턴스 변수 사용 X
  • 반대로 일반 메서드에서 클래스 변수 사용하는 건 상관 없음!
public static int getSerialNum(){
	int i = 10; // i는 지역변수로 메서드가 호출될 때 메모리에 생성되고, 메서드가 끝나면 사라짐
	studentName = "김철수"; // 오류 발생
	return serialNum;
}

변수 유효 범위

지역변수 유효 범위

지역변수는 함수나 메서드 내부에 선언하기 때문에 함수 밖에서는 사용 X

  • 하나의 함수에 선언한 지역 변수는 다른 함수에서 사용 X
  • 지역 변수가 생성되는 메모리를 스택(stack)이라고 함
  • 스택에 생성되는 지역 변수는 함수가 호출될 때 생성되었다가 함수가 반환되면 할당되었던 메모리 공간이 해제되면서 함께 없어짐

멤버 변수 유효범위

멤버 변수는 인스턴스 변수라고도 함

  • 클래스가 생성될 때 힙(heap) 메모리에 생성</span<되는 변수
  • 클래스의 어느 메서드에서나 사용할 수 있음
  • 힙에 생성된 인스턴스가 가비지 컬렉터에 의해 수거되면 메모리에서 사라짐

static 변수 유효범위

  • 사용자가 프로그램을 실행하면 메모리에 프로그램이 상주함. 이때 프로그램 영역 중 데이터 영역 존재
  • 데이터 영역에 상수나 문자열, static 변수 생성됨
  • private가 아니면 클래스 외부에서도 객체 생성과 무관하게 사용 가능
  • 프로그램 실행이 끝난 뒤 메모리에서 내려가면 static 변수도 소멸됨
  • static 변수는 프로그램 시작할 때부터 끝날 때까지 메모리에 상주하므로 크기가 너무 큰 변수는 static으로 선언하는 것은 좋지 않음!

static 응용 - 싱글톤 패턴

싱글톤 패턴
인스턴스를 단 하나만 생성하는 디자인 패턴

ex) 한 회사에 직원이 여러 명인 경우 회사 클래스 생성하기

package singleton;

public class Company {
    private static Company instance = new Company(); // 유일하게 생성한 인스턴스
    private Company() {}
    
    public static Company getInstance(){
        if(instance == null){
            instance = new Company();
        }
        return instance; // 유일하게 생성한 인스턴스 반환
    }
}
package singleton;

public class CompanyTest {
    public static void main(String[] args){
        Company myCompany1 = Company.getInstance();
        Company myCompany2 = Company.getInstance();
        System.out.println(myCompany1 == myCompany2); // true
    }
}

0개의 댓글