OOP : Object Oriented Programming
객체(객체가 가지고 있는 기능 요소)를 사용하여 프로그램 작성 / 객체(관계를 맺고 있는)들을 만들려면 클래스 필요
현실 세계에 존재하는 대상을 모델링하여 클래스로 작성하고 클래스로 객체를 생성하여 객체의 요소로 프로그램을 작성하는 방법
관계를 맺고 있는 객체들이 메시지를 주고 받는 것
객체 모델링(Object Modeling) : 현실 세계에 존재하는 대상을 속성(값)과 행위(일)로 구분하여 설계
대상을 모델링(설계)하여 클래스라는 자료 생성 (속성은 필드, 행위는 메소드로 만들어줌)
OOP 특징 : 1. 추상화, 2. 캡슐화, 3. 다형성, 4. 상속성
객체 모델링한 대상을 클래스(필드와 메소드)로 선언
추상화는 관점에 따라 다르게 표현
해결해야 되는 문제/현실을 SW적으로 단순화 시켜서 만드는 행위
장점 : 클래스라는 자료형 배포 가능 ( ex) 망치가 필요할때 사서 사용)
public class ArraySortApp {
public static void main(String[] args) {
int[] array={30,50,10,40,20};
System.out.print("정렬 전 >> ");
for(int num:array) {
System.out.print(num+" ");
}
System.out.println();
//배열 요소값을 선택 정렬 알고리즘을 사용하여 오름차순 정렬되도록 저장
for(int i=0;i<array.length-1;i++) {
for(int j=i+1;j<array.length;j++) {
if(array[i]>array[j]) {
int temp=array[i];
array[i]=array[j];
array[j]=temp;
}
}
}
System.out.print("정렬 후 >> ");
for(int num:array) {
System.out.print(num+" ");
}
System.out.println();
int[] array={30,50,10,40,20};
System.out.println("정렬 전 >> "+Arrays.toString(array));
Arrays.sort(array);
System.out.println("정렬 후 >> "+Arrays.toString(array));
객체(Object)를 만들기 위한 자료형(참조형) / 객체 대신 인스턴스(Instance)로 표현 가능
현실 세계의 존재하는 사물을 클래스라는 자료형으로 표현하여 객체로 구현
형식) public(생략가능) class 클래스명(식별자 파스칼표기법) {
클래스 선언 : 필드에는 프로그램 실행에 필요한 값을 저장하고 메소드로 필드값을 사용해 원하는 기능을 제공
public class Car {
//1. 필드(Field) : 클래스에 선언된 모든 메소드는 필드 사용 가능
//모든 메소드가 사용할수있도록 클래스에 만들어짐
private String modelName; //모델명 (필드 이름은 카멜 표기법 사용)
private boolean engineStatus; //엔진상태 - false : Off, true : On
private int currentSpeed; //현재속도
//2. 생성자 : 생성자 선언을 생략하면 매개변수가 없는 기본 생성자
//(Default Constructor)가 존재하는 것으로 처리
//3. 메소드 : 필드를 이용하여 명령들로 필요한 기능을 제공
//메소드 호출: 메시지 주고받는 일 시키는 것
public void startEngine() { // startEngine메소드는 시동 온(On) 명령 실행
engineStatus=true;
System.out.println(modelName+"의 시동을 켰습니다.");
}
public void stopEngine() { // stopEngine메소드는 시동 오프(Off) 명령 실행
if(currentSpeed!=0) { //자동차가 멈췄있지 않은 경우
//currentSpeed=0;
//System.out.println(modelName+"의 자동차가 멈췄습니다.");
//클래스에 선언된 메소드를 서로 호출 가능
// → 코드의 중복성 최소화 : 프로그램의 생산성 및 유지보수의 효율성 증가
speedZero();
}
engineStatus=false;
System.out.println(modelName+"의 시동을 껐습니다.");
}
public void speedUp(int speed) {
//speedUp메소드는 매개변수(speed)를 전달받아 속도 증가 명령 실행
if(!engineStatus) { //시동이 꺼져 있는 경우
System.out.println(modelName+"의 시동이 꺼져 있습니다.");
return; //메소드 종료
}
if(currentSpeed+speed>150) {
//현재속도와 증가된 속도의 합이 최고 속도보다 큰 경우
speed=150-currentSpeed; //증가된 속도 변경
}
currentSpeed+=speed;
System.out.println(modelName+"의 속도가 "+speed+"Km/h 증가 되었습니다.
현재 속도는 "+currentSpeed+"Km/h입니다.");
}
public void speedDown(int speed) {
//speedDown메소드는 매개변수(speed)를 전달받아 속도 감소 명령 실행
if(!engineStatus) { //시동이 꺼져 있는 경우
System.out.println(modelName+"의 시동이 꺼져 있습니다.");
return;//메소드 종료
}
if(currentSpeed<speed) { //현재속도보다 감소된 속도가 큰 경우
speed=currentSpeed; //감소된 속도 변경
}
currentSpeed-=speed;
System.out.println(modelName+"의 속도가 "+speed+"Km/h 감소 되었습니다.
현재 속도는 "+currentSpeed+"Km/h입니다.");
}
public void speedZero() { //speedZero메소드는 속도 0으로 명령 실행
currentSpeed=0;
System.out.println(modelName+"의 자동차가 멈췄습니다.");
}
public boolean isEngineStatus() {
return engineStatus;
}
public void setEngineStatus(boolean engineStatus) {
this.engineStatus = engineStatus;
}
public int getCurrentSpeed() {
return currentSpeed;
}
public void setCurrentSpeed(int currentSpeed) {
this.currentSpeed = currentSpeed;}}
public class CarApp {
public static void main(String[] args) {
//Car 클래스로 객체를 생성하여 참조변수에 저장
//하나의 클래스로 서로 다른 객체를 여러개 생성 가능
//객체를 생성하면 객체의 필드에 기본값 저장 (숫자형:0, 논리형:false, 참조형:null)
Car carOne=new Car();
Car carTwo=new Car();
Car carThree=carTwo;//다른 참조변수에 저장된 객체의 주소를 전달받아 저장 가능
System.out.println("carOne = "+carOne);//oop.Car@5aaa6d82
System.out.println("carTwo = "+carTwo);//oop패키지.Car클래스의 메모리주소
System.out.println("carThree = "+carThree);//carTwo와 동일
//참조변수.필드 : 참조변수에 저장된 객체로 필드에 접근하여 사용
//문제점 : 필드에 직접 접근하여 필드값을 변경할 경우 비정상적인 값 저장 가능
//해결법 : 필드를 은닉화 처리하여 클래스 선언 → 은닉화 선언된 필드에 접근할 경우 에러 발생
//carOne.modelName="티코"; //필드값 변경
//필드값을 직접 변경 불가 → 필드값을 변경하는 Setter 메소드 호출하여 필드값 변경
carOne.setModelName("티코");
carOne.setEngineStatus(true);
carOne.setCurrentSpeed(100);
//System.out.println("첫번째 자동차의 모델명 = "+carOne.modelName);//필드값 출력
//필드값을 직접 사용 불가 → 필드값을 반환하는 Getter 메소드 호출하여 필드값 반환받아 출력
System.out.println("첫번째 자동차의 모델명 = "+carOne.getModelName());//필드값 출력
System.out.println("첫번째 자동차의 엔진상태 = "+carOne.isEngineStatus());
System.out.println("첫번째 자동차의 현재속도 = "+carOne.getCurrentSpeed());
carTwo.setModelName("싼타페");
System.out.println("두번째 자동차의 모델명 = "+carTwo.getModelName());//싼타페
System.out.println("두번째 자동차의 엔진상태 = "+carTwo.isEngineStatus());//false
System.out.println("두번째 자동차의 현재속도 = "+carTwo.getCurrentSpeed());//0
//참조변수.메소드명(값,...) : 참조변수에 저장된 객체를 사용하여 메소드 호출
carTwo.startEngine(); //싼타페의 시동을 켰습니다.
carTwo.speedUp(50);
//싼타페의 속도가 50Km/h 증가 되었습니다. 현재 속도는 50Km/h입니다.
carTwo.speedUp(30);
//싼타페의 속도가 30Km/h 증가 되었습니다. 현재 속도는 80Km/h입니다.
carTwo.speedDown(40);
//싼타페의 속도가 40Km/h 감소 되었습니다. 현재 속도는 40Km/h입니다.
carTwo.speedZero();//싼타페의 자동차가 멈췄습니다.
carTwo.stopEngine();}} //싼타페의 시동을 껐습니다.
public class Method {
void displayOne() { //displayOne이라는 메소드를 호출하여 얻을 수 있는 결과값 없음
System.out.println("# Method 클래스의 displayOne() 메소드 호출 #");}
void displayTwo() {
System.out.println("# Method 클래스의 displayTwo() 메소드 호출 #");}
void printOne() {
int tot=0;
for(int i=1;i<=100;i++) {
tot+=i;}
System.out.println("1~100 범위의 정수들의 합계 = "+ tot);}
//메소드 호출시 매개변수에 값이 정상적으로 전달되어 저장되야만 메소드의 명령 실행
// → 매개변수에 값이 저장되지 않을 경우 메소드 호출 불가능 (에러 발생)
void printTwo(int num) {
//매개변수에 저장된 값에 대한 검증
if(num<0) {//비정상적인 값이 매개변수에 저장된 경우
System.out.println("[에러]매개변수에 0보다 큰 정수값이 저장되어야 됩니다.");
return;//메소드 종료
}
int tot=0;
for(int i=1;i<=num;i++) {
tot+=i;
}
System.out.println("1~"+num+" 범위의 정수들의 합계 = "+ tot);}
void printThree(int num1, int num2) {
/*
if(num1>num2) {//비정상적인 값이 매개변수에 저장된 경우
System.out.println("[에러]첫번째 전달값이 두번째 전달값보다 작아야 됩니다.");
return;//메소드 종료
}
*/
if(num1>num2) {
int temp=num1;
num1=num2;
num2=temp;}
int tot=0;
for(int i=num1;i<=num2;i++) {
tot+=i;}
System.out.println(num1+"~"+num2+" 범위의 정수들의 합계 = "+ tot);}
int returnTot(int num1, int num2) {
if(num1>num2) {
int temp=num1;
num1=num2;
num2=temp;}
int tot=0;
for(int i=num1;i<=num2;i++) {
tot+=i;}
//변수에 저장된 값을 메소드 종료하며 반환
//→ 반환되는 값의 자료형과 메소드 반환형이 반드시 동일
return tot;}
//매개변수로 정수값을 전달받아 홀수와 짝수를 구분하여 반환하는 메소드
// → false 반환 : 홀수, true 반환 : 짝수라고 약속
boolean isOddEven(int num) {//is로 시작하는 메소드는 boolean자료형 사용
if(num%2!=0) {
return false;
} else {
return true;
}
}
//배열(여러개의값)의 메모리 주소를 반환하는 메소드
int[] returnArray() {
/*
int[] array={10,20,30,40,50};
return array;//참조변수에 저장된 배열의 메모리 주소 반환 - 배열 반환
*/
//return {10,20,30,40,50};//에러 발생
return new int[]{10,20,30,40,50};
}
//3개의 매개변수에 정수값을 전달받아 합계를 계산하여 반환하는 메소드
int sumOne(int num1, int num2, int num3) {
return num1+num2+num3;
}
//배열을 전달받아 배열의 모든 요소값들의 합계를 계산하여 반환하는 메소드
int sumTwo(int[] array) {
int tot=0;
for(int num:array) {
tot+=num;
}
return tot;
}
//매개변수 생략 기호(...)를 사용하여 매개변수를 선언한 경우 값을 0개 이상 전달받아 저장 가능
//→ 매개변수로 값들을 전달받아 내부적으로 배열을 생성하여 요소값으로 저장
int sumThree(int...array) {
int tot=0;
for(int num:array) {
tot+=num;
}
return tot;
}
}
//클래스 선언 예제인 Method 클래스 참고
public class MethodApp {
public static void main(String[] args) {
//클래스로 객체를 생성하여 객체의 메모리 주소를 참조변수에 저장
// → 같은 패키지의 클래스는 패키지 표현없이 클래스만 사용하여 접근 가능
// → 참조변수를 사용하여 객체의 필드 또는 메소드 접근
Method method=new Method();
//참조변수에 저장된 값을 출력할 경우 "자료형@메모리주소" 형식으로 제공된 결과값 출력
System.out.println("method = "+method);//oop.Method@5aaa6d82
//메소드 호출 : 메소드를 호출하면 프로그램 흐름(스레드)이 객체의 메소드로 이동하여
//메소드의 명령을 실행하고 메소드가 종료되면 다시 되돌아와 다음 명령 실행
method.displayOne();//# Method 클래스의 displayOne() 메소드 호출 #"
method.displayTwo();//# Method 클래스의 displayTwo() 메소드 호출 #"
method.printOne();//5050
method.printTwo(80);//1~80 범위의 정수들의 합계 = 3240
method.printTwo(-30);//[에러]매개변수에 0보다 큰 정수값이 저장되어야 됩니다.
//메소드 호출시 나열될 값이 매개변수에 차례대로 전달되어 저장
method.printThree(25, 75);//25~75 범위의 정수들의 합계 = 2550
method.printThree(77, 45);//45~77 범위의 정수들의 합계 = 2013
//메소드를 호출하여 반환되는 결과값을 변수에 저장
// → 메소드 명령에 대한 결과값을 지속적으로 사용할 경우 변수에 저장
int tot=method.returnTot(34, 86);
//입력과 출력 명령은 프로그램에서 작성 (프로그램에 대한 독립성 확보)
// → 메소드에서는 값에 대한 계산만 하고 입력과 출력은 미작성
System.out.println("합계(메소드 호출의 반환 결과값) = "+tot);
//반환값을 일시적으로 사용할 경우 변수에 미저장
System.out.println("합계 = "+method.returnTot(40,80));//합계 = 2460
boolean result=method.isOddEven(10);
if(result) {
System.out.println("매개변수에 전달된 값은 [짝수]입니다.");
} else {
System.out.println("매개변수에 전달된 값은 [홀수]입니다.");
}
//if 구문의 조건식 대신 논리값을 반환하는 메소드를 호출하여 명령 선택 실행
if(method.isOddEven(11)) {
System.out.println("매개변수에 전달된 값은 [짝수]입니다.");
} else {
System.out.println("매개변수에 전달된 값은 [홀수]입니다.");
}
//메소드 호출시 반환되는 배열의 메모리 주소를 참조변수에 저장 (배열의 요소 참조 가능)
int[] array=method.returnArray();
for(int num:array) {
System.out.print(num+" ");
}
System.out.println();//10 20 30 40 50
System.out.println("합계 = "+method.sumOne(10, 20, 30));//합계 = 60
//매개변수에 값이 정상적으로 전달되지 않을 경우 메소드 호출에 대한 에러 발생
//System.out.println("합계 = "+method.sumOne());
//System.out.println("합계 = "+method.sumOne(10, 20));
//System.out.println("합계 = "+method.sumOne(10, 20, 30, 40));
//배열을 만들어서 사용하면 원하는 값을 통채로 전달하므로 오류 발생 X
//System.out.println("합계 = "+method.sumTwo({10,20,30}));
//매개변수가 객체가 아니므로 에러 발생
System.out.println("합계 = "+method.sumTwo(new int[]{10, 20, 30}));//60
System.out.println("합계 = "+method.sumTwo(new int[]{}));//합계 = 0
System.out.println("합계 = "+method.sumTwo(new int[]{10, 20}));//합계 = 30
System.out.println("합계 = "+method.sumTwo(new int[]{10, 20, 30, 40}));
//int sumThree(int...array) : 매개변수로 값들을 전달받아 내부적으로 배열 생성
System.out.println("합계 = "+method.sumThree(10, 20, 30));
System.out.println("합계 = "+method.sumThree());
System.out.println("합계 = "+method.sumThree(10, 20));
System.out.println("합계 = "+method.sumThree(10, 20, 30, 40)); }}
같은 이름의 메소드를 호출할 경우 상태에 따라 메소드가 선택 호출되는 기능
호출되는 기능 : 1. 메소드 오버로드, 2. 메소드 오버라이드
메소드 오버로드 ( Method Overload )
//같은 기능을 가진 메소드를 오버로드 (메소드 이름 동일하게 선언)
public class Overload {
public void displayInt(int param) {
//displayint메소드를 이용해 정수값 param값 반환
System.out.println("정수값 = "+param);
}
public void displayBoolean(boolean param) {
System.out.println("논리값 = "+param);
}
public void displatString(String param) {
System.out.println("문자열 = "+param);
}
// 같은 메소드 사용하여 매개변수에 전달되는 값에 의해 메소드를 선택 호출
public void display(int param) {
System.out.println("정수값 = "+param);
}
public void display(boolean param) {
System.out.println("논리값 = "+param);
}
public void display(String param) {
System.out.println("문자열 = "+param);}}
//오버로드로 선언한 메소드 프로그램 실행
public class OverloadApp {
public static void main(String[] args) {
Overload overload=new Overload();// Overload 객체 생성
overload.displayInt(100);//overload참조변수를 통해 displayInt메소드 호출
//overload.displayInt(false);
//메소드 호출시 매개변수에 값을 잘못 전달한 경우 에러 발생
overload.displayBoolean(false);
overload.displatString("홍길동");
//오버로드 선언된 메소드는 매개변수에 전달되는 값에 의해 메소드를 선택 호출
//→메소드 오버로드에 의한 다형성
overload.display(200);
overload.display(true);
overload.display("임꺽정");
//overload.display(12.34);}}
//전달된 값에 대한 자료형의 매개변수가 없는 경우 에러 발생
메소드에 this 매개변수가 존재하는 이유:
this 키워드를 표현하여 사용하는 경우
public class Member {
private String id="NoId";//필드(Field) 선언
private String name="NoName";
private String email="NoEmail";
public Member() {
this("NoId","NoName","NoEmail");
}
public Member(String id) {
this.id=id;//this.id : id 필드의 초기화
}
public Member(String id, String name) {
super();
this.id = id;
this.name = name;
}
public Member(String id, String name, String email) {
super();
this.id = id;
this.name = name;//this.name : 필드 & name : 매개변수
this.email = email;
}
//getter, setter 메소드(Method) 선언
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
//필드값을 출력하는 메소드
public void display() {
System.out.println("아이디 = "+id);
System.out.println("이름 = "+name);
System.out.println("이메일 = "+email);}}
public class MemberApp {
public static void main(String[] args) {
//new 연산자로 클래스의 매개변수가 없는 기본 생성자를 사용하여 객체 생성
//→ 생성된 객체의 필드는 기본값으로 자동 초기화
//→ new 연산자로 호출한 생성자가 없는 경우 에러 발생 (객체 생성 불가능)
Member member1=new Member();
//Getter 메소드를 호출하여 필드값을 반환받아 출력
System.out.println("아이디 = "+member1.getId());
System.out.println("이름 = "+member1.getName());
System.out.println("이메일 = "+member1.getEmail());
//Setter 메소드를 호출하여 매개변수의 전달값으로 객체의 필드값 변경
member1.setId("aaa");
member1.setName("홍길동");
member1.setEmail("hgd@google.com");
member1.display();
Member member2=new Member("bbb"); //원하는 필드에 초기값 저장
member2.display(); //display 메소드 호출
Member member3=new Member("ccc", "임꺽정");
member3.display();
Member member4=new Member("ddd", "전우치", "chon@itwill.xyz");
member4.display();}}
//학생정보(학번,이름,국어,영어,총점)를 저장하기 위한 VO클래스
public class Student {
private int num;//일반적으로 String or int의 결정은 연산 여부로 판단
private String name;//필드 생성
private int kor, eng, tot;
private static int total=0; //기본값 사용시 초기값 설정 생략, 필드 작성시 작성
//private int total; 하면 객체 여러개 생성됨 (비효율)
//total변수는 메모리에 하나만 있으면 됨 → static 사용 필요
//생성자 : 객체 생성시 인스턴스 필드에 원하는 초기값을 저장하기 위해 작성
public Student() { }// Student 기본생성자 [ctrl]+[space]
public Student(int num, String name, int kor, int eng) {
super();
this.num = num; // 필드 생성자 초기화
this.name = name;
this.kor = kor;
this.eng = eng;
//총점을 계산하여 필드에 저장하는 명령 작성 (메소드 호출)
// → 코드의 중복성을 최소화하여 프로그램의 생산성 및 유집보수의 효율성 증가
//tot=kor+eng;
calcTot(); }// 계산 메소드 호출하면 총점을 계산하는 메소드 호출할 필요 없음
// 메소드가 생성자를 호출할수없지만 생성자가 메소드를 호출하는것은 가능
//1. 인스턴스 메소드 : this 매개변수가 존재하는 메소드로 인스턴스 필드 및 정적 필드 접근 가능
public int getNum() {
return num;
}
public void setNum(int num) {//getter,setter 메소드 선언 [alt]+[shift]+[s]→[r]
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getKor() {
return kor;
}
public void setKor(int kor) {
this.kor = kor;
calcTot();
}
public int getEng() {
return eng;
}
public void setEng(int eng) {
this.eng = eng;
calcTot();
}
public int getTot() {
return tot;
}
public void setTot(int tot) {
this.tot = tot;
}
/*
public void calcTot() {//총점을 계산하는 메소드
tot=kor+eng;
}
*/
//은닉화 선언된 메소드 (클래스 내부에서만 사용하는 메소드) : 시스템 메소드
// → 코드의 중복성을 최소화하기 위한 기능을 제공
private void calcTot() {
tot=kor+eng;
}
public void display() { //필드값을 출력하는 메소드
System.out.print(name+"["+num+"]님의 성적 >> ");
System.out.println("국어 = "+kor+", 영어 = "+eng+", 총점 = "+tot);
}
//2. 정적 메소드(Static Method) : this 매개변수가 없는 메소드
//this 매개변수가 없으므로 인스턴스 필드에 접근 불가(정적 필드만 접근하여 사용 가능)
//객체 생성 전에 클래스 이름을 사용하여 호출 가능 (메소드 호출의 용이성)
// ex) math class : 수학 관련된 기능만 제공, 생성자 은닉화하여 객체생성불가.
public static int getTotal() {
return total;
}
public static void setTotal(int total) {
Student.total = total; }}
public class StudentApp {
public static void main(String[] args) {
//방법1
Student student1=new Student(1000, "홍길동", 90, 90);
Student student2=new Student(2000, "임꺽정", 94, 98);
Student student3=new Student(3000, "전우치", 92, 80);
Student student4=new Student(4000, "일지매", 76, 82);
Student student5=new Student(5000, "장길산", 84, 86);
//student1.calcTot(); 은닉화 처리된 메소드 사용 불가
student1.display();
student2.display();
student3.display();
student4.display();
student5.display();
student1.setKor(100);//국어점수 변경
student1.display();//변경값 확인
//방법2
//객체를 저장할 수 있는 참조요소가 5개인 배열 생성 (배열의 참조요소 초기값: null)
//참고로 자리가 30개→학생이 30명 X (참조요소가 5개있다고 객체가 만들어진것 X)
Student[] students=new Student[5];
//배열의 참조요소에 객체를 생성하여 저장 (객체 배열)
students[0]=new Student(1000, "홍길동", 90, 90);
students[1]=new Student(2000, "임꺽정", 94, 98);
students[2]=new Student(3000, "전우치", 92, 80);
students[3]=new Student(4000, "일지매", 76, 82);
students[4]=new Student(5000, "장길산", 84, 86);
//참조변수에 null이 저장된 상태에서 메소드를 호출한 경우 NullPointerException 발생
for(int i=0;i<students.length;i++) {
//참조변수(요소)에 저장된 값이 null이 아닌 경우에만 메소드 호출
//→ NullPointerException 발생 방지
if(students[i]!=null) {
students[i].display(); }}
//방법3
Student[] students={new Student(1000, "홍길동", 90, 90)
, new Student(2000, "임꺽정", 94, 98), new Student(3000, "전우치", 92, 80)
, new Student(4000, "일지매", 76, 82), new Student(5000, "장길산", 84, 86)};
for(Student student:students) {//참조변수를 통해 배열을 호출하여 명령 실행
student.display();
//정적 필드는 클래스를 이용하여 접근 - 형식)클래스명.필드명
// 정적 필드의 접근 지정자가 private인 경우 접근 불가능
//Student.total+=student.getTot();
//정적 메소드는 클래스를 이용하여 호출 - 형식)클래스명.메소드명(값,값,...);
Student.setTotal(Student.getTotal()+student.getTot());
} // Total이라는 정적 필드를 변경하여 총합계 계산
System.out.println("총합계 = "+Student.getTotal()); }}
//모든 학생들의 점수 총합계를 출력
Java 프로그램을 실행하는 JVM 관련 정보를 저장하기 위한 클래스
Runtime.getRuntime() : Runtime 객체를 반환하는 정적 메소드 (클래스명으로 호출)
Runtime.totalMemory() : JVM이 사용 가능한 전체 메모리의 크기(Byte)를 반환하는 메소드
Runtime.freeMemory() : JVM이 사용 가능한 여유 메모리의 크기(Byte)를 반환하는 메소드
Runtime.gc() : 메모리를 청소하는 가비지 콜렉터(Garbage Collector)를 실행하는 메소드
public class RuntimeApp {
public static void main(String[] args) {
//생성자가 은닉화 선언되어 있어 new 연산자로 객체 생성 불가능
//getRuntime() 메소드를 여러번 호출해도 같은 객체를 반환 (같은 메모리 주소 출력)
Runtime runtime1=Runtime.getRuntime();
Runtime runtime2=Runtime.getRuntime();
System.out.println("청소 전 JVM 사용 메모리 크기 = "
+(runtime1.totalMemory()-runtime1.freeMemory())+"Byte");
//싱글톤 클래스는 객체를 반환받아 참조변수에 저장하여 메소드를 호출하지 않고 객체를
//반환받아 직접 메소드를 호출하여 사용하는 것을 권장
System.out.println("청소 전 JVM 사용 메모리 크기 = "+
(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())+"Byte");
Runtime.getRuntime().gc();
public class Singleton {
private static Singleton _instance;
//생성자를 은닉화 선언 : 클래스 외부에서 생성자에 접근하지 못하도록 설정(객체 생성 불가능)
private Singleton() { }
static {
//클래스로 객체를 생성하여 시스템 필드에 저장 (프로그램에서 하나의 객체만 생성하여 사용)
_instance=new Singleton();
}
//미리 생성되어 시스템 필드에 저장된 객체를 반환하는 정적 메소드 선언
public static Singleton getInstance() {
return _instance;
}
//인스턴스 메소드
public void display() {
System.out.println("Singleton 클래스의 display() 메소드 호출"); }}
public class SingletonApp {
public static void main(String[] args) {
//싱글톤 클래스는 생성자가 은닉화 선언되어 new 연산자로 객체 생성 불가능
//클래스 생성시 미리 생성되어 시스템 필드에 저장된 객체를 반환하는 정적 메소드 호출
// → 프로그램에서 객체를 하나만 제공받아 사용
Singleton singleton1=Singleton.getInstance();
Singleton singleton2=Singleton.getInstance();
System.out.println("singleton1 = "+singleton1);
System.out.println("singleton2 = "+singleton2);
//동일한 메모리 주소 출력
singleton1.display();
singleton2.display();
//싱글톤 클래스는 참조변수에 객체를 저장하여 참조변수로 메소드를 호출하지 않고
//객체를 반환받아 메소드를 직접 호출하여 사용하는 것을 권장
Singleton.getInstace().display(); }}