메서드와 생성자

주8·2023년 1월 5일
0

Method (메서드)

OOP에서 객체의 action(기능)을 정의하는 부분을 operation이라고 하는데 이 operation을 java에서는 method라고 한다.


메서드의 장점 및 작성 지침

  • 반복적인 코드를 줄이고 코드의 관리가 용이하다(재사용성).
  • 메서드를 보면 객체가 어떤 일을 하는지 알 수 있다.
  • 객체가 무슨 일을 해야 할지 정의할 수 있다.
  • 값을 설정하거나 가져올 수 있다.
  • 하나의 메서드는 한 가지 기능만 수행하도록 작성하는 것이 좋으며, 이를 통해 재사용성을 높일 수 있다.

메서드 이름 명명 규칙

  • 동사이면서 소문자로 시작한다.
  • 메서드 이름이 두 단어 이상인 경우 첫번째 단어를 제외하고 각 단어의 첫글자는 대문자여야 한다.
  • 예) sum(), areaOfCircle()

Calling method & Worker method

  • Calling method: 기능을 호출하는 메서드
  • Worker method: 호출되어 기능을 수행하는 메서드

Argument Object method(instance method)

  • Object method는 object를 생성해야만 호출할 수 있다.
  • Object method는 instance method라고도 하며, 메서드 내에서 인스턴스 변수를 사용할 수 있다.
    • 인스턴스 변수 → 일반적인 변수라고 보면 되고, 클래스 변수 → static 붙은 변수
  • Obejct method는 “참조변수명.method명()”으로 접근한다.

Access method (접근자 메서드) → getter

  • 인스턴스 변수를 read하는 메서드다. 메서드 앞에 get 단어가 붙어서 쉽게 식별할 수 있으며, getter라고도 한다.
  • private 변수의 값을 반환한다.
public int getNumber(){
	return number;
}

Mutator method (설정 메서드) → setter

  • 인스턴스 변수의 값을 수정하는 메서드로 메서드 앞에 set 단어가 붙기 때문에 쉽게 식별할 수 있다. setter라고도 한다.
  • 반환값이 없으며, 동일한 데이터 타입의 매개변수를 허용하여 private 변수의 값을 설정하는데 사용된다.
  • 외부에서 값을 변경할 필요가 없는 불변(immutable)객체의 경우 setter 메서드를 만들면 안 된다(예: 주소객체 등과 같은 생성 후 값이 변하지 않는 객체)
public void setNumber(int number){
	this.number = number;
}

Static method(class method)

  • object를 생성하지 않고 호출할 수 있으며 class method라고도 불린다.
  • 클래스의 인스턴스가 아닌 클래스에 속하는 메서드다.
  • static method는 method 정의시 static keyword를 사용한다.
  • Java API 중에도 static method들이 존재한다. (예: Math.random())
  • object의 생성 없이도 접근이 가능한 method를 정의할 때 사용한다(예를 들자면 Utility class의 문자변환 기능, 날짜 변환 기능 등)
  • static method는 “클래스명.method명()”으로 접근한다.
  • static method 예: Date today = Util.getDate(); //static method
public class StaticMethod{
	public static void main(String[] args){
		show();
	}
	static void show(){
		System.out.println("Static method 예제");
	}
}

Object method와 Static method 차이

  • 둘 다 같은 클래스의 멤버간에는 객체생성이나 참조변수 없이 참조할 수 있다.
    그러나 static 멤버들은 인스턴스 멤버들을 참조할 수 없고 static은 static간에 참조나 호출이 가능하다.
  • static method 영역은 객체 생성 없이 접근할 수 있지만 Object method는 객체 생성이 되어야만 호출될 수 있기 때문에 static 영역에서 바로 메서드 호출은 불가능하다(객체 생성하면 가능).
public class InstanceStaticMethod{
	//Object(instance) method
	void instanceMethod1(){}
	//static method
	static void staticMethod1(){}

	//instance method
	void instanceMethod2(){
		instanceMethod1(); //다른 instance method 호출
		staticMethod1(); //static method 호출
	}

	//static method
	static void staticMethod2(){
		//instanceMethod1(); //Error! 인스턴스를 호출할 수 없다
		InstanceStaticMethod instance = new InstanceStaticMethod();
		instance.instanceMethod1(); //성공
		staticMethod1();
	}
}

매개변수(Parameter)

  • 기본형 매개변수 - 변수의 값을 읽기만 할 수 있다(read only).
  • 참조형 매개변수 - 변수의 값을 읽거나 변경할 수 있다.
  • Call by Name
    • 이름으로 메서드를 호출하는 방식으로 특정 매개변수 없이 실행
    • 이미 결정된 결과를 출력하거나 고정된 실행을 요구하는 것 외에는 다른 기능이 없다.
    • 예) System.out.println();
  • Call by Value
    • 이름으로 메서드를 호출할 때 특정 매개변수를 전달하여 그 값을 이용해 실행
    • 매개변수는 개수 제한, 자료형 제약이 없다.
    • 예) System.exit(1);
  • Call by Reference
    • 메서드 호출 시 매개변수로 사용되는 값이 특정 위치를 참조

