package javajungsuk6;

public class Ch06_6a7 {

	public static void main(String[] args) {
		// 6-6 ~ 6-7 객체의 생성과 사용
		
		// 가비지 컬렉터(Garbage Collector, GC)가 주기적으로 검사하여 메모리를 청소해준다.
		// java에서는 우리가 더이상 사용불가한 객체를 지우지 않아도 자동으로 메모리를 청소해준다.
		// 하나의 인스턴스를 여러개의 참조변수가 가리키는 것은 가능
		// 여러개의 인스턴스를 하나의 참조변수가 가리키는 것은 불가능
		
		// Tv t; // class(설계도)의 리모콘 / 객체를 사용하고 다루려면 참조변수 선언
		// t = new Tv(); // 객체 생성 : Tv의 인스턴스를 생성 후, t에 인스턴스 주소를 저장
		Tv t = new Tv(); // 한 번에 선언과 생성 : 리모콘(t)과 Tv객체를 연결(=)하다.
		Tv t2 = new Tv();
		
		// 변수 사용
		t.color = "rainbow";
		t.power = true;
		t.channel = 7;
		
		// 메서드 호출 : 채널을 낮추는 기능을 사용
		t.channelDown(); // 메서드 사용
		
		System.out.println("Tv의 색깔은 " + t.color + "입니다.");
		System.out.println("현재 채널은 " + t.channel + "입니다.");
		
		System.out.println("Tv의 색깔은 " + t2.color + "입니다."); // String의 기본값 null 출력 
		System.out.println("현재 Tv의 전원상태 : " + t2.power); // boolean의 기본값 false 출력
		t2 = t; // t의 주소값을 t2에 대입
		System.out.println("현재 채널은 " + t2.channel + "입니다."); // t2의 기본값이 0이였지만 t의 메모리를 가리켜서 6이 된다.
	}

}

class Tv{
	// Tv의 속성(맴버변수)
	String color; // 색깔
	boolean power; // 전원상태 on, off
	int channel; // 채널
	
	// Tv의 기능(메서드)
	void power() { power = !power; } // Tv를 켜거나 끄는 기능을 하는 메서드
	void channelUp() { ++channel; } // Tv의 채널을 높이는 기능을 하는 메서드
	void channelDown() { --channel; } // Tv의 채널을 낮추는 기능을 하는 메서드
	
}

package javajungsuk6;

import java.util.Arrays;

public class Ch06_8 {

	public static void main(String[] args) {
		// 6-8 객체 배열
		
		// 객체 배열 == 참조변수 배열
		
		// Tv2 t1, t2, t3; >> 더 나은 방법
		// Tv2[] tvArr = new Tv2[3]; / 참조변수의 기본값은 null이다.
		
		// 배열의 각 요소에 객체를 생성해서 저장해주면 된다.
		// tvArr[0] = new Tv2();
		// tvArr[1] = new Tv2();
		// tvArr[2] = new Tv2();
		
		// 위의 것과 같지만 더 간단하게 작성을 할 수 있다.
		Tv2[] tvArr = {new Tv2(), new Tv2(), new Tv2()};
		System.out.println(Arrays.toString(tvArr)); // 클래스이름@객체주소 배열로 출력
	} // main의 끝

}

class Tv2{
	// Tv의 속성(맴버변수)
	String color; // 색깔
	boolean power; // 전원상태 on, off
	int channel; // 채널
	
	// Tv의 기능(메서드)
	void power() { power = !power; } // Tv를 켜거나 끄는 기능을 하는 메서드
	void channelUp() { ++channel; } // Tv의 채널을 높이는 기능을 하는 메서드
	void channelDown() { --channel; } // Tv의 채널을 낮추는 기능을 하는 메서드
	
}

package javajungsuk6;

public class Ch06_9a10 {

	public static void main(String[] args) {
		// 6-9 ~ 6-10 클래스의 정의
		
		// 클래스를 정의하는 것 3가지 : 설계도, 데이터 + 함수, 사용자 정의
		// 1. 변수는 하나의 데이터를 저장할 수 있는 공간이다.
		// 2. 배열은 같은 타입의 여러 데이터를 저장할 수 있는 공간이다.
		// 3. 구조체는 타입은 달라도 서로 관련된 데이터라면 저장할 수 있는 공간이다. int float char 등 관련이 되어있다면 가능하다.
		// 4. 클래스는 구조체 + 함수라고 보면 된다. (데이터와 함수의 결합) / 매서드는 명령문을 묶은 것
		
		// 시, 분, 초
		Time time = new Time();
		
		// 시, 분, 초를 각 몇개씩 만들기
		// Time time1 = new Time();
		// Time time2 = new Time();
		// Time time3 = new Time();
		
		// 객체배열로 시는 시끼리, 분은 분끼리, 초는 초끼리 묶기
		Time[] timeArr = new Time[3];
		timeArr[0] = new Time();
		timeArr[1] = new Time();
		timeArr[2] = new Time();
		
		// 비객체지향 코드
		// int hour = 12;
		// int minute = 30; 
		// int second = 10;

		// 객체지향 코드
		time.hour = 12;
		time.minute = 30;
		time.second = 10;
		
		System.out.println("현재는 " + time.hour + "시 " + time.minute + "분 " + time.second + "초 입니다.");
		
		// 복잡한 예시
		// 시, 분, 초
		// int hour, minute, second;
		
		// // 시, 분, 초를 각 몇개씩 만들기
		// int hour1, hour2, hour3;
		// int minute1, minute2, minute3;
		// int second1, second2, second3;
		
		// // 시는 시끼리, 분은 분끼리, 초는 초끼리 묶기
		// int[] hourArr = {hour1, hour2, hour3};
		// int[] minuteArr = {minute1, minute2, minute3};
		// int[] secondArr = {second1, second2, second3};
		
	}// main의 끝

}

