본문 바로가기

Java

Java(9) - 메소드 오버로딩, 클래스와 인스턴스, 생성자, static

728x90
반응형

<목차>

1) 메소드 오버로딩

   1-1) 개념, 조건, 장점

   1-2) 예제 풀이

2) 클래스와 인스턴스, 생성자

   2-1) 개념

   2-2) 예제 풀이

3) static

   3-1) 주요사항

   3-2) 예제 풀이

 

 

 

 

 

1) 메소드 오버로딩

1-1) 개념, 조건, 장점

메소드 오버로딩(overloading)이란 같은 이름의 메소드를 중복하여 정의하는 것을 말함

 

오버로딩 조건

  • 메소드의 이름이 같아야 한다.
  • 파라미터의 개수가 달라야 한다.
  • 파라미터의 데이터 타입이 달라야 한다.
  • 파라미터의 순서가 달라야 한다.

 

오버로딩 장점

Java에서는 원래 한 클래스 내에 같은 이름의 메소드를 두 개 이상 가질 수 없다.

하지만 오버로딩을 통해, 하나의 이름으로 메소드를 만들 수 있다.

 

(1) 메소드에 사용되는 이름을 절약

(2) 메소드를 호출할 때 전달해야 할 매개변수의 타입이나 개수에 대해 크게 신경을 쓰지 않고 호출

 

메소드 오버로딩은 객체 지향 프로그래밍의 특징 중 하나인 다형성(polymorphism)을 구현한 것이다!

 

 

 

 

1-2) 예제 풀이

패키지 chapter07.method

Overloading.class

package chapter07.method;

public class Overloading {

	public static void main(String[] args) {
		/*
		    오버로딩 조건
		    - 메소드 이름이 같아야 한다.(필수)
		    - 파라미터 개수가 달라야 한다.
		    - 파라미터 타입이 달라야 한다.
		    - 파라미터 순서가 달라야 한다.
		    
		    장점
		    - 반복작업을 피할 수 있다.
		    - 모듈화로 인해 전체적 코드의 가독성을 높인다.
		    - 기능의 변경이 필요할 때 유지보수가 쉽다.
		*/
		
		getMax(5);
		getMax(5, 3.14);
		getMax(3.14, 5);
		System.out.println("[3, 5] = " + getMax(3, 5));
		System.out.println("[3.4, 5.6] = " + getMax(3.4, 5.6));

	}
	
	static void getMax(int a) {
		System.out.println(a);
	}
	
	static void getMax(int a, double b) {
		System.out.println(a + b);
	}
	
	static void getMax(double a, int b) {
		System.out.println(a * b);
	}
	
	static int getMax(int a, int b) {
		if (a > b) return a;
		else       return b;
	}
	
	static double getMax(double a, double b) {
		if (a > b) return a;
		else       return b;
	}

}

 

 

 

 

+) 가변 인자

MethodTest5.class

package chapter07.method;

public class MethodTest5 {

	public static void main(String[] args) {
		// 가변 인자(variable arguments)
		System.out.println(getSum(1, 2));
		System.out.println(getSum(1, 2, 3, 4));
		System.out.println(getSum(1, 2, 3, 4, 5, 6, 7));

	}
	
	/*
	    가변 인자를 사용할 경우, 오버로딩된 메서드들 간의 구분이 되지 않아
	    가급적 가변 인자를 사용한 메서드는 오버로딩 하지 않는 것이 좋다!
	*/
	static int getSum(int... a) { // 가변 인자를 내부적으로 배열로 사용
		int sum = 0;
		for (int i : a) {
			sum += i;
		}
		return sum;
	}

}

 

 

 

 

 

 

2) 클래스와 인스턴스, 생성자

2-1) 개념

클래스와 인스턴스

(정의한 클래스명) (인스턴스 명) = new 생성자();

 

클래스와 인스턴스의 관계 : 클래스가 붕어빵 틀이라 하면 인스턴스는 붕어빵 하나하나를 말한다!

 

 

생성자

생성자란 클래스를 통해 생성되는 인스턴스의 초기화를 도와주는 메소드의 일종

클래스 내에 선언되며, 클래스의 이름과 같으며, return 값이 없다.

생성자도 오버로딩이 가능하므로 하나의 클래스에 여러 개의 생성자가 존재 가능하다.

 

 

기본 생성자와 명시적 생성자

클래스를 생성하게 되면 컴파일러가 자동적으로 기본 생성자를 만들어 주며,

명시적 생성자를 새로이 생성하게 되면 컴파일러가 생성자가 있다고 판단하여

기본 생성자를 추가해 주어야 한다.

 

 

 

 

2-2) 예제 풀이

패키지 chapter08.classPart

Class_basic1.class

package chapter08.classPart;