Pass by Value / Pass by Reference

  • 자바는 값을 인자에 의해서만 전달한다.
  • 한 객체의 인스턴스가 메소드의 인자로 전달될 때 그 인자의 값은 객체에 대한 레퍼런스(참조값)이다.
  • 객체의 내용은 호출된 메소드 내에서 변경될 수 있다. 그러나 객체의 레퍼런스는 절대 변경되지 않는다.
  • Pass by value: 메서드가 호출되면 호출자는 인수 변수의 복사본을 메서드에 전달하여 메모리에 두 개의 값을 생성한다.
  • Pass by Reference: 메서드가 호출될 때 메서드 인수는 메모리에서 호출자와 동일한 변수를 참조한다.
public static void main(String[] args){
	MyDate date;
	int var;

	val = 11;
	//기본형 변수의 값을 변경하기 위해 호출
	changeInt(val);
	System.out.println("Int value: " + val);

	date = new MyDate(2022, 7, 22);
	//참조 변수의 참조값을 변경하기 위해 메서드 호출
	chageObjectRef(date);
	//현재 멤버 변수의 값 출력 -> 원래 객체를 참조하고 있다.
	date.print();

	//참조변수의 setter 메서드로 객체의 멤버변수 값 수정
	chageObjectVar(date);
	//값이 변경된 걸 확인
	date.print();
}

public static void changeInt(int value){
	value = 55;
}
public static void changeObjectRef(MyDate ref){
	ref = new MyDate(2022,1,1);
}
public static void changeObjectVar(MyDate ref){
	ref.setDay(4);
}

Pass by Value

  • 기본 데이터 타입인 int 타입 foo 변수가 setFoo() 매개변수로 전달되면 메서드별로 두 개의 스택에 개별 변수가 만들어지면서 foo 변수 값의 복사본이 bar로 전달된다.
  • setFoo() 메서드 안에서 bar 매개변수의 값을 2로 변경한다.
public class PassByValueEx1{
	public static void main(String[] args){
		int foo = 1;
		System.out.println(foo); //1
		//Pass by Value
		setFoo(foo);
		System.out.println(foo); //1
	}

	public static void setFoo(int bar){ //bar = 1
		bar = 2;
	}
}

Pass by Reference

  • spill() 메서드가 호출되면 매개변수는 mugToBeSpilled 매개변수로 객체 참조 변수의 복사본이 전달된다.
  • spill() 메서드에서는 복사본 참조변수를 통해 contents의 값을 “Nothing”으로 변경한다.
  • myMug, mugToBeSpilled 두 참조변수 모두 하나의 객체를 바라본다.
public class Mug{
	private String contents;
	public Mug(String contents){
		this.contents = contents;
	}
	public void setContents(String contents){
		this.contents = contents;
	}
	public String getContents(){
		return contents;
	}
}

public class PassbyReferenceEx1{
	public static void main(String[] args){
		//Mug 클래스의 생성자를 호출하면서 contents 멤버변수에 초기화 값 "Tea"를 할당
		Mug myMug = new Mug("Tea");
		System.out.println(myMug.getContents());
		//myMug 객체 참조 변수의 참조값을 전달
		spill(myMug);
		//spill 메서드 종류 후의 myMug 인스턴스의 contents 값이 "Nothing"으로 변경됨
		System.out.println(myMug.getContents());
	}

	public static void spill(Mug mugToBeSpilled){
		//myMug와 mugToBeSpilled는 동일한 Mug 인스턴스를 참조한다
		//Mug 인스턴스의 setContents메서드로 값을 변경
		mugToBeSpilled.setContents("Nothing");
	}
}

Method overloading

하나의 클래스 내에 동일한 이름으로 동일한 작업을 하는 여러 개의 메서드를 구현하는 것

하나의 작업만 수행해야 하는 경우 메서드의 이름이 동일하면 프로그램의 가독성이 높아지고, 기능은 동일하나 매개변수 목록이나 타입에 따라 호출되는 메서드를 제어하고자 할 경우 사용된다.

오버로딩 조건

  • 메서드 이름이 동일해야 한다.
  • 매개변수의 개수 또는 타입이 달라야 한다.
  • return type, modifier는 오버로딩 조건에 영향을 미치지 않는다.
  • 매개변수는 같고 리턴타입이 다른 경우는 오버로딩 조건이 되지 않는다.
public class MethodOverloading{
	public static void main(String[] args){
		ClacAdder adder = new CalcAdder();
		//메서드 오버로딩 조건 성립 - 매개변수 개수가 다르다
		adder.add(10,20);
		adder.add(10,20,30);
		//메서드 오버로딩 조건 성립 - 매개변수 데이터 타입이 다르다
		adder.add(12,5D,21,7D);
	}
}

class CalcAdder{
	int add(int a,int b){
		return a+b;
	}
	double add(double a,double b){
		return a+b;
	}
	int add(int a,int b,int c){
		return a+b+c;
	}
}

생성자(Constructor)

