tuter77

Java : 참조자료형 변수, 접근제어 지시자, 정보은닉 본문

JavaStudy

Java : 참조자료형 변수, 접근제어 지시자, 정보은닉

tuter77 2023. 1. 29. 19:37

  참조자료형 변수

 

▷ 참조자료형(reference Data type)

클래스형으로 변수를 선언하다.

기본자료형은 사용하는 메모리의 크기가 정해져 있지만, 참조 자료형은 클래스에 따라 다르다.

참조자료형을 사용할 때는 해당 변수에 대해 생성해야한다.*예외적으로 String 클래스는 생성하지않고 사용이 가능하다.대표적으로 String과 Class가 있다.

 

▷ 참조자료형 정의하여 사용하기

예시)학생(Student)과 학생과목(Subject) 점수에 대한 클래스 생성.

일반적으로 클래스를 생성하면, 학생클래스에 학생이 수강하는 과목과 그 점수를 같이 생성하는데, 학생이 수강한 과목들의 성적을 산출하기 위한경우라면, 학생클래스 속성에 과목이 모두 있으면 불합리하다.

왜냐하면 각각의 학생들이 수강한 과목이 다를것이고 과목수도 다를것이기 때문이다.

 

때문에 Student와 Subject에 대한 클래스를 분리하여 사용하고 Subject 클래스를 활용하여 수강한 과목들의 변수의 타입으로 선언한다.

 

예시)

- 과목 클래스

public class Subject {

String subjectName;

int score; //과목 점수를 과목 이름에 대한 변수로 선언.

int subjectID; //과목 아이디도 과목 이름에 대한 변수로 선언.

}

 

- 학생 클래스

public class Student {

 

int studentID;

String studentName;

 

Subject korea;//과목명을 앞에서 선언해주고 아래의 생성자를 통해 과목에 연결한다.

Subject math; //이렇게 해야 과목클래스에서 변수를 가져와 사용할 수 있다.

 

Student(int studentID, String studentName){ //학생id와 이름이 매개변수로 들어가는 생성자를 선언.

this.studentID = studentID;

this.studentName = studentName;

 

korea = new Subject(); 

math = new Subject();

 

}

public void setKoreaSubject(String name, int score) { //국어 변수에 학생이름과 점수를 입력해주기위한 메소드 선언.

 

korea.subjectName = name;

korea.score = score;

 

}

public void setMathSubject(String name, int score) {//영어 변수에 학생이름과 점수를 입력해주기위한 메소드선언.

 

math.subjectName = name;

math.score = score;

 

}

public void showScoreInfo() { //학생의 점수를 나타낼 메소드 선언.

 

int total = korea.score + math.score;

System.out.println(studentName + " 학생의 총점은 " + total + "점 입니다.");

}

 

}

 -앞의 클래스를 이용하는 테스트 클래스.

public class SubjectTest {

public static void main(String[] args) {

 

Student studentLee = new Student(100, "Lee"); //학생LEE 인스턴스 생성 및 과목과 점수 입력.

studentLee.setKoreaSubject("국어", 100);

studentLee.setMathSubject("수학", 90);

 

Student studentKim = new Student(100, "Kim");//학생KIM 인스턴스 생성 및 과목과 점수 입력.

studentKim.setKoreaSubject("국어", 85);

studentKim.setMathSubject("수학", 55);

 

studentLee.showScoreInfo(); //총점표기 메소드 호출.

studentKim.showScoreInfo();

}

}

 

위의 예시에서 살펴보듯, 과목과 학생의 클래스를 나누어주면 훨씬 효율적인 클래스 활용이 된다고한다.강의를 들으며, 이해가 안된것이 있는데, 클래스를 나누어주지 않으면 불합리한 클래스 구조가 된다는 말이다.이유에 대해 강사님은 이렇게 설명하셨다. 예시에서는 수학, 국어 두가지의 과목이 다지만 어떤 학생의 경우엔 10과목을 들을 수도 있다. 각 과목의 변수가 과목명과 점수 두가지만 있다고 하더라도 10개를 듣는 학생을 위해 새 클래스를 만든다. 이후 과목에대한 20개의 property를 넣게된다.그러나 이 10개의 과목 중 어떤 학생은 2과목만 듣고, 어떤학생은 10개를 다 듣기 때문에 구조가 불합리하다는 것이다.

 

다시봐도 여전히 이해가 가지않는다... 이 부분은 따로 찾아보고 내일 til에 올리겠다.

 

 접근 제어 지시자(access modifier)와 정보은닉(infomation hiding)

▷ 접근 제어 지시자.(access modifier)

- 클래스 외부에서 클래스의 멤버 변수, 메서드, 생성자를 사용할 수 있는지 여보를 지정하는 키워드.

- private: 같은 클래스 내부에서만 접근 가능(외부 클래스, 상속 관계의 클래스에서도 접근 불가.)

