ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 9. 객체지향프로그램3
    개발자 수업/Java 2021. 10. 6. 18:47

    1. 객체 자신을 가리키는 this
        1) 인스턴스 자신의 메모리를 가리킴
        2) this() : 생성자에서 또 다른 생성자를 호출할 때 사용
            - 클래스에 생성자가 여러 개인 경우, this()를 이용하여 생성자에서 다른 생성자를 호출
            - 생성자에서 다른 생성자를 호출하는 경우에는 인스턴스 생성이 미완성인 상태이므로 다른 수행문을 쓸 수 없음
        3) 자신의 주소를 반환

    public class Person {
    
    	private String name;
    	private int age;
    	
    	
    	public Person() {
    		this("no name", 20);
    	}
    	
    	public Person(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    	
    	public void showInfo() {
    		System.out.println(this.name + " " + this.age);
    	}
    	
    	public Person getPerson() {
    		return this;
    	}
    	
    	public static void main(String[] args) {
    		Person person = new Person();
    		person.showInfo();
    		
    		person.name = "이순신";
    		person.age = 30;
    		person.showInfo();
    		
    		Person person2 = person.getPerson();
    		System.out.println(person);
    		System.out.println(person2);
    	}
    }



    2. 객체 간의 협력(collaboration)
        1) OOP에서 협력
            - 필요한 메세지를 전송하고 이를 처리하는 기능이 구현되어야 함

            - 매개변수로 객체가 전달되는 경우가 발생

    public class Bus {
    	int busNumber;
    	int passengerCount;
    	int money;
    	
    	public Bus(int busNumber) {
    		this.busNumber = busNumber;
    	}
    	
    	public void take(int money) {
    		this.money += money;
    		passengerCount++;
    	}
    	
    	public void showInfo() {
    		System.out.println(busNumber + "번 버스의 승객은 " + passengerCount + "명 이고, 수익은 " + money + "원 입니다.");
    	}
    }
    public class Subway {
    
    	int lineNumber;
    	int passengerCount;
    	int money;
    	
    	public Subway(int lineNumber) {
    		this.lineNumber = lineNumber;
    	}
    	
    	public void take(int money) {
    		this.money += money;
    		passengerCount++;
    	}
    	
    	public void showInfo() {
    		System.out.println(lineNumber + "번 전철의 승객은 " + passengerCount + "명 이고, 수익은 " + money + "원 입니다.");
    	}
    }
    public class Taxi {
    	
    	String companyName;
    	int money;
    	
    	public Taxi(String companyName) {
    		this.companyName = companyName;
    	}
    	
    	public void take(int money) {
    		this.money += money;
    	}
    	
    	public void showInfo() {
    		System.out.println(companyName + " 택시 수입은 " + money +"원 입니다.");
    	}
    }
    public class Student {
    
    	String studentName;
    	int money;
    	
    	public Student(String studentName, int money) {
    		this.studentName = studentName;
    		this.money = money;
    	}
    	
    	public void takeBus(Bus bus) {
    		bus.take(1000);
    		this.money -= 1000;
    	}
    	
    	public void takeSubway(Subway subway) {
    		subway.take(1500);
    		this.money -= 1500;
    	}
    	
    	public void takeTaxi(Taxi taxi) {
    		taxi.take(10000);
    		this.money -= 10000;
    	}
    	
    	public void showInfo() {
    		System.out.println(studentName + "의 남은 돈은 " + money + "원 입니다.");
    	}
    }
    /*
     * 최지만은 지각을 해서 택시를 타야했습니다.
     * 20000원을 갖고 있었는데 10000원을 택시비로 사용했습니다.
     * 택시는 '이젠운수' 회사 택시를 탔습니다.
     * 
     * 출력
     * 최지만의 남은 돈은 10000원입니다.
     * 이젠운수 택시 수입은 10000원입니다.
     */
    
    public class CollaborationTest {
    	public static void main(String[] args) {
    		Student student1 = new Student("김광현", 5000);
    		Student student2 = new Student("최지만", 20000);
    		
    		Bus bus1000 = new Bus(1000);
    		Subway subwayGreen = new Subway(2);
    		Taxi taxiEzen = new Taxi("이젠운수");
    		
    		student1.showInfo();
    		bus1000.showInfo();
    		System.out.println();
    		
    		student1.takeBus(bus1000);
    		student1.showInfo();
    		bus1000.showInfo();
    		System.out.println("-------------------");
    		
    //		student2.showInfo();
    //		subwayGreen.showInfo();
    //		System.out.println();
    //		
    //		student2.takeSubway(subwayGreen);
    //		student2.showInfo();
    //		subwayGreen.showInfo();
    		
    		student2.showInfo();
    		taxiEzen.showInfo();
    		System.out.println();
    		
    		student2.takeTaxi(taxiEzen);
    		student2.showInfo();
    		taxiEzen.showInfo();
    	}
    }



    3. 여러 인스턴스에서 공통으로 사용하는 변수를 선언 => static 변수
        1) 공통으로 사용하는 변수 필요한 경우
            - 여러 인스턴스가 공유하는 기준 값이 필요한 경우
            - 학생마다 새로운 학번 생성
            - 회사에서 사원이 입사할 때 새로운 사번이 필요한 경우
            - 카드 회사에서 카드를 새로 발급할 때마다 새로운 카드 번호를 부여
        2) 데이터 영역 메모리
            - 공유
        3) static 변수 선언과 사용하기
            - 인스턴스가 생성될 때마다 만들어지는 변수가 아닌, 처음 프로그램이 로딩될 때 메모리를 할당받음
            - 클래스 변수, 정적 변수라고도 함 <----> 인스턴스 변수
            - 인스턴스 생성과 상관 없이 사용 가능하므로 클래스 이름으로 직접 참조
        4) static 메서드 구현과 활용
            - 클래스 메서드, 정적 메서드
            - 클래스 이름으로 호출 가능
            - 인스턴스 생성 전에 호출될 수 있으므로 static 메서드 내부에서는 인스턴스 변수를 사용할 수 없음

    /*
     * 	1) static 변수와 메서드는 인스턴스 변수와 메서드가 아니므로 클래스 이름으로 직접 참조
     * 	2) static 변수는 인스턴스에서 공통으로 사용하는 영역임을 알 수 있음
     */
    
    public class Employee {
    	
    	// class variable
    	private static int serialNum = 1000;
    	
    	// instance member variable
    	private int employeeId;
    	private String employeeName;
    	private String department;
    	
    	public Employee() {
    		serialNum++;
    		 this.employeeId = Employee.serialNum;
    	}
    	
    	
    	// class method 
    	public static int getSerialNum() {
    		return serialNum;
    	}
    
    
    
    	public static void setSerialNum(int serialNum) {
    		Employee.serialNum = serialNum;
    	}
    
    
    
    	public int getEmployeeId() {
    		return employeeId;
    	}
    
    	public void setEmployeeId(int employeeId) {
    		this.employeeId = employeeId;
    	}
    
    	public String getEmployeeName() {
    		return employeeName;
    	}
    
    	public void setEmployeeName(String employeeName) {
    		this.employeeName = employeeName;
    	}
    
    	public String getDepartment() {
    		return department;
    	}
    
    	public void setDepartment(String department) {
    		this.department = department;
    	}
    }
    
    
    
    
    public class EmployeeTest {
    
    	public static void main(String[] args) {
    		Employee employeeLee = new Employee();
    		employeeLee.setEmployeeName("이순신");
    		
    		Employee employeeLee2 = new Employee();
    		employeeLee2.setEmployeeName("이도");
    		
    		System.out.println(employeeLee.getEmployeeName() + ", " + employeeLee.getEmployeeId());
    		System.out.println(employeeLee2.getEmployeeName() + ", " + employeeLee2.getEmployeeId());
    		
    		System.out.println(Employee.getSerialNum());
    		
    		Employee.setSerialNum(1003);
    		System.out.println(Employee.getSerialNum());
    	}
    
    }



    4. 변수의 유효 범위와 메모리
        1) 변수의 유효 범위(scope)와 생성과 소멸(life cycle)은 각 변수의 종류마다 다름
        2) 지역변수, 멤버변수, 클래스 변수는 유효범위와 life cycle, 사용하는 메모리도 다름

        변수 유형   선언 위치       사용 범위       메모리      생성과 소멸
        -------------------------------------------------------------------------------------------------------------------
        지역변수    메서드 내부     메서드 내부     스택        함수가 호출될 때 생성되고
        (local                                                               함수가 끝나면 소멸됨
        variable)

        멤버변수    클래스 멤버     클래스 내부     힙          인스턴스가 생성될 때 힙에 생성되고
        (instance   변수로 선언                                       GC가 메모리 수거할 때 소멸됨
        variable)   

        static 변수  클래스 내부     클래스 내부 데이터 영역   프로그램이 처음 시작할 때 상수와 함께 생성되고 
        (class                                                               프로그램이 끝나고 메모리를 해제할 때 소멸됨
        variable)

        3) static 변수는 프로그램이 메모리에 있는 동안 계속 그 영역을 차지하므로 너무 큰 메모리를 할당하는 것은 좋지 않음

    /*
     * 변수의 종류			선언위치		생성시기
     * --------------------------------------------------------------------------------------
     * 클래스, 정적(static) 변수	클래스 영역	클래스가 메모리에 올라갈 때(인스턴스 생성하지 않아도 사용 가능)
     * 인스턴스 변수			클래스 영역	무조건 new 연산자로 인스턴스 생성 시
     * 지역 변수			메서드 영역	메서드가 호출될 때 생겨나고, 메서드 종료 시 소멸됨
     * 						(초기화가 반드시 필요, static 변수 사용 못함)
     */
    
    public class Card /* extends Object */ {
    	
    	// 인스턴스 변수 --- 반드시 인스턴스 생성해야 접근 가능 
    	private String color;
    	private String company;
    	
    	// static 변수 (=정적변수, 클래스변수, 공유변수) --- 인스턴스 생성 없이도 클래스명.static으로 접근 가능
    	static int width = 100;
    	static int height = 50;
    	
    	// 인스턴스 메서드
    	public String getColor() {
    		return color;
    	}
    	public void setColor(String color) {
    		this.color = color;
    	}
    	public String getCompany() {
    		return company;
    	}
    	public void setCompany(String company) {
    		this.company = company;
    	}
    	
    	@Override
    	public String toString() {
    		// TODO Auto-generated method stub
    		return "Card의 색상: " + this.getColor() + 
    				", Card의 회사: " + this.getCompany() +
    				", 크기 : (" + Card.height +
    				", " + Card.width + ")";
    	}
    	
    }
    
    
    
    
    
    public class CardTest {
    	public static void main(String[] args) {
    		
    		Card card = new Card();
    		card.setColor("노랑");
    		card.setCompany("국민은행");
    		System.out.println(card);
    		
    		Card.height = 150;
    		Card.width = 80;
    		
    		Card card2 = new Card();
    		card2.setColor("파랑");
    		card2.setCompany("농협");
    		System.out.println(card2);
    		
    	}
    }

    public class Calculator {
    	
    	// 인스턴스 메서드 : new 연산자로 인스턴스를 생성해야지만 참조변수명.인스턴스메서드명 으로 접근가능
    	public int add(int x, int y) {
    		double dresult = Calculator.divide(10.5, 11.7);
    		System.out.println("인스턴스 메서드 내에서 static 메서드 호출 : " + dresult);
    		return x + y;	
    	}
    	
    	// 인스턴스 메서드
    	public int substract(int x, int y) {
    		return x - y;
    	}
    
    	// 정적(static) 메서드 : 인스턴스 생성없이 클래스명.정적메서드명 으로 접근가능
    	public static long multiply(long x, long y) {
    		/*
    		 * static 메서드는 이미 메모리 상단에 올라가 있고 인스턴스 생성 없이 접근 가능해야 되는데
    		 * 인스턴스가 생성되어야지만 사용가능한 add()의 경우는 호출할 수 없음
    		 * 인스턴스가 언제 생성될지를 아무도 모르기 때문에 static 메서드 안에서는 인스턴스 메서드가 절대 오면 안 됨
    		 */
    		// this.add(10,5);
    		return x * y;
    	}
    	
    	// 정적 메서드
    	public static double divide(double x, double y) {
    		return x / y;
    	}
    }
    
    
    
    
    
    public class CalcuratorTest {
    	public static void main(String[] args) {
    		Calculator cal = new Calculator();
    		
    		// 인스턴스 메서드 호출
    		int addResult = cal.add(100, 200);
    		System.out.println("인스턴스 메서드 add() 호출결과 : " + addResult);
    		
    		// static 메서드 호출
    		long mulResult = Calculator.multiply(100, 20);
    		System.out.println("static 메서드 multiply() 호출결과 : " + mulResult);
    		
    		double divResult = Calculator.divide(100.2, 10.2);
    		System.out.println("static 메서드 divResult() 호출결과 : " + divResult);
    		
    	}
    }

     


    5. static 응용 -- 싱글톤 패턴(singleton pattern)
        1) 싱글톤 패턴이란?
            - 프로그램에서 인스턴스가 단 한 개만 생성되어야 하는 경우 사용하는 디자인 패턴
            - static 변수, 메서드를 활용하여 구현할 수 있음
        2) 싱글톤 만드는 방법
            - 해당 클래스 자신의 타입으로 정적 멤버 선언과 생성
            - 해당 클래스를 외부에서 new 연산자로 인스턴스 생성 못하게 생성자를 private으로 생성
            - 정적 멤버의 주소를 공유하기 위해서 외부에서 호출할 수 있는 getInstance() 제공함
        3) 싱글톤을 사용하는 이유
            - 단 하나의 인스턴스만 생성을 원하고자 할 때 사용함
            - ex) 사용자 환경설정(시간, 날짜정보), 커넥션 풀

     

    public class Company {
    	
    	// 외부에서 접근 못하도록 private 적용
    	private static Company instance = new Company();
    	
    	// 기본 생성자
    	private Company() {}
    	
    	// 외부에서 호출할 수 있도록 getInstance() 제공
    	public static Company getInstance() {
    		if(instance == null) {
    			instance = new Company();
    		}
    		return instance;
    	}
    }
    
    
    
    
    import java.util.Calendar;
    import java.util.Date;
    
    public class CompanyTest {
    	public static void main(String[] args) {
    		Company company1 = Company.getInstance();
    		Company company2 = Company.getInstance();
    		Company company3 = Company.getInstance();
    		
    		System.out.println(company1);
    		System.out.println(company2);
    		System.out.println(company3);
    		// 결과 값이 다 똑같음 kr.co.ezenac.singleton.Company@73a28541
    		
    		// Object 클래스의 equals() : 주소비교
    		if(company1.equals(company2)) {
    			System.out.println("같은 객체입니다.");
    		}
    		else {
    			System.out.println("다른 객체입니다.");
    		}
    		
    		// 객체의 == 연산자 : 주소값 비교연산
    		if(company2==company3) {
    			System.out.println("같은 객체입니다.");
    		}
    		else {
    			System.out.println("다른 객체입니다.");
    		}
    		
    		//Calendar calendar = new Calendar();
    		Calendar calendar = Calendar.getInstance();
    		Date date = calendar.getTime();
    		System.out.println(date);
    		
    	}
    }

    '개발자 수업 > Java' 카테고리의 다른 글

    11. 컬렉션 프레임워크  (0) 2021.10.07
    10. 배열  (0) 2021.10.06
    8. 객체지향프로그래밍2  (0) 2021.10.05
    6. Review / 7.객체지향프로그램  (0) 2021.10.04
    5. 반복문 (while문, do~while문, for문)  (0) 2021.10.01

    댓글