3월 ~ 5월) 자바/java
9Day - (this) / Student & StudentApp / (Static) (Math) / MainArgsApp / RuntimeApp / Singleton&SingletonApp
첼로그
2023. 4. 7. 18:14
메소드에 this 키워드가 존재해야되는 이유
> 필드는 객체마다 메모리(HeapArea)로 독립적으로 생성되지만,
메소드는 객체와 상관없이 메모리 하나만 생성 - 프로토타입 클래스
> 문제점 - 메소드에서 필드를 사용할때 this 키워드를 사용하여 객체를 명확히 구분하여 필드 접근하도록 사용
this - 메소드 내부에 숨겨져 있는 키워드로 메소드를 호출한 객체의 메모리 주소
(HashCode)를 자동으로 전달받아 저장하는 키워드
> 메소드 내부의 명령에서 객체의 필드 또는 메소드를 사용하기 위한 this 키워드 사용
> 메소드 내부에서 객체를 대신 표현하기 위한 키워드 (내것.)
> this 키워드를 사용 하지않아도 자동으로 객체의 필드 또는 메소드에 접근하여 사용
this 키워드를 사용하는 경우
① 메소드에서 매개변수의 이름을 필드의 이름과 동일하게 작성한 경우 필드를 표현하기 위해
this - 생성자 및 setter 메소드
②
public Member() {
// this (값, 값, ...) : 생성자에서 this 키워드로 다른 생성자를 호출하는 명령
// > this 키워드로 생성자를 호출하는 명령은 첫번째 명령으로 작성 - 다른 명령이 먼저 실행될 경우 에러 발생
// > 생성자를 호출하는 명령 전에 다른 명령이 먼저 실행될 경우 에러 발생
this("NoId", "NoName", "NoEmail"); // TODO Auto-generated constructor stub
}
// 필드 선언 - 객체를 생성하면 객체의 필드에는 기본값이(숫자형 : 0, 논리형 : false, 참조형 : null) 초기값으로 자동 저장
private String id = "NoId";
private String name = "NoName";
private String email = "NoEmail";
// > 객체 생성시 객체 필드에 초기값으로 자동 저장될 기본값 변경 가능
// - 이렇게 많이 쓰진않음.
Student
// static : 객체가 아닌 클래스로 접근하기 위한 기능을 제공하는 제한자
// > 클래스(내부클래스), 필드, 메소드 작성시 사용
// 제한자 - 특별한 기능을 제공 (제한)하기 위해 사용하는 키워드
// > Access Modifiter(private, package, protected, public), static, final, abstract
// 학생정보 (학번, 이름, 국어, 영어, 총점)을 저장하기 위한 클래스 - VO 클래스
// > 클래스(내부클래스), 필드, 메소드 작성시 사용
// 제한자 - 특별한 기능을 제공 (제한)하기 위해 사용하는 키워드
// > Access Modifiter(private, package, protected, public), static, final, abstract
// 학생정보 (학번, 이름, 국어, 영어, 총점)을 저장하기 위한 클래스 - VO 클래스
public class Student {
// 인스턴스 필드 (Instance Field) 객체가 생성될때 메모리 (HeapArea)에 생성되는 필드
private int num;
private String name;
private int kor, eng, tot;
// 정적필드 (Static Field) 클래스를 읽어 메모리에 저장될때 생성되는 필드
// > 객체가 생성되기 전에 메모리에 하나만 생성되는 필드
// > 생성자에 초기화 처리하지않고 직접 초기값을 필드에 저장
// > 클래스로 생성된 모든 객체가 정적 필드 사용가능 - 공유값: 메모리 절약 및 필드값 변경
// > 클래스 외부에서는 객체가 아닌 클래스를 사용하여 접근 가능
private static int total; // 기본값을 초기값으로 사용할 경우 초기값 저장 생략 가능
// 생성자 (Constructor) 객체를 생성하면서 인스턴스 필드에 원하는 초기값을 저장하기 위해
public Student() { // TODO Auto-generated constructor stub
}
public Student(int num, String name, int kor, int eng) { // 생성자 생성 :alt + insert > Constructor
super();
this.num = num;
this.name = name;
this.kor = kor;
this.eng = eng;
// > 코드의 중복성을 최소화하여 프로그램의 생산성 밒 유지보수의 효율성 증가
// tot = kor + eng; // 총점을 계산하여 필드에 저장하는 명령 작성 - 메소드 호출
calcTot();
}
// 인스턴스 메소드 (Instan me) - this 키워드가 제공되는 메소드
// => this 키워드를 이용하여 인스턴스 필드 및 메소드 접근 가능
// => 클래스를 사용하여 정적 필드 및 메소드 접근 가능 - 클래스 생략 가능
public int getNum() { // getter&setter : alt + insert > getter&setter
return num;
}
public void setNum(int num) {
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;
calcTot();
}
/*
public void calcTot() { // 총점을 계산하는 메소드
tot = kor + eng;
}
*/
// ▽대신
// 은닉화 선언된 메소드 - 클래스 내부에서만 호출하여 사용하는 메소드
// > 코드의 중복성을 최소화 하기 위한 기능을 제공하는 메소드
private void calcTot() { // 총점을 계산하는 메소드
tot = kor + eng;
}
public void display() {
System.out.print("[" + name +"]님의 성적 >> ");
System.out.println("국어 = " + kor + ",영어 = " + eng + ", 총점 = " + tot);
}
// 정적 메소드(Static Method) : this 키워드를 제공하지 않는 메소드
// > this 키워드가 없으므로 인스턴스 필드 및 메소드 접근불가능
// > 클래스를 사용하여 정적 필드 및 메소드 접근 가능 - 클래스 생략 가능
public static int geTotal() {
return total;
}
public static void setTotal (int total) {
Student.total = total;
}
}
StudentApp
public class StudentApp {
public static void main(String[] args) {
/*
Student student1 = new Student(1000, "홍길동", 90, 90);
Student student2 = new Student(2000, "임꺽정", 94, 98);
Student student3 = new Student(3000, "전우치", 91, 80);
Student student4 = new Student(4000, "일지매", 76, 82);
Student student5 = new Student(5000, "장길산", 84, 86);
// 55번째줄 대신
// student1.calcTot(); // 총점을 구해주세요 클래스만들어서 불러냄.
// student2.calcTot();
// student3.calcTot();
// student4.calcTot();
// student5.calcTot();
// △ 대신 Student 에 적어줌
// public Student(int num, String name, int kor, int eng) { // 생성자 생성 :alt + insert > Constructor
// super();
// this.num = num;
// this.name = name;
// this.kor = kor;
// this.eng = eng;
//
// tot = kor + eng; // 총점을 계산하여 필드에 저장하는 명령 작성 - 메소드 호출
// // > 코드의 중복성을 최소화하여 프로그램의 생산성 밒 유지보수의 효율성 증가
// // tot = kor + eng;
// calcTot();
student1.display();
student2.display();
student3.display();
student4.display();
student5.display();
System.out.println("---------------------------------------------");
student1.setKor(100); // 국어점수가 바뀜
// student1.calcTot(); 대신 스튜던트에 ▽
// public void setKor(int kor) {
// this.kor = kor;
// calcTot(); << 대신넣어줌
// }
student1.display();
*/
System.out.println("---------------------------------------------");
// 방법 1)
// Student[] students = new Student[5]; // 학생을 5명만든게아니라, 객체를 저장할수있는 배열을(참조요소) 5개 생성
// 배열의 참조요소에는 기본적으로 [null]을 초기값으로 저장
// // 객체를 생성하여 배열의 참조요소에 객체의 메모리 주소 저장 - 객체 배열
// students[0] = new Student(1000, "홍길동", 90, 90);
// students[1] = new Student(2000, "임꺽정", 94, 98);
// students[2] = new Student(3000, "전우치", 91, 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++) {
//
// if (students[i]! = null) { // 참조변수에 [null]이 저장되어 있지않은 경우 메소드 호출
// students[i].display();
// }
// }
// System.out.println("----------------------------------------------------");
// 방법 2 )
Student[] students = { new Student(1000, "홍길동", 90, 90),
new Student(2000, "임꺽정", 94, 98),
new Student(3000,"전우치",91,80),
new Student(4000,"일지매",76,82),
new Student(5000,"장길상", 84, 86) };
// int total = 0; // 토탈은 Student 클래스에 만들어줘야함, 근데 거기에선 5개만둘어줘야해서
// 배열의 참조요소에 저장된 객체의 메모리 주소를 차례대로 제공받아 변수에 저장하여 처리하는 향상된 for구문을 사용하여 일괄처리
for (Student student : students) {
student.display();
// 정적 필드는 public 접근 제한자로 설정된 경우 클래스를 이용하여 접든 가능
// > 객체로 접근 가능하지만 경고 발생
// Student.total += student.getTot(); // 학생 총점을 반환받아 총합계 변수에 누적하여 저장
// 정적 필드가 private 접근 제한자로 설정된 경우 메소드를 이용하여 접근 가능
// > 정적 메소드는 객체가 아닌 클래스를 이용하여 호툴가능
Student.setTotal(Student.geTotal()+student.getTot());
}
System.out.println("----------------------------------------------------");
// 모든 학생들의 점수들의 합계를 계산하여 출력
// System.out.println("총합계 = " +Student.total);
System.out.println("총합계 = " + Student.geTotal());
System.out.println("----------------------------------------------------");
}
}
MainArgsApp
public class MainArgsApp {
// main 메소드의 매개변수에 프로그램 실행시 제공받은 문자열들을 매열로 전달받아 전달
public static void main(String[] args) {
// main 메소드의 매개변수에 저장된 배열의 요소 갯수출력
System.out.println("args.length = " + args.length);
// main 메소드의 매개변수에 저장된 배열의 모든 요소값을 일괄적으로 출력
for (int i = 0; i < args.length; i++) {
System.out.println("args[ " + i + "] = " + args[i]);
}
}
}
RuntimeApp
import java.io.IOException;
public class RuntimeApp {
public static void main(String[] args) throws IOException {
// Runtime 클래스 : Java 프로그램과 운영체제(Operation System) 관련 정보를 제공하는 메소드
// 기능의 메소드가 선언된 클래스
// > 생성자가 은닉화 선언되어 있는 new연산자로 객체 불가능
// Runtime runtime = new Runtime(); // 오류뜸
// Runtime.getRuntime() - Runtime 객체를 반환하는 메소드
// > 정적 메소드이므로 클래스를 이용하여 호출가능
// > getRuntime() 메소드를 여러번 호출해도 같은 객체를 반환
Runtime runtime1 = Runtime.getRuntime();
Runtime runtime2 = Runtime.getRuntime();
System.out.println("runtime1 = " + runtime1);
System.out.println("runtime2 = " + runtime2);
System.out.println("----------------------------------------------");
System.out.println(" 메모리 정리 전, JVM 사용 메모리의 크기 >> ");
// Runtime.totalMemory() : JVM 사용 가능한 전체 메모리의 크기를 반환하는 메소드
// Runtime.freeMemory() : JVM이 사용 가능한 여유 메모리의 크기를 반환하는 메소드
System.out.println((runtime1.totalMemory() - runtime1.freeMemory()) + "Byte");
// Runtime.gc() - 메모리를 정리하는 Gaebage Collector를 실행하는 메소드
runtime1.gc(); // System.gc();
System.out.print("메모리를 정리한 후 JVM 사용 메모리의 크기 >> ");
System.out.println((runtime1.totalMemory()-runtime1.freeMemory())+"Byte");
// Runtime. exec(String command) : 운영체제에 명령을 전달하여 실행하는 메소드
runtime2.exec("calc.exe");
System.out.println();
// 계산기 뜸
}
}
runtime1 = java.lang.Runtime@3498ed
runtime2 = java.lang.Runtime@3498ed
----------------------------------------------
메모리 정리 전, JVM 사용 메모리의 크기 >>
2686688Byte
메모리를 정리한 후 JVM 사용 메모리의 크기 >> 1228328Byte
Singleton
// 싱글톤 디자인 패턴을 적용하여 작성된 클래스 - 싱글톤 클래스 (Singleton Class)
// > 프로그램에 객체를 하나만 제공하기 위한 목적의 클래스를 작성하기 위해 사용
// > 프로그램에 불필요한 객체가 여러개 생성되는 것을 방지하기 위한 디자인 패턴
// > 프로그램에 객체를 하나만 제공하기 위한 목적의 클래스를 작성하기 위해 사용
// > 프로그램에 불필요한 객체가 여러개 생성되는 것을 방지하기 위한 디자인 패턴
public class Singleton {
// 클래스의 객체를(메모리 주소)를 저장하기 위한 필드 선언
// > static 제한자를 사용하여 정적 필드 선언
// 시스템 필드 : 클래스 내부에서만 사용하기 위한 필드
// > Getter 메소드와 Setter 메소드를 작성하지 않은 필드
// > 일반적인 필드와 구분하기 위해 필드명을 _로 시작되도록 작성하는 것을 권장
private static Singleton _instance; // 정적필드
// 생성자를 은닉화 선언 - 클래스 외부에서 생성자에 접근하지 못하도록 설정
// > 객체 생성 불가능
private Singleton() {
}
// 정적 영역(Static Block) - 클래스를 읽어 메모리(MthodArea)에 저장된 후 자동으로 실행될 명령을 작성하기 위한 영역
// > 프로그램에서 한번만 실행되는 명령
// > 정적 필드 또는 정적 메소드만 사용 가능
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 = new Singleton();
Singleton singleton2 = new Singleton();
System.out.println("singleton1 = " + singleton1);
System.out.println("singleton2 = " + singleton2);
singleton1.display();
singleton2.display();
*/
// 싱글톤 클래스는 생성자가 은닉화 선언되어 있어 new 연산자로 생성자를 호출하여 객체 생성 불가능
// > 객체를 반환하는 정적 메소드를 호출하여 참조변수에 반환받은 객체를 저장하여 사용
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println("singleton1 = " + singleton1);
System.out.println("singleton2 = " + singleton2);
singleton1.display();
singleton2.display();
System.out.println("------------------------------------------");
// 싱글톤 클래스는 참조변수에 반환받은 객체를 저장하여 메소드를 호출하지않고,
// 반환 받은 객체로 직접 메소드를 호출하여 사용하는 것을 권장
Singleton.getInstance().display();
Singleton.getInstance().display();
}
}
singleton1 = oop.Singleton@1a407d53
singleton2 = oop.Singleton@1a407d53
Singleton 클래스의 display() 메소드 호출
Singleton 클래스의 display() 메소드 호출
------------------------------------------
Singleton 클래스의 display() 메소드 호출
Singleton 클래스의 display() 메소드 호출