-----------------------------------------
제어자(Modifier)
1. 제어자는 외부에서 멤버의 접근을 제한하는 접근 제어자와 멤버의 상태를 제한하는 제어자가 있다.
2. 접근 제어자 종류
- private : 같은 클래스 내부에서만 접근 가능
- (default) : 접근지정자 표기하지 않은 경우. 같은 패키지 내부에서만 접근 가능
- protected : 상위 클래스에서 protected 접근 지정자를 지정한 멤버는 하위 클래스에서만 접근 가능. 단, 같은 패키지에서도 접근 가능.
- public : 모든 경우에서 접근 가능
private 생성자 테스트
//Sample39.java
package com.test;
//private 생성자를 가진 클래스는
//상속하는 과정에서 super() 생성자 호출이 안되므로
//상속 불가 클래스로 만드는 것이 좋다.
//-> final 키워드
public final class Sample39 {
//private 접근 제어자를 가진 생성자 지정
private Sample39() {
System.out.println("Sample39 클래스의 생성자 호출!");
}
//생성자가 private이므로 인스턴스 멤버는 접근 불가.
//-> 모든 멤버는 static 상태가 되어야 한다.
public static void method() {
System.out.println("Sample39 클래스의 메소드 호출");
}
}
//SubSample39.java
package com.test;
//private 생성자를 가진 클래스는 상속이 불가능하므로
//상속이 불가능한 클래스임을 알려주는 것이 좋다.
//-> final 키워드
public class SubSample39 extends Sample39 {
//SubSample39의 기본생성자는 Sample39의 생성자(super 생성자)를 필요로 한다.
//생략된 멤버? -> 기본 생성자
public SubSample39() {
//생략된 구문? -> super();
super(); //->private 생성자는 접근 불가
}
}
//Main.java
package com.test;
public class Main {
public static void main(String[] args) {
//객체 생성 -> 생성자 호출 -> 생성자의 접근제어자가 private 상태임.
//객체 생성이 되지 않으면 인스턴스 멤버 접근도 할 수 없다.
//인스턴스 멤버 사용할 수 없다는 의미.
//인스턴스 멤버가 전혀 없는 상태라는 의미.
//-> 객체 생성 과정 불필요.
//-> 생성자 호출 차단
//-> private 접근 제어자 지정
//Sample39 s39 = new Sample39();
//s39.method();
Sample39.method();
}
}
//PrivateFinalTest.java
package com.test;
//private 생성자가 포함된 클래스를 상속 받는 경우
//상속 받은 클래스가 객체 생성하는 과정에서
//super() 생성자 호출 부분이 실행되지 않는다.
//-> final 클래스 지정 필요
public final class PrivateFinalTest {
//추가 객체가 만들어지지 않도록 하기 위한 멤버 변수 추가
private static PrivateFinalTest obj;
//private 생성자 추가
private PrivateFinalTest() {
}
//객체 생성을 위한 전용 메소드 추가
//싱글톤 디자인패턴
public static PrivateFinalTest getInstance() {
if (obj == null) {
obj = new PrivateFinalTest();
}
return obj;
}
//현재 클래스 내부에 모든 메소드가 static 상태인 경우
//현재 클래스에 대한 객체 생성 과정이 필요 없는 경우가 있다.
//-> private 생성자
//-> 객체 생성 불가
public static void method() {
}
}
//SubClass.java
package com.test;
public class SubClass extends PrivateFinalTest {
}
//Main.java
package com.test;
public class Main {
public static void main(String[] args) {
//private 생성자이므로 객체 생성 불가
//PrivateFinalTest test = new PrivateFinalTest();
//static 멤버는 접근 가능
PrivateFinalTest.method();
//getInstance() 메소드를 이용한 객체 획득
//객체가 추가로 만들어지지 않도록 하는 것이 목적
PrivateFinalTest test2 = PrivateFinalTest.getInstance();
System.out.println(test2.toString());
PrivateFinalTest test3 = PrivateFinalTest.getInstance();
System.out.println(test3.toString());
}
}
---------------------------------------------
싱글톤 기법
//Singleton01.java
package com.test;
public class Singleton01 {
//일반적으로 클래스의 객체 생성을 위해서
//생성자를 추가한다.
//기본생성자->자동 추가
//생성자 역할 -> 멤버변수 초기화
//생성자 호출 -> new 연산자를 이용한 객체 생성시
public Singleton01() {
}
}
//Singleton02.java
package com.test;
public final class Singleton02 {
//객체 생성 과정을 위한 전용 메소드 추가
//한 개의 객체만 생성되도록 제한
//-> Singleton
//-> private 생성자 준비
//-> 객체 제공 전용 메소드 준비
//private 생성자
//-> 사용자가 클래스의 객체를 직접 생성 불가능
private Singleton02() {
}
//객체 제공 전용 (인스턴스)메소드
/*
public Singleton02 getInstance() {
return new Singleton02();
}
*/
//객체 제공 전용 (스태틱)메소드
//-> new 연산자 제한이 없는 상태라서 객체가 여러개 생성될 수 있다.
/*
public static Singleton02 getInstance() {
return new Singleton02();
}
*/
//객체 제공 전용 (스태틱)메소드
//-> new 연산자 제한
//-> 한 개의 객체만 제공
//-> Singleton 기법
private static Singleton02 obj; //null
public static Singleton02 getInstance() {
//현재 메소드를 최초 호출시
//if문을 만족하고 객체 생성 과정 실행
//객체의 참조 주소를 obj 변수에 저장
//다음에 호출되는 경우는
//obj 변수에 이미 객체의 참조 주소가 저장된 상태이므로
//if문 실행 없이 기존의 값 반환
if (obj == null) {
obj = new Singleton02();
}
return obj;
}
}
//Main.java
package com.test;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
//일반적인 객체 생성 과정
Singleton01 singleton01 = new Singleton01();
//toString() -> Object 클래스
//객체 정보(패키지이름.클래스이름@해쉬코드) 출력
System.out.println(singleton01.toString());
//같은 자료형을 가진 다른 객체 생성 -> new 연산자
Singleton01 singleton02 = new Singleton01();
//해쉬코드가 다른 경우 다른 객체이다.
System.out.println(singleton02.toString());
//클래스의 객체를 한 개만 생성되도록 하려면?
//-> new 연산자 사용 제한
//-> private 생성자 준비
//-> 객체 제공 전용 메소드 호출
//-> ?
//Singleton02 singleton03 = new Singleton02(); //X
//-> 객체 제공 전용 메소드 호출 -> 인스턴스 -> 호출 불가능
//singleton03.getInstance(); //X
//-> 객체 제공 전용 메소드 호출 -> 스태틱 -> 호출 가능
/*
Singleton02 singleton03 = Singleton02.getInstance(); //O
System.out.println(singleton03.toString());
*/
//같은 자료형을 가진 다른 객체 생성 -> new 연산자
/*
Singleton02 singleton04 = Singleton02.getInstance(); //O
System.out.println(singleton04.toString());
*/
//Singleton 기법이 적용된 메소드 호출
Singleton02 singleton05 = Singleton02.getInstance(); //O
System.out.println(singleton05.toString());
//같은 자료형을 가진 같은 객체
Singleton02 singleton06 = Singleton02.getInstance(); //O
System.out.println(singleton06.toString());
//new 연산자 제한
//Calendar cal0 = new Calendar(); //X
//객체 제공 메소드 호출
Calendar cal1 = Calendar.getInstance();
System.out.println(cal1.toString());
Calendar cal2 = Calendar.getInstance();
System.out.println(cal2.toString());
}
}
---------------------------------------------
//GetSet.java
package com.test;
public class GetSet {
//default 접근제어자를 지정한 멤버변수
//외부에서 멤버변수를 직접 접근 가능한 상태
//멤버변수에 저장될 데이터에 대한 검증과정 추가 불가능
//내부적으로 kor, eng, mat는 0~100 사이의 점수만 취급 예정.
//int kor, eng, mat;
//내부적인 기준을 검사하는 과정을 추가하기 위해서
//외부에서 직접 접근 불가능하도록 설정
private int kor, eng, mat;
//내부적인 기준을 검사하는 과정을 추가하기 위해서
//멤버변수만을 위한 getter, setter 메소드 추가
public void setKor(int kor) {
if (kor>=0 && kor<=100) {
this.kor = kor;
} else {
System.out.println("범위(0~100)를 벗어나는 데이터입니다.");
}
}
public void setEng(int eng) {
if (eng>=0 && eng<=100) {
this.eng = eng;
} else {
System.out.println("범위(0~100)를 벗어나는 데이터입니다.");
}
}
public void setMat(int mat) {
if (mat>=0 && mat<=100) {
this.mat = mat;
} else {
System.out.println("범위(0~100)를 벗어나는 데이터입니다.");
}
}
public int total() {
return kor + eng + mat;
}
}
//GetSetTest.java
package com.test;
public class GetSetTest {
public static void main(String[] args) {
GetSet test = new GetSet();
//외부에서 직접 멤버변수에 접근해서 데이터 저장 가능
//외부에서 내부적인 기준을 알 수 없기 때문에
//무작위의 데이터 입력 가능
/*
test.kor = 200;
test.eng = 100;
test.mat = 100;
*/
//getter, setter 등록을 하면
//setter() 메소드를 이용해서
//데이터 입력 처리
//내부적인 기준을 만족하는 데이터만 입력 가능
test.setKor(200);
test.setEng(100);
test.setMat(100);
System.out.println(test.total());
}
}
3. 멤버의 상태를 제한하는 제어자
- static : 멤버의 상태를 static 상태로 지정
- final : 멤버의 상태를 최종 상태로 지정. 변형 불가.
- abstract : 멤버의 상태를 추상으로 지정. 구현 불가.
//Sample40.java
package com.test;
//클래스에 final 키워드 사용시 상속 불가
public final class Sample40 {
}
//SubSample40.java
package com.test;
//클래스에 final 키워드 사용시 상속 불가
public class SubSample40 extends Sample40 {
}
//Sample41.java
package com.test;
public class Sample41 {
//멤버에 final 키워드 사용시 오버라이딩 금지
public final void method1() {
System.out.println("final 키워드가 있는 메소드!");
}
public void method2() {
System.out.println("final 키워드가 있는 메소드!");
}
}
//SubSample41.java
package com.test;
public class SubSample41 extends Sample41 {
//멤버에 final 키워드 사용시 오버라이딩 금지
@Override
public void method1() {
}
@Override
public void method2() {
}
}
//Sample42.java
package com.test;
public class Sample42 {
//멤버변수(field)에 final 키워드 사용한 경우는
//변수의 값(초기값)에 대한 변형 불가
//초기값 지정 방법 -> 초기화 구문, 초기화 블럭, 생성자
private final int a = 10;
private final int b;
public Sample42() {
this.b = 20;
}
public Sample42(int b) {
this.b = b;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
//final 키워드가 지정된 멤버변수에
//초기화 과정 이후의 대입문 사용은 불가
public void setA(int a) {
this.a = a;
}
public void setB(int b) {
this.b = b;
}
}
----------------------------------------------
상수
- 정해진 값을 변경하지 않고 그대로 사용하는 수.
- static final
- 상수명은 대문자로 표기
public static final int MAX_VALUE = 0x7fffffff;
public class 클래스 {
public static final 자료형 상수명 = 값;
}
-------------------------------------------------
과제)외부에서 데이터(이름, 전화번호)를 입력 받아서 메모리에 저장하고 출력, 검색할 수 있는 회원 입력, 출력 프로그램 작성.
회원 저장용 저장소(배열) 생성시 회원의 수는 사용자가 결정.
실행 예)
---- 회원관리 ----
1. 회원 입력
2. 회원 전체 출력
3. 회원 검색(이름 기준)
선택(1~3, 0 종료)?
//Student.java -> 회원 한 명분의 정보 저장용 클래스. 이름, 전화번호 항목으로 구성.
//MenuAction.java -> 메뉴 액션 클래스. 최초 입력시 회원 n명까지 저장할 수 있는 배열 생성. 배열의 자료형은 Student 클래스로 지정.
//Main.java -> 메뉴 출력
//Student.java
package com.sist;
public class Student {
private String name, tel;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
//toString() 메소드 오버라이딩 구현
//멤버변수의 데이터를 출력하는 용도로 변경
@Override
public String toString() {
return String.format("%s %s"
, this.getName()
, this.getTel());
}
//문제) equals() 메소드 오버라이딩
//equals()는 Object 클래스의 메소드
//equals()는 원래 객체의 참조주소를 비교하는 기능이지만
//객체의 멤버(name)을 비교하도록 변경
@Override
public boolean equals(Object obj) {
//원본 -> this.name
//비교 대상 -> obj.getName(); //X
//비교 대상 -> ((Student)obj).getName(); //O
//비교 방법 -> 같은지, 다른지 ? -> true or false -> 비교 대상의 자료형 -> String -> equals() 메소드 -> 문자열 비교
return this.name.equals(((Student)obj).getName());
}
}
//MenuAction.java
package com.sist;
import java.util.Scanner;
public class MenuAction {
//학생 정보 저장용 배열 준비->데이터 저장소
private Student[] students;
public MenuAction() {
//배열 생성 및 초기화
students = new Student[5];
this.init();
}
private void init() {
Student student0 = new Student();
student0.setName("hong");
student0.setTel("010-123-1234");
students[0] = student0;
Student student1 = new Student();
student1.setName("kim");
student1.setTel("010-432-4321");
students[1] = student1;
Student student2 = new Student();
student2.setName("park");
student2.setTel("010-987-9876");
students[2] = student2;
Student student3 = new Student();
student3.setName("choi");
student3.setTel("010-567-5678");
students[3] = student3;
/*
Student student4 = new Student();
student4.setName("hwang");
student4.setTel("010-876-8765");
students[4] = student4;
*/
}
//1. 회원 입력
public void menuInsert(Scanner sc) {
//문제) 신규 정보 등록 과정 추가
//배열 크기 및 여분 확인 -> 입력 가능 여부 결정
//입력-> 새로운 name, tel
//처리-> 저장소(배열)에 신규 저장
//출력-> "신규 데이터 입력!" or "저장소 full!" 메시지 출력
if (students.length > this.count()) {
System.out.print("이름 입력 : ");
String name = sc.next();
System.out.print("전화번호 입력 : ");
String tel = sc.next();
Student stu = new Student();
stu.setName(name);
stu.setTel(tel);
students[this.count()] = stu;
System.out.printf("신규 데이터 입력 완료! %n%n");
} else {
System.out.printf("저장소 Full! %n%n");
}
}
//2. 회원 전체 출력
public void menuSelect() {
//출력 -> 저장소(배열)에 있는 모든 데이터
/*
for (int i=0; i<students.length; ++i) {
Student student = students[i];
if (student != null) {
//System.out.println(student.toString());
System.out.println(student);
}
}
*/
System.out.printf("인원수:%d %n", this.count());
System.out.println("---------------");
System.out.println("이름 전화번호");
System.out.println("---------------");
for (Student student : students) {
if (student != null) {
System.out.println(student);
}
}
System.out.println("---------------");
System.out.println();
}
//인원수 메소드 -> private
private int count() {
int result = 0;
//문제) 저장소(배열)에 들어있는 데이터의 갯수 확인
for (int i=0; i<students.length; ++i) {
Student student = students[i];
if (student != null) {
++result;
}
}
return result;
}
//3. 회원 검색
public void menuSearch(Scanner sc) {
//외부 입력(name)
System.out.print("name?");
String name = sc.next();
Student value = new Student();
value.setName(name);
//처리 -> 검색 액션
//-> 배열 저장소 내에서 name이 일치하는 자료 검색
//-> Student 자료형을 가진 객체 한 개
Student result = null;
for (int i=0; i<students.length; ++i) {
Student temp = students[i];
/*
if (temp.getName().equals(name)) {
result = temp;
break;
}
*/
if (value.equals(temp)) {
result = temp;
break;
}
}
//결과 출력
if (result == null) {
System.out.printf("검색 결과가 없습니다.%n%n");
} else {
/*
System.out.printf("%s %s %n%n"
, result.getName()
, result.getTel());
*/
/*
System.out.println(result); //객체 정보
System.out.println(result.toString()); //객체 정보
*/
//toString() 메소드 호출시 객체 정보가 아니라
//멤버변수의 데이터를 출력하는 용도로 변경
//->오버라이딩
System.out.println(result);
System.out.println();
}
}
}
//Main.java
package com.sist;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
MenuAction menu = new MenuAction();
do {
System.out.println("--- 회원 정보 관리 ---");
System.out.println("1. 회원 전체 출력");
System.out.println("2. 회원 입력");
System.out.println("3. 회원 검색");
System.out.print("선택(1, 0-exit)?");
int m = sc.nextInt();
if (m==0) {
break;
}
switch (m) {
case 1: menu.menuSelect(); break;
case 2: menu.menuInsert(sc); break;
case 3: menu.menuSearch(sc); break;
}
}while(true);
sc.close();
}
}
----------------------------------------------------
요약
1. 멤버의 접근을 제한하는 제어자
- private
- (default)
- protected
- public
2. 멤버의 상태를 제한하는 제어자
- static
- final
3. private 생성자의 특징
4. final 키워드를 붙인 클래스, 멤버, 지역 변수의 특징
-------------------------------------------
'JavaSE' 카테고리의 다른 글
23일차_예외처리, String 클래스, 로그인 액션 (0) | 2015.06.21 |
---|---|
22일차_추상클래스,인터페이스, 회원관리_배열 (0) | 2015.06.21 |
20일차_메소드 오버로딩, 메소드 오버라이딩, 메인메뉴 액션 (0) | 2015.06.21 |
19일차_상속 (0) | 2015.06.21 |
18일차_상속 (0) | 2015.06.21 |