class Car {
	// 멤버 변수, 속성, 필드
	String name;
	boolean gasoline;
	
	// 기본 생성자 : 인스턴스가 새로 생성될 때마다 실행됨!
	Car() {
		System.out.println("기본 생성자 호출");
	}
	
	// 명시적 생성자
	Car(String aName, boolean aGasoline) {
		System.out.println("명시적 생성자 호출");
		name = aName;
		gasoline = aGasoline;
	}
	
	// 멤버 메서드
	void run() {
		if (gasoline)      System.out.println("부릉 부릉");
		else               System.out.println("덜컹 덜컹");
	}
	void stop() {
		System.out.println("끼이익");
	}
}


public class Class_basic1 {

	public static void main(String[] args) {
		// 여기서 클래스 또한 일종의 데이터 타입이라는 사실을 반드시 기억할 것!!
		Car korando = new Car(); // (정의한 클래스명 == 데이터 타입) (인스턴스 명) = new 생성자();
		korando.name = "코란도C";
		korando.gasoline = false;
		System.out.println(korando.name + " : ");
		korando.run();
		
		/*
		// 기본 생성자 호출 : 명시적 생성자가 존재할 시 기본 생성자는 자동으로 생성되지 않기에 기본 생성자를 따로 명시하지 않으면 에러가 발생함!
		Car equus = new Car();
		equus.name = "에쿠스";
		equus.gasoline = true;
		System.out.println(equus.name + " : ");
		equus.run();
		*/
		
		// 명시적 생성자 호출
		Car equus = new Car("에쿠스", true);
		System.out.println(equus.name + " : ");
		equus.run();

	}

}

 

 

 

 

Class_basic2.class

package chapter08.classPart;

class Human {
	int age;       // 멤버 변수
	String name;
	
	void intro() { // 멤버 메서드
		System.out.println("안녕, " + age + "살 " + name + "이야");
	}
	
	// 기본 생성자
	Human() {}
	
	// 명시적 생성자
	Human(String aName, int aAge) {
		name = aName;
		age = aAge;
	}
}

public class Class_basic2 {

	public static void main(String[] args) {
		/*
		     [용어]
		           객체 - 객체지향 프로그램의 대상, 생성된 인스턴스
		           클래스 - 객체를 프로그래밍하기 위해 코드로 만든 상태
		           인스턴스 - 클래스가 메모리에 생성된 상태
		           멤버 변수 - 클래스의 속성, 특성
		           메서드 - 멤버 변수를 이용하여 클래스의 기능을 구현
		           참조 변수 - 메모리에 생성된 인스턴스를 가리키는 변수
		           참조값 - 생성된 인스턴스의 메모리 주소 값
		           생성자 - 클래스를 처음 만들 때 멤버 변수나 상수를 초기화
		*/
		
		// 기본 생성자
		Human basic = new Human();
		basic.age = 24;
		basic.name = "황상범";
		System.out.println("기본 생성자 출력 결과" + " : ");
		basic.intro();
		
		// 명시적 생성자
		Human define = new Human("황생밤", 27);
		System.out.println("명시적 생성자 출력 결과" + " : ");
		define.intro();

	}

}

 

 

 

 

User.class

package chapter08.classPart;

public class User {
	String name;
	int age;

	public void userInfo() {
		System.out.println("이름: " + name + ", 나이: " + age);
	}
	
	// 단축키 alt shift s > o
	public User(String name, int age) {
		/*
		    this
		    - 클래스 내부에서 해당 인스턴스를 부를 이름이 없음
		    - 인스턴스 이름이 각자 달라지기 때문에 this를 사용해서 자신을 가리킴
		*/
		
		this.name = name;
		this.age = age;
	}
	
	public User(String name) {
		this.name = name;
	}

	public User() {
	}
	
}

 

 

 

Constructor1.class

package chapter08.classPart;

public class Constructor1 {

	public static void main(String[] args) {
		/*
		     * 생성자 규칙
		     - 생성자는 이름이 클래스와 같다.
		     - 클래스 생성 시 생성자를 넣지 않아도 기본 생성자가 생성된다.
		     - 부모 클래스는 자식 클래스보다 먼저 생성되어야 한다.
		     - 리턴 타입을 갖지 않는다.
		     - 명시적 생성자가 있으면 기본 생성자는 별도로 생성해야 한다.
		*/
		
		User user1 = new User();
		user1.userInfo();
		
		User user2 = new User("홍길동");
		user2.userInfo();
		
		User user3 = new User("이순신", 70);
		user3.userInfo();

	}

}

 

 

 

 

 

3) static

3-1) 주요사항

static 영역은 stack, heap 영역보다 먼저 생성되기에 stack과 heap 영역에서 static 영역을 참조할 수 없다!