생성자는 클래스의 인스턴스 생성에 사용되며, 객체가 생성될 때 멤버변수들의 값을 초기화하는 기능을 한다.

  • 클래스가 생성자 선언을 하지 않으면, 매개변수가 없는 디폴트 생성자(default constructor)가 자동으로 제공된다.
  • 기본 생성자는 데이터 타입에 따라 0, null과 같은 객체의 기본값을 제공하기 위해 사용된다.
  • 디폴트 생성자는 컴파일러에 의해 제공되며 암묵적으로 public이 접근제한자로 선언된다.
  • 생성자는 메소드와 흡사하지만 메소드는 아니다.
  • 생성자는 메소드 호출방식으로 호출될 수 없으며, 인스턴스 생성시점에만 호출된다.
  • 생성자는 항상 객체를 잠그고, 객체의 모든 생성자 작업을 마칠 때까지 다른 스레드에서 이를 정상적으로 사용할 수 없도록 한다.
  • 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.
  • 생성자를 호출할 때 객체에 대한 메모리가 JVM Heap 메모리 영역에 할당된다.
  • new 키워드를 사용하여 객체를 생성할 때마다 생성자가 호출된다.
  • 생성자는 매개변수가 없는 생성자와 있는 생성자 두 개로 나뉜다.

생성자 작성 규칙

  • 생성자의 이름은 클래스의 이름과 같아야 한다.
  • 생성자는 리턴값이 없다. (하지만 void를 쓰지 않는다)
  • 생성자의 접근제한자로는 public, protected, private를 선언할 수 있으며, 접근제한자가 없다면 default 접근제한자로 선언된다.
  • 생성자에는 abstract, static, final, synchronized 키워드를 사용할 수 없다.
  • 생성자가 오버로딩된 다른 생성자를 호출할 수 있다.
  • new라는 keyword를 이용해서 객체를 생성할 때 자동적으로 default constructor가 호출된다.
    → Person person = new Person();
  • 기본 문법
    • 클래스이름(타입 변수명, 타입 변수명, …){
      //주로 인스턴스 변수의 초기화 코드를 작성한다
      }

생성자 오버로딩

  • 생성자를 오버로딩한 경우 기본 생성자를 호출하여 객체를 생성하고자 할 경우에는 컴파일러가 자동으로 생성해주지 않기 때문에 기본 생성자를 클래스에 명시적으로 구현해야 한다.
    public class ConstructorOverloading{
    	int id;
    	String name;
    
    	//오버로딩 생성자로 매개변수가 있음
    	ConstructorOverloading(int id, String name){
    		//인스턴스 초기화 작업
    	}
    }
    
    public class ConstructorOverloadingTest{
    	public static void main(String[] args){
    		//기본 생성자가 없기 때문에 오류가 발생한다
    		ConstructorOverloading c1 = new ConstructorOverloading();
    		ConstructorOverloading c2 = new ConstructorOverloading(1, "test");
    	}
    }
  • 생성자의 오버로딩은 메서드 오버로딩과 동일한 방식으로 구현한다.
  • 다른 매개변수 리스트를 가지는 생성자들로 구성하며, 매개변수 수와 유형에 따라 컴파일러에 의해 구분된다.
    public class ConstructorOverloading{
    	int id;
    	String name;
    
    	//기본 생성자로 매개변수 없음
    	ConstructorOverloading(){
    		//인스턴스 초기화 작업
    	}
    
    	//오버로딩 생성자로 매개변수가 있음
    	ConstructorOverloading(int id, String name){
    		//인스턴스 초기화 작업
    	}
    }

Copy 생성자

Java에서 자사 생성자는 없지만 한 객체에서 다른 객체로 값을 복사하는 방식으로 처리할 수 있다.

public class CopyConstructorEx1{
	int id;
	String name;

	CopyConstructorEx1(int i,String n){
		id = i;
		name = n;
	}
	//constructor to initialize another obejct
	CopyConstructorEx1(CopyConstructorEx1 originObj){
		id = originObj.id;
		name = originObj.name;
	}
	void display(){
		System.out.println(id+" "+name);
	}
		
	public static void main(String[] args){
		CopyConstructorEx1 obj = new CopyConstructorEx1(123,"홍길동");
		CopyConstructorEx1 copyObj = new CopyConstructorEx1(obj);
		obj.display();
		copyObj.display();
	}
}

생성자와 메서드의 차이점

생성자와 메서드의 주요 차이점은 return type이 없고, 사용 용도가 다르며, 호출 시점이 다르다는 것이다.

생성자메서드
객체의 상태를 초기화하는 사용(초기화시 1번만 호출)객체의 동작을 노출하는데 사용(필요시 제한없이 호출)
return type이 없어야 한다return type이 있어야 한다
암묵적으로 호출된다명시적으로 호출된다
Java 컴파일러는 클래스에 생성자가 없는 경우 기본 생성자를 제공한다어떤 경우에도 컴파일러가 제공하지 않는다
생성자 이름은 클래스 이름과 동일해야 한다메서드 이름은 클래스 이름과 같을 수도 아닐 수도 있다
profile
웹퍼블리셔의 백엔드 개발자 도전기

0개의 댓글