class Time {
	// 위의 복잡함을 해결하기 위해 class를 사용한다.
	int hour, minute, second;
}

package javajungsuk6_10;

public class Ch06_11 {

	public static void main(String[] args) {
		// 6-11 선언위치 변수 종류
		
		// 선언의 위치는 클래스와 매서드 영역
		// 클래스 영역 : 인스턴스 변수와 클래스 변수
		// 메서드 영역 : 지역변수 / 메서드 내에 선언된 변수

		// 생성시기
		System.out.println("중요 - iv : 인스턴스가 생성되었을 때 생성 - 객체 생성"); // 객체는 iv변수 묶음이다.
		System.out.println("cv : 클래스가 메모리에 올라갈 때 생성 - 필요할 때 클래스(설계도)가 메모리에 올라가고(로딩) CPU가 읽을 수 있고 객체를 생성한다."); // static + iv = cv
		System.out.println("lv : 변수 선언문이 수행되었을 때 생성");

		// 특징
		System.out.println("iv는 참조변수가 없어지면 가비지 컬렉터(GC)로 인해 객체가 제거된다.");
		System.out.println("cv는 static이기 때문에 객체생성을 하지 않아도 된다.");

	} // main의 끝

} 

class Variables {
	int iv; // 인스턴스 변수
	static int cv; // 클래스 변수 (static 변수, 공유변수)

	void method() {
		int lv = 0; // 지역변수(로컬)
		System.out.println(lv);
	}
}

package javajungsuk6_10;

public class Ch06_12a13 {

    public static void main(String[] args) {
        // 6-12 ~ 6-13 클래스 변수, 인스턴스 변수

        // 개별 : 객체마다 다르게 유지되어야 하는 값
        // 공통 : 공통속성이 유지되어야 하는 값
        // cv는 클래스의 이름으로 사용하여야 하며, 객체생성을 하지 않아도 자동으로 생성이 된다.

        Card c = new Card();
        c.kind = "Heart";
        c.number = 5;

        // 참조변수를 사용하는 이 방법이 틀린 것은 아니지만 권장하는 방법은 아니다.
        // c.width = 150;

        // static 변수를 사용할 때는 클래스의 이름으로 사용하는 것이 좋다.
        Card.width = 100; // 폭을 100으로 따로 변경해주었다.

        System.out.println(" 이 카드의 무늬는 " + c.kind + "이며, " + "숫자는 " + c.number + "입니다.");
        System.out.println(" 폭은 " + Card.width + "이며, " + "높이는 " + Card.height + "입니다.");


    } // main의 끝

}

class Card {
    // 개별
    String kind; // 무늬
    int number; // 숫자

    // 공통
    static int width = 150; // 폭
    static int height = 250; // 높이

}

package javajungsuk6_10;

public class Ch06_14a16 {
    public static void main(String[] args) {
        // 6-14 ~ 6-16 메서드란? 메서드의 선언부와 구현부

        // 메서드 : 문장들을 묶어놓은 것
        // 메서드 호출(사용) : 값을 받아서 처리하고 출력한다. / 입력과 반환
        // 코드중복을 보기좋게 바꾸고 사용하기 위해 {}로 묶어서 코드를 한 묶음으로 만든다.
        // 매개변수 : 작업에 필요한 값들 / 0~n개 입력 가능하다.
        // 출력 : 0~1개 까지만 가능하다. / 작업결과가 여러개라면 배열, 하나의 객체로 묶어서 사용하면 된다. 방법은 나중에
        // 반환할 값이 없다면 반환타입에 void(없다는 뜻)라고 적어야 한다.

        // 객체 생성
        Math m = new Math();

        // 호출
        int result1 = m.add(3, 5);
        System.out.println(result1); // 8

        int result2 = m.multiply(3, 5);
        System.out.println(result2); // 15
    } // main의 끝

}

    class Math {
        int add(int x, int y) { // 선언부
            // 구현부
            int result = x + y;
            return result;
        }

        int multiply(int x, int y) { // 선언부
            // 구현부
            return x * y;
        } // add메서드에 있는 지역변수 x, y와 이름이 같아도 사용 가능하다. / 지역변수 : 메서드 모두 사용하면 사라진다.


    } // class의 끝