static 영역은 클래스 내부에서 가장 먼저 생성되고 실행된다!

 

 

 

3-2) 예제 풀이

Time.class

package chapter08.classPart;

import java.time.LocalTime;

public class Time {
	/*
	    * 필드, 속성, 멤버 변수의 초기화 순서
	    1. 클래스 변수 : 기본값 > 명시적 초기화 > 클래스 초기화 블록
	    2. 인스턴스 변수 : 기본값 > 명시적 초기화 > 인스턴스 초기화 블록
	*/
	
	static final int num = 999; // 클래스 변수
	// 인스턴스 변수
	boolean am;
	int hour;
	int minute;
	int second;
	
	// 클래스 초기화 블록
	static {
		System.out.println("static 초기화 블록");
	}
	
	// 인스턴스 초기화 블록
	{
		System.out.println("instance 초기화 블록");
		LocalTime now = LocalTime.now();
		this.hour = now.getHour();
		if (hour >= 12) {
			hour -= 12;
			am = false;
		} else {
			am = true;
		}
		minute = now.getMinute();
		second = now.getSecond();
	}
	
	Time() {}  // 기본 생성자

	// 리턴 타입이 없기 때문에 메서드명 앞에 반환할 값이 자료형 부분 값이 비어있고, public(접근 지정자)만 옴!!
	public Time(boolean am, int hour, int minute) {
		this.am = am;
		this.hour = hour;
		this.minute = minute;
		this.second = 0;
	}

	public Time(int hour, int minute) {
		this.am = hour < 12;
		this.hour = hour % 12;
		this.minute = minute;
		this.second = 0;
	}
	
	void whatTime() {
		System.out.println(am ? "오전" : "오후");
		System.out.println(hour + "시 " + minute + "분 " + second + "초");
	}
	
	

}

 

 

 

Constructor2.class

package chapter08.classPart;

public class Constructor2 {

	public static void main(String[] args) {
		Time t = new Time();
		
		System.out.println(t.num);
		System.out.println(Time.num);  // 클래스이름.static 변수
		
		method();
		
		Constructor2 c2 = new Constructor2();
		c2.method2();

	}
	
	public static void method() {}
	public void method2() {}

}

 

 

 

 

Constructor3.class

package chapter08.classPart;

public class Constructor3 {

	public static void main(String[] args) {
		Time now = new Time(true, 12, 34);
		now.whatTime();
		
		System.out.println("===============");
		Time today = new Time(18, 30);
		today.whatTime();

	}

}

 

 

 

 

Constructor4.class

package chapter08.classPart;

class Product {
	static int count = 0;   // 생성된 인스턴스의 수를 저장하기 위한 변수
	int serialNo;           // 인스턴스 고유 번호
	
	static int snum;        // 클래스 초기화, 클래스 변수
	int num = 1;            // 명시적 초기화, 인스턴스 변수
	
	// 클래스 초기화 블록
	static {
		snum = 999;
		System.out.println("static: " + snum);
	}
	
	// 인스턴스 초기화 블록 : new 키워드를 통해 인스턴스를 새로 생성할 때마다 인스턴스 초기화 블록 내부의 코드가 실행됨!
	{
		++count;
		serialNo = count;
	}
	
	// 기본 생성자
	Product() {
		num++;
	}
}

public class Constructor4 {

	public static void main(String[] args) {
		Product p1 = new Product();  // 해당 코드가 수행될 때(인스턴스가 생성될 때) "static: 999"를 출력하는 코드가 실행됨!
		Product p2 = new Product();
		Product p3 = new Product();
		
		System.out.println("p1의 제품번호(serialNo)는 " + p1.serialNo);
		System.out.println("p2의 제품번호(serialNo)는 " + p2.serialNo);
		System.out.println("p3의 제품번호(serialNo)는 " + p3.serialNo);
		System.out.println("생산된 제품 총수는 " + Product.count + "개");
		
		// 인스턴스 변수는 인스턴스가 생성될 때마다 초기화된다!
		System.out.println(p1.num);
		System.out.println(p2.num);
		System.out.println(p3.num);

	}

}

 

 

 

 

StaticTest.class

package chapter08.classPart;

class Student {
	public static int serialNum = 1000;
	public int studentID;
	public String studentName;
	public int grade;
	public String address;
	
	// 기본 생성자
	public Student() {
		serialNum++;
		studentID = serialNum;
	}
}

public class StaticTest {

	public static void main(String[] args) {
		int a = Student.serialNum;
		System.out.println(a);
		
		Student studentLee = new Student();
		System.out.println("학번:" + studentLee.serialNum);
		
		Student studentSon = new Student();
		System.out.println("학번:" + studentSon.serialNum);

	}

}