Study Web Development

11월 4일

이전으로

자바

6. 클래스와 객체

6-8 메서드 오버로딩

  1. 새 패키지 kr.s02.overloading 생성하고 새 클래스 OverloadingMain01 생성
package kr.s02.overloading;

public class OverloadingMain01 {
	// 메서드 오버로딩
	public void print(int n) {
		System.out.println("정수 n = " + n);
	}
	/*
	public void print(int a) { // 인자의 수를 점검하고, 자료형을 점검하였으나 차이가 없어 처음 정의한 메서드와 동일한 메서드로 인식되고 오류 발생
		System.out.println("정수 a = " + a);
	}
	*/
	public void print(double a) { // 인자의 자료형이 다르기 때문에 다른 메서드로 인식됨
		System.out.println("실수 a = " + a);
	}
	public void print(double n, long a) {
		System.out.println("실수 n = " + n + ", 정수 a = " + a);
	}
	public void print(long a, double n) { // 인자 자료형들의 배치 순서가 다르기 때문에 다른 메서드로 인식됨
		System.out.println("실수 n = " + n + ", 정수 a = " + a);
	}

	public static void main(String[] args) {
		OverloadingMain01 ot = new OverloadingMain01();
		ot.print(1000); // 첫 메서드 호출
		ot.print(20d); // 세 번째 메서드 호출
		ot.print(20d, 1000l); // 네 번째 메서드 호출
		ot.print(1000l, 20d); // 마지막 메서드 호출
	}
}
  1. 새 클래스 OverloadingMain02 생성
    • 이클립스에서 메서드명 위에 커서를 올리면 API 문서를 읽어와 보여주기 때문에 인자의 자료형이나 반환형 등을 바로 알 수 있음
package kr.s02.overloading;

public class OverloadingMain02 {
	// 전달되는 인자의 자료형을 String으로 변환하여 문자열의 길이를 구하는 메서드 만들기
	public void getLength(int n) {
		String s = String.valueOf(n);
		getLength(s); // println을 반복적으로 쓰는 대신, 이미 정의한 메서드를 호출; s가 String이기 때문에 인자가 String인 getLength를 호출하게 됨
	}
	void getLength(float n) {
		String s = String.valueOf(n);
		getLength(s);
	}
	private void getLength(String s) {
		System.out.println(s + "의 길이 : " + s.length());
	}
	
	public static void main(String[] args) {
		OverloadingMain02 om = new OverloadingMain02();
		om.getLength(1000); // 1, 0, 0, 0 각각이 문자로 취급되는 문자열의 길이를 구함
		om.getLength(3.14f); // 3, ., 1, 4 각각이 문자로 취급되는 문자열의 길이를 구함
		om.getLength("Hello");
	}
}

6-6 캡슐화

  1. 새 패키지 kr.s03.capsule 생성 후 새 클래스 CapsuleMain 생성
package kr.s03.capsule;

class Capsule {
	// 은닉화; 중요한 요소를 감춤
	private int a; // 변수를 같은 클래스에서만 접근 가능하도록 제한

	// 캡슐화; 은닉화된 요소를 대신할 수 있는 요소를 만드는 것
	public void setA(int n) { // 외부에서 데이터를 받아 오는 메서드
		if(n>=0) { // 데이터 검증
			a = n;
		}
		else {
			System.out.println("음수는 허용되지 않습니다.");
		}
	} 	
	public int getA() { // 외부에서 데이터를 읽게 하는 메서드
		return a;
	}
}

public class CapsuleMain {
	public static void main(String[] args) {
		Capsule cap = new Capsule();
		
		// cap.a = -10; // 객체 cap의 멤버 필드 a는 접근 지정자(=접근 제한자)가 private이기 때문에 다른 클래스에서 호출 불가능
		
		cap.setA(100); // 메서드를 통해 변수에 데이터를 저장
		System.out.println(cap.getA()); // 메서드를 통해 변수의 데이터를 호출
		
		cap.setA(-10); // 잘못된 데이터 전달시 메서드에서 차단되므로 변수의 데이터는 보호됨
		System.out.println(cap.getA());
	}
}