- 아무것도 없음(default) : 같은 패키지 내부에서만 접근 가능(상속 관계라도 패키지가 다르면 접근 불가. 다른 패키지의 경우 import를 사용. 예시로 java.util.Scanner)

- protected : 같은 패키지나 상속관계의 클래스에서 상위클래스의 속성을 하위클래스에서 접근 가능하고 그 외 외부에서는 접근할 수 없음.

- public : 클래스의 외부 어디서나 접근할 수 있음.

 

▷ get() / set() 메서드 (private으로 선언된 변수들을 외부에서 필요로 할때 사용)

- private 로 선언된 멤버 변수(필드)에 대한 접근, 수정할 수 있는 메서드를 public으로 제공.

- get() 메서드만 제공되는 경우 read-only 필드

- 이클립스에서 자동으로 생성됨. (우클릭 > source > general getter/setter에서 자동생성가능)

- 데이터의 오용을 막기위해 private 사용.

- 디버깅도 수월하다 > 사용하는 곳(메서드)에서 잘못된 내용을 확인하면 된다. 

 

예시) 

public class BirthDay {

 

private int day;

private int month;

private int year;

 

//생일에 적합한지에 대한 프로그램.

private boolean isValid; //디폴트 값 false

 

public int getday() {

return day;

}

 

public void setDay(int day) {

this.day = day;

}

 

public int getMonth() {

return month;

}

public void setMonth(int month) {

if(month < 1 || month > 12) {

 

isValid = false; // 값이 유요한지 확인.

}

else {

 

isValid = true;

this.month = month;

}

}

 

위와 같이 클래스 내에서 private 를 적용하여 정보를 숨기고 숨긴정보가 필요한 경우에  get/set을 활용할 수 있다.

public class BirthDayTest {

public static void main(String[] args) {

BirthDay date = new BirthDay();

 

date.setYear(2019);

date.setMonth(12);

date.setDay(30);

 

//date.month = 100; 프라이빗에서 이런 오류를 막아줌.

 

date.showDate();

System.out.println(date.getIsValid());

}

 

주석 처리된 부분처럼 잘못된 데이터값이 쉽게 저장되는것을 막기위해 private를 활용한다.

 

▷ 정보 은닉

위의 private 과정을 통해 정보은닉을 사용할 수 있다.

 

 

 캡슐화(encapsulation)

 

▷정보 은닉을 활용한 캡슐화

- 꼭 필요한 정보와 기능만 외부에 오픈한다.

- 대부분의 멤버변수와 메서드를 감추고 외부에 통합된 인터페이스만은 제공하여 일관된 기능을 구현하게 한다.

- 각각의 메서드나 멤버변수를 접근함으로써 발생하는 오류를 최소화 한다.

 

*StringBuffer / StringBuilder Class : 스트링을 append 메서드를 사용하여 쭉 연결하는 클래스.

 

● This(객체 자신을 가리키는)

- 인스턴스 자신의 메모리를 가리킨다.

- 생성자에서 또 다른 생성자를 호출할 때 사용한다.

- 자신의 주소(참조값)을 반환한다.

 

생성된 인스턴스 메모리의 주소를 가진다는건, 클래스 내에서 참조변수가 가지는 주소값과 동일한 주소값을 가지는 키워드라는 것이다.

 

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

- 클래스에 생성자가 여러개인 경우, this를 이용하여 생성자에서 다른 생성자를 호출할 수 있다.

- 생성자에서 다른 생성자를 호출하는 경우, 인스턴스의 생성이 완전하지 않은 상태이므로, this() statement 이전에 다른 statement를 쓸 수 없다.

 

예시) 

String name;

int age;

 

public Person(){

//이 상태에서는 인스턴스의 생성이 완전하지 않은 상태라, 다른 코드를 이 위에 집어넣으면 오류가 발생한다.

             this("이름없음", 1);  // 이 뒤에 쓰는건 상관 없다.

}

 

다른 예시)

 

public Person getPerson() {//반환타입은 자기자신.

return this;//this를 해주면 어떻게 반환될까? 패키지가 포함된 클래스네임과, 인스턴스의 어드레스가 출력된다.

}

예시를 통해 알아본 결과 this와 person은 같은 메모리에서 값을 출력함을 알 수 있었다.

ch12.Person@7a81197d // this로 출력한 결과.

ch12.Person@7a81197d //person으로 출력한 결과.

 

생성자 이후부터는 이해가 안되는 내용이 조금씩 추가되고 있다. 인스턴스를 생성할 때 사용하는 new생성자. 오늘 배운 클래스의 구조가 불합리하기 때문에 참조자료형을 이용하는 내용 등.

점점 어려워지고 있는게 느껴진다.. 분발해야지.

 

위 내용은 2022.12.23에 공부한 내용입니다.

링크 : https://dudwls3278.tistory.com/23