8일차 - 240105

김리오·2024년 1월 5일

학원공부 TIL

목록 보기
8/13

📌240104 과제 Solution

  • 내림차순으로 정리하는 sort method를 추가할 수 있다
  • sort method의 코드를 이해하려면, 참조형배열인 students 변수가 어떤 형태로 저장되어 있는지 그림으로 이해해야 한다. (그래야 덩어리로 비교한다는 말을 이해할 수 있음)
//method를 만드는 기준은 반복되는 작업이라는 것

package ex07_08_private_field;

public class Student_Make_Solution_Array_Sort {
	public static void main(String[] args) {
		/*
		 * Student h1 = new Student("강호동", 85, 60, 70);
		 * Student h2 = new Student("이승기", 90, 95, 80); 
		 * Student h3 = new Student("유재석", 75, 80, 100);
		 * Student h4 = new Student("하하", 80, 70, 95);
		 * Student h5 = new Student("이광수", 100, 65, 80);
		 */
		
		// int[] a = {1,2,3};

//		Student[] students = new Student[5];
//		students[0] = new Student("강호동",85,60,70);
//		students[1] = new Student("이승기", 90, 95, 80);
//		students[2] = new Student("유재석", 75, 80, 100);
//		students[3] = new Student("하하", 80, 70, 95);
//		students[4] = new Student("이광수", 100, 65, 80);

		Student[] students = { new Student("강호동", 85, 60, 70),
							   new Student("이승기", 90, 95, 80),
				               new Student("유재석", 75, 80, 100),
				               new Student("하하", 80, 70, 95),
				               new Student("이광수", 100, 65, 80) };

		int subject[] = getTotal(students);
		
		sort(students);

		print(students, subject);

		

	}// main

	// 학생들의 과목 총점을 구하는 getTotal method 정의
	// 향상된 for문이 아니라, 그냥 for문으로 정의하면 어떤 형태가 될까?
	private static int[] getTotal(Student[] objs) {
		int[] subject = new int[3];
		for (Student obj : objs) { // objs배열을 가져와서 obj에 저장하는데 obj는 Student class의 참조변수
			subject[0] += obj.kor;
			subject[1] += obj.eng;
			subject[2] += obj.math;
		}
		return subject;
	}

	// print method를 호출하면 아래 작업을 수행한다
	static void print(Student[] objs, int[] subject) {
		System.out.println("========= 학생별   /   과목별 총점 구하기 =========");
		System.out.println("이름\t국어\t영어\t수학\t총점\t평균");

		for (Student obj : objs) {
			printInfo(obj);
		}

		for (int j = 0; j < 45; j++) {
			System.out.print("=");
		}
		System.out.print("\n총점\t");
		for (int i = 0; i < subject.length; i++)
			System.out.print(subject[i] + "\t");
	}

	// printInfo method를 호출하면 아래 작업을 수행한다.
	static void printInfo(Student student) {
		System.out.print(student.name + "\t" + student.kor + "\t" + student.eng + "\t" + student.math + "\t"
				+ student.getTotal() + "\t");
		System.out.printf("%.1f\n", student.getAverage());
	}

	/////////////// 총점을 바탕으로 배열을 내림차순으로 정리해주는 logic
	/////////////// 지금 한 결과로 덩어리 자체가 바뀐 것이다. 참조변수 students의 순서가 총점기준 내림차순으로 
	private static void sort(Student[] students) {
		for (int i = 0; i < students.length - 1; i++) {
			for (int j = i + 1; j < students.length; j++) { // 초기값, 변하는 값, 최종값

				// students[0] ~ [4] 덩어리 째로 비교
				if (students[i].getTotal() < students[j].getTotal()) {
					Student imsi = students[i];
					students[i] = students[j];
					students[j] = imsi;
				}

			}
		}
	}
}

📌 Static Field

  • 클래스 필드에 Static으로 선언된 멤버는 클래스를 통해 생성되는 모든 인스턴스에서 동일한 값을 가진다.
  • class(static) variable은 인스턴스 생성없이 '클래스이름.클래스변수명'으로 접근한다.
    instance variable은 각 인스턴스의 개별 저장공간으로 '참조변수.인스턴스변수명'으로 접근한다.
//정적 필드가 있는 Accumulator 클래스
//total 필드는 객체마다 따로 생기지만
//grandTotal 필드는 특정 객체에 상관없이 클래스 자체에 생기는 정적 필드이다.


class Accumulator {
	int total = 0;
	static int grandTotal = 0;		//정적 필드를 선언하는 선언문
		
	void accumulate(int amount) {
		total += amount;
		
		//정적 필드에 amount 파라미터 값을 더하는 대입문
		grandTotal += amount;
	}
}
	public static void main(String args[]) {
		// 정적 변수 사용법 : 클래스명.정적변수
		System.out.println("정적변수 grandTotal = " + Accumulator.grandTotal);
		
		Accumulator obj1 = new Accumulator();
		obj1.accumulate(10);
		System.out.println("obj1.total = "+obj1.total);
		System.out.println("obj1.grandTotal = "+obj1.grandTotal);
		System.out.println("Accumulator.grandTotal = "+Accumulator.grandTotal);
		
		Accumulator obj2 = new Accumulator();
		obj2.accumulate(20);
		System.out.println("===========================================");
		System.out.println("obj2.total = "+obj2.total);
		System.out.println("obj2.grandTotal = "+obj2.grandTotal);
		System.out.println("Accumulator.grandTotal = "+Accumulator.grandTotal);
	}