6-9 생성자

  1. 새 패키지 kr.s04.constructor 생성하고 새 클래스 CarMain01 생성
package kr.s04.constructor;

class Car {
	String color; // 색상
	String gearType; // 변속기 종류
	int door; // 문의 수
	
	public Car() {} // 기본 생성자; 생략 가능
}

public class CarMain01 {
	public static void main(String[] args) {
		Car c1 = new Car(); // new 연산자 다음에 생성자가 와서 멤버 변수를 초기화함
		System.out.println("c1.color : " + c1.color);
		System.out.println("c1.gearType : " + c1.gearType);
		System.out.println("c1.door : " + c1.door);
		c1.color = "white";
		c1.gearType = "auto";
		c1.door = 4;		
		System.out.println(c1.color + ", " + c1.gearType + ", " + c1.door);
		
		Car c2 = new Car(); // 새롭게 객체를 생성함
		c2.color = "red";
		c2.gearType = "manual";
		c2.door = 5;
		System.out.println(c2.color + ", " + c2.gearType + ", " + c2.door);
	}
}
생성자 오버로딩
  1. 새 클래스 CarMain02 생성
package kr.s04.constructor;

class Car2 { // 같은 패키지에 같은 클래스가 있으면 충돌
	String color;
	String gearType;
	int door;
	
	// 생성자 오버로딩
	public Car2() {} // 기본 생성자
	public Car2(String c, String g) { // 인자가 있는 생성자; 객체를 생성하면서 원하는 데이터로 바로 초기화 가능
		color = c;
		gearType = g;
		door = 4;
	}
	public Car2(String c, String g, int d) {
		color = c;
		gearType = g;
		door = d;
	}	
}

public class CarMain02 {
	public static void main(String[] args) {
		// Car2 c1 = new Car2();
		
		Car2 c2 = new Car2("blue", "auto");
		System.out.println(c2.color + ", " + c2.gearType + ", " + c2.door);
		
		Car2 c3 = new Car2("black", "auto", 2);
		System.out.println(c3.color + ", " + c3.gearType + ", " + c3.door);
	}
}

  1. 새 클래스 AccountMain 생성
package kr.s04.constructor;

public class AccountMain {
	// 멤버 변수
	String accountNo; // 계좌 번호
	String ownerName; // 예금주명
	int balance; // 잔고
	
	// 생성자
	public AccountMain(String a, String o, int b) {
		accountNo = a;
		ownerName = o;
		balance = b;
		System.out.println("계좌 생성이 완료되었습니다.");
	}
	
	// 멤버 메서드
	public void deposit(int amount) { // 예금하기
		balance += amount;
		System.out.println("입금이 완료되었습니다.");
	}
	public void withdraw(int amount) { // 출금하기
		balance -= amount;
		System.out.println("출금이 완료되었습니다.");
	}
	public void printAccount() { // 계좌 정보 보기
		System.out.println("계좌번호 : " + accountNo);
		System.out.println("예금주명 : " + ownerName);
		System.out.printf("잔고 : %,d원\n", balance);
	}
	
	public static void main(String[] args) {
		// 계좌 생성
		AccountMain am = new AccountMain("100-123", "홍길동", 1000);
		// 계좌 정보
		am.printAccount();
		//입금
		am.deposit(1000);
		am.printAccount();
		//출금
		am.withdraw(2000);
		am.printAccount();
	}
}
  1. 새 클래스 CarMain03 생성
package kr.s04.constructor;

public class CarMain03 {
	// 생성자 오버로딩
	public CarMain03(int n) {
		this(String.valueOf(n)); // 생성자 내에서 또 다른 생성자를 호출할 때는 생성자명을 쓸 수 없고 this를 사용; 생성자명으로 호출하는 것은 객체 생성시에, new 연산자 바로 다음에만 허용됨  
	}
	public CarMain03(float n) {
		// System.out.println("float 데이터 변환"); // 생성자 내에서 또 다른 생성자를 호출하기 전에 수행문을 배치하면 오류 발생; 다른 생성자 호출을 우선적으로 처리해야 할 중요한 초기화 작업으로 간주하기 때문
		this(String.valueOf(n));
		System.out.println("float 데이터 변환");
	}
	public CarMain03(String s) {
		System.out.println(s + "의 길이 : " + s.length());		
	}

	public static void main(String[] args) {
		CarMain03 cm1 = new CarMain03(2000); // 메서드와 마찬가지로 문자열의 길이를 구하는 작업을 수행할 수 있지만, 객체 생성시의 1회만 수행 가능
		CarMain03 cm2 = new CarMain03(3.141592f);
		CarMain03 cm3 = new CarMain03("Hello");
	}
}

6-10 this와 this()

  1. 새 패키지 kr.s04.thistest를 생성하고 새 클래스 LocalVariable 생성
package kr.s04.thistest;

public class LocalVariable { // 클래스 영역 시작
	int b = 200; // 멤버 변수; 같은 객체의 메서드들에서 모두 호출 가능
	
	public void make() {
		int a = 100; // 지역 변수; make 메서드를 구동할 때만 호출 가능
		System.out.println("a : " + a);
		System.out.println("b : " + b);
	}
	
	public void fun() {
		// System.out.println("a : " + a); // fun 메서드 안에서 a 변수가 정의되지 않아서 호출 불가
		System.out.println("b : " + b);
	}
	
	public static void main(String[] args) {
		for(int i=1;i<=5;i++) { // i는 for문 블럭 안의 지역 변수
			System.out.print(i+"\t");
		} // for문 블럭 종료시 i가 소멸하므로 이후 수행문에서 호출 불가
		// System.out.println(i);
		
		int a; // a는 main 블럭 안의 지역 변수
		for(a=1;a<=5;a++) {
			System.out.print(a + "\t");
		} // 반복문이 종료되어도 main 블럭 안에 a가 있어 이후 수행문에서 호출 가능
		System.out.println(a);
	} // main 블럭 종료시 a 소멸
} // 클래스 영역 끝

  1. 새 클래스 ThisMain 생성
package kr.s04.thistest;

public class ThisMain {
	public ThisMain() {
		System.out.println("객체 생성 : " + this); // this는 객체 내부의 참조 변수 역할; 객체의 참조값을 가지고 있으며 객체 내부에서 객체를 지칭할 때 사용
	}
	
	public static void main(String[] args) {
		ThisMain tt = new ThisMain(); // 생성된 객체 주소의 유니크한 참조값을 참조 변수 tt에 저장; 자바는 주소를 내부적으로만 처리하며, 프로그래머가 같은 객체인지를 판단할 수 있게끔 유니크한 16진수 해시값만 제공함
		System.out.println("객체 생성 후 : " + tt);
	}
}
  1. 새 클래스 ThisMain02 생성
package kr.s04.thistest;

class ThisTest {
	// 은닉화
	private int a;

	// 캡슐화
	public void setA(int a) { // 지역 변수 a 선언
		// a = a; // {} 블럭 내에서 a는 지역 변수로 인식됨
		this.a = a; // 멤버 변수명과 지역 변수명을 동일하게 명시했기 때문에, 멤버 변수와 지역 변수를 구분하기 위해 this.를 사용
	}
	public int getA() {
		return a;
	}	
}

public class ThisMain02 {
	public static void main(String[] args) {
		ThisTest tt = new ThisTest();
		tt.setA(200);
		System.out.println(tt.getA());
	}
}
  1. 새 클래스 ThisMain03 생성
    • 이클립스에서 멤버 변수들을 private으로 선언하고 오른쪽 클릭 후 Source-Generate Getters and Setters... 선택시, 표준 문법에 맞게 캡슐화하는 코드가 자동으로 작성됨