정적변수 grandTotal = 0
obj1.total = 10
obj1.grandTotal = 10
Accumulator.grandTotal = 10
===========================================
obj2.total = 20
obj2.grandTotal = 30
Accumulator.grandTotal = 30
  • total은 정적필드가 아니다. 즉, 인스턴스를 생성할 때마다 초기화되는 값이다.
    반면 정적필드 grandTotal은 Accumulator 클래스와 함께 Method Area 메모리 영역에 올라가 있다.
    인스턴스 생성 후 accumulate(10)을 했을 때 10이 저장되어 있고,
    두 번째 인스턴스 생성 후 accumulate(20)을 했을 때 20이 더해지고 대입된다.
    그 결과 30이 저장되어 있는 것이다.

📌 Static method

  • 동일한 클래스 안에 static method가 정의된 경우
    메소드를 호출할 때 '클래스명.'을 생략하고 '메소드이름(매개변수)'로 호출할 수 있다.
public class Circle {
	public static void main(String[] args) {
		Circle obj = new Circle(3.5);
		Circle.print(obj);
		//print(obj);
        
		obj.radius = 5.5;
		print(obj);

	}

	private static void print(Circle obj) {
		// double area = obj.getArea();
		// System.out.println("원의 넓이 = " + area);

		System.out.println("원의 반지름 = " + obj.radius);
		System.out.println("원의 넓이 = " + obj.getArea());

	}

}

📌 캡슐화 및 접근제어자 / getter, setter

  • 객체 지향 프로그래밍의 주요 특징 중 하나인 캡슐화는 클래스 멤버를 클래스 내부에 감추는 것이다.
    클래스 멤버를 외부에서 조작할 수 없도록 은닉하기 위해 접근제어자 private을 사용한다.
  • 하지만 일부 멤버는 외부 클래스가 사용할 수 있도록 공개해야 한다.
    예로 리모컨은 복잡한 내부 회로를 캡슐화해서 은폐하지만 전원 버튼, 음량 조절 버튼 등은 외부에 노출해서 사용할 수 있게 한다.
    이처럼 클래스 내부에 은닉한 필드를 외부에서 사용할 수 있도록 Getter와 Setter를 제공한다.
    일반적으로 Getter는 get, Setter는 set으로 시작하는 이름을 사용한다.
    private으로 설정된 radius 클래스의 필드에 접근 하기 위해서 getRadius(), setRadius()메서드를 사용한다.
  • public : 다른 package에서도 접근 가능
    protected : 같은 package안에서는 접근 가능 / 다른 package의 자손은 접근 가능
    default : 같은 package안에서만 접근 가능
    private : 같은 class안의 멤버들만 접근 가능

public class Circle {
	// 접근 제어자 private은 클래스 내부에서만 접근 가능하다.
	// 동일 package내의 다른 class에서는 접근할 수 없다 not visibleFieldExample1_method.java
	private double radius;

	final double PI = 3.14;

	Circle(double radius) {
		this.radius = radius;
	}

	double getArea() {
		return radius * radius * PI;
	}

	// getter 메서드 - radius값을 모르지만 값을 얻고 싶음
	// radius의 반환형을 입력해야 함. get+첫글자는 대문자
	public double getRadius() {
		return radius;
	}

	// setter 메서드 - radius값을 모르지만 값을 변경하고 싶음
	// 반환형은 void로. set+첫글자는 대문자
	public void setRadius(double radius) {
		this.radius = radius;
	}

}

📌 singleton

  • getInstance() 메서드를 활용해 객체를 생성할 수 있다.
    객체 생성 방법이 new 연산자로 정의해주는 것만 있는 건 아니었다.
  • 참조변수인 obj1, obj2는 서로 같은 객체를 가리키고 있으므로, 서로 같은 값을 갖는다.
class Singleton {

	//필드 s는 외부에서 사용 못한다.
	//이 문장은 처음 Singleton 클래스가 JVM에 로딩될 때 한 번만 실행된다.
	private static Singleton s = new Singleton();
	
	//private : 외부에서 생성자를 호출할 수 없도록 막는다.
	private Singleton() {}

	public static Singleton getInstance() {
		System.out.println("여기는 getInstance입니다");
		return s;
	}
}
public class Singleton_main {
	public static void main(String[] args) {
		//Singleton obj1 = new Singleton(); //에러 발생
		//Singleton obj2 = new Singleton(); //에러 발생
		//무조건 new를 사용해야 객체를 생성할 수 있는 게 아니라, 이런 방식으로도 객체 생성 가능
		Singleton obj1 = Singleton.getInstance();
		Singleton obj2 = Singleton.getInstance();
		
		
		//하나의 객체를 계속 사용. 
		if(obj1 == obj2) {
			System.out.println("같은 Singleton 객체입니다.");
		} else {
			System.out.println("다른 Singleton 객체입니다.");
		}
	}

}
profile
생각하는 사람이 되고 싶다

0개의 댓글