package kr.s04.thistest;

public class ThisMain03 {
	// 은닉화
	private String name;
	private String job;
	private int age;
	private int phone;
	private String address;
	private String hobby;
	private int level;
	
	// 캡슐화; 이클립스에서 자동으로 작성
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getPhone() {
		return phone;
	}
	public void setPhone(int phone) {
		this.phone = phone;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getHobby() {
		return hobby;
	}
	public void setHobby(String hobby) {
		this.hobby = hobby;
	}
	public int getLevel() {
		return level;
	}
	public void setLevel(int level) {
		this.level = level;
	}
}

6-3 멤버 변수와 멤버 메서드

멤버 변수
멤버 메서드

6-11 static

  1. 새 패키지 kr.s05.statictest 생성하고(static은 예약어라 패키지명으로 사용 불가) 새 클래스 StaticCount 생성
package kr.s05.statictest;

public class StaticCount {
	int c; // 인스턴스 변수; 객체 생성시 메모리에 올라감
	static int count; // static 변수; 객체 생성과 무관하게 호출되면 메모리에 올라감

	public StaticCount() { // 생성자
		c++;
		count++;
	}
}
  1. 새 클래스 StaticMain01 생성
package kr.s05.statictest;

public class StaticMain01 {
	public static void main(String[] args) {
		// 객체의 멤버 변수 c는 객체가 새로 생성될 때마다 초기값 0으로 새로 만들어지고 생성자에 의해 값이 1이 됨; static 변수 count는 한 번만 만들어지고 그 변수를 계속 가져다 쓰기 때문에 생성자가 실행될 때마다 1씩 값이 증가하게 됨
		StaticCount sc1 = new StaticCount();
		System.out.println("c : " + sc1.c + ", count : " + StaticCount.count); // static 변수는 객체에 포함되어 있지 않으므로, 호출시 객체가 아니라 클래스를 통해 접근
		StaticCount sc2 = new StaticCount();
		System.out.println("c : " + sc2.c + ", count : " + sc2.count); // static 변수를 객체를 통해 접근할 경우 오류가 발생하지는 않지만, 정상적으로 호출하는 방법이 아님
		StaticCount sc3 = new StaticCount();
		System.out.println("c : " + sc3.c + ", count : " + StaticCount.count);
	}
}
  1. 새 클래스 StaticMain02 생성
package kr.s05.statictest;

public class StaticMain02 {
	int a; // 인스턴스 변수
	static String s; // static 변수
	
	public static void main(String[] args) { // 프로그램 실행시 main 메서드가 static 영역에 올라감
		// a = 10; // 인스턴스 변수는 객체 생성 이후에 호출
		s = "자바의 꿈"; // static 변수는 객체 생성과 무관하게 호출; main과 s가 같은 클래스에 있기 때문에 클래스명 생략해도 호출됨
		System.out.println("s = " + StaticMain02.s);
	}
}
  1. 새 클래스 StaticMain03 생성
package kr.s05.statictest;

class StaticMethod {
	String s1 = "스태틱";
	static String s2 = "static";
	
	public static String getString() { // static 메서드는 호출시 메모리에 올라감
		// return s1; // 인스턴스 변수는 객체를 생성하지 않으면 메모리에 올라가 있지 않음
		return s2; // static 변수는 호출시 메모리에 올라감; getString과 s2가 같은 클래스에 있어 호출시 클래스명 생략 가능
	}
}

public class StaticMain03 {
	public static void main(String[] args) {
		System.out.println(StaticMethod.getString()); // main의 클래스와 getString의 클래스가 같지 않으므로 클래스명을 명시해야 static 메서드에 접근 가능
	}
}

다음으로