본문 바로가기

개발일지/Java + Spring

211022 Java - 메소드(클래스/인스턴스/기본형/참조형)

배운 걸 정리하기 앞서 클래스=객체=인스턴스에 대해서 다시 한 번 이야기를 해야할 것 같다. 클래스는 한 번 만들어두면 여러 번 반복해서 만들 필요 없이 쉽게 불러다 쓸 수 있다. 클래스의 경우 설계도만 짜놓는 것과 같고 객체의 경우 메인에서 만들어둔 클래스를 부를 때 클래스명에 해당하는 것이다. new 연산자를 이용해 객체 생성을 하는 것이 중요한데 여기서 객체명이 객체의 인스턴스가 되는 것임!! 


 

클래스 메소드와 인스턴스 메소드

public class Sample1024 {

	public static void main(String[] args) {
		Sample1024 s1 = new Sample1024();
		int x = 5, y = 10;
		int sum = s1.add(x, y);
		
		System.out.printf("%d + %d = %d", x, y, sum);
	}
	

	int add(int a, int b)
	{
		int sum = a + b;
		return sum; //a+b;
	}
	
	//정수타입이 실수타입보다 타입이 작으니까 강제 형변환을 하든가 a, b 타입을 double로 맞춤
	//리턴을 받지 않고 각 메소드에서 출력을 한다.
}

 

Main 클래스

다른 메소드와 공유하고 있어야 하기 때문에 메인 클래스는 반드시 static 메소드여야만 한다. 메소드를 쓰려면 보통은 반드시 객체 생성을 해서 가져와야만 함 

 

		Sample1022 s1 = new Sample1022();
		int x = 5, y = 10;
		int sum = s1.add(x, y);

 

정수타입만 넘기면 되니까 3, 5 처럼 숫자만 넣어도 됨 
변수 집에 있는 값이 넘어가는 거임
이름은 같지만 이곳의 인수값 xy는 아래의 메소드의 파라미터값 xy와 다른 집이다.

 


add 메소드

	int add(int x, int y)
	{
		x = 10;
		int sum = x + y;
		return sum;
	}

 

메소드는 static의 유무로 결정이 되는데 static이 있으면 클래스 메소드이고, 없을 땐 인스턴스 메소드이다. 이 메소드의 경우 인스턴스 메소드로 분류가 된다. 

 

	int add(int x, int y) //선언부

 

메소드의 선언부를 보자 

순서대로 : 반환타입 / 메소드명 / 매개변수

int로 시작을 하는 이유는 리턴(return)값이 int 타입이기 때문이다. 

선언부에 있는 값들도 지역변수로 치기 때문에 add()메소드의 지역변수는 총 3개이다. 지역변수는 이 메소드 안에서만 사용할 수 있다. 

매개변수를 받을 때는 일반 변수 설정처럼 하면 안 된다. 한 개 이상의 매개변수가 있다면, 컴마(,) 뒤에 오는 매개변수의 데이터 타입을 적어줘야한다.

 

		x = 10;
		int sum = x + y;
		return sum;

 

매개변수를 넣은 클래스는 return을 하지 않았을 때 에러가 일단 뜨는데 끝까지 작성하면 없어지니까 신경쓰지 않아도 됨. 변수 설정을 해주지 않아도 return 3+5; 바로 해줄수도 있다! 또한 매개변수의 숫자와 인자값 숫자를 맞춰야 한다. 매개변수 2개를 받았으니 메인에서 호출할 때 반드시 2개를 넣어줘야한다. 

 

 


MyMath Class

public class Sample1024_2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		MyMath mm = new MyMath();
		int x, y;
		
		System.out.print("x = ");
		x = sc.nextInt();
		System.out.print("y = ");
		y = sc.nextInt();
		
		System.out.printf("%d + %d = %d \n", x, y, mm.add(x,y));
		System.out.printf("%d - %d = %d \n", x, y, mm.substract(x,y));
		System.out.printf("%d * %d = %d \n", x, y, mm.multiply(x,y));
		System.out.printf("%d / %d = %.2f \n", x, y, mm.divide(x,y));
		
		sc.close();
	}

}

 

숫자를 입력 받아 사칙연산을 수행하는 코드이다.

메인은 위에서 사용했던 방법과 같지만 메인 안에 포함 돼 있는 인스턴스 메소드가 아니라 메인 바깥에 클래스를 만들어주었다.

 

class MyMath{
	int add(int a, int b)
	{
		int sum = a + b;
		return sum; //a+b;
	}
	
	int substract(int a, int b)
	{
		int sub = a - b;
		return sub;
	}
	
	int multiply(int a, int b)
	{
		int mul = a * b;
		return mul;
	}
	
	double divide(double a, double b)
	{
		double div = a / b;
		return div;
	}
}

 

클래스나 메소드를 작성할 땐 법칙이 있다. public 클래스는 한 파일 안에 하나만 존재해야한다. 메소드의 경우 return(반환값)이 있는 경우 반환값의 데이터 타입을 메소드명 앞에 넣어주어야한다. 반환값이 없다면 void를 사용하면 된다. 마지막 반환값이 double 타입의 경우 정수타입이 실수타입보다 타입이 작으니까 강제 형변환을 하든가 a, b 타입을 double로 맞춰야만 에러가 뜨지 않는다. 그런데 void 라도 return을 사용할 수도 있음!!

 

class MyMath{
	int add(int a, int b)
	{
		return a + b;
	}
	
	int substract(int a, int b)
	{
		return a - b;
	}
	
	int multiply(int a, int b)
	{
		return a * b;
	}
	
	double divide(double a, double b)
	{
		return a / b;
	}
}

 

메소드에서 따로 변수 선언을 하지 않고 바로 리턴에서 계산을 해주어도 답이 나온다.

 

 


 

public class Sample1024_2 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		MyMath mm = new MyMath();
		int x, y;
		
		System.out.print("x = ");
		x = sc.nextInt();
		System.out.print("y = ");
		y = sc.nextInt();
		
		mm.add(x,y);
		mm.substract(x,y);
		mm.multiply(x,y);
		mm.divide(x,y);
		
		sc.close();
	}

}

class MyMath{
	void add(int a, int b)
	{
		int sum = a + b;
		System.out.printf("add(%d, %d) = %d \n", a, b, sum);
	}
	
	void substract(int a, int b)
	{
		int sub = a - b;
		System.out.printf("substract(%d, %d) = %d \n", a, b, sub);
	}
	
	void multiply(int a, int b)
	{
		int mul = a * b;
		System.out.printf("multiply(%d, %d) = %d \n", a, b, mul);
	}
	
	void divide(double a, double b)
	{
		double divide = a / b;
		System.out.printf("divide(%d, %d) = %.2f \n", (int)a, (int)b, divide);
	}
	
	//정수타입이 실수타입보다 타입이 작으니까 강제 형변환을 하든가 a, b 타입을 double로 맞춤
	//리턴을 받지 않고 각 메소드에서 출력을 한다.
}

 

이번엔 리턴값으로 돌려주는 게 아니라 메소드를 메인에서 호출하면 바로 출력 하도록 만들어줬다. 마지막 double 타입의 매개변수를 정수 타입으로 출력하고 싶을 때 앞에 (int)를 넣어주면 성공이다!

 


매개변수에는 기본형과 참조형이 있다. 기본형은 매개변수의 경우 기본적으로 선언하는 데이터 타입을 말하고, 참조형 매개변수는 객체 생성시에 가지고 있는 객체 생성 시작 주소를 갖고 있는 매개변수이다. 

 

 

 

기본형 매개변수

	public static void main(String[] args) {
		//기본형 매개변수, 참조형 매개변수
		// 참조형 매개변수 - 인스턴스형 시작주소값
		/*
		 * 기본형 매개변수임!!
		 *  출력예 ) 
		 *  main : x = 10
		 *  change() : x = 1000 
		 *  After change()(d.x)
		 *  main() : x = 10
		 */
		Data d = new Data(); 
		d.x = 10; //Data 클래스에서 갖고 와서 값 줌
		
		System.out.println("main : x = " + d.x );
		change(d.x); //기본자료형 //객체 생성 없이 부르려면 static이어야한다.
		
		System.out.println("After change()(d.x)");
		System.out.println("main : x = " + d.x);
	}
	
	//클래스랑 지역변수랑 이름이 똑같으면 지역변수 우선순위가 먼저임
	static void change(int x)
	{
		x = 1000;
		System.out.println("change() : x = " + x);
	}
}

class Data
{
	int x; 
	//지역변수는 반드시 값을 세팅해서 써야한다.
	//속성만 있고 기능은 없음
}

 

1. 첫 시작은 Data 클래스를 만든다. 지역변수 int x를 만들어 준다. 속성은 있고 기능은 없다.

 

2. 메인에서 객체생성을 하고 x를 불러서 값을 준다. 출력을 하면 10이 출력된다. change()로 메소드를 불러온다. 

 

3. 그 시각 메소드에서는 x를 1000으로 만들어준다. 그리고 출력하고 끝이남 참고로 change메소드에서 받은 매개변수를 바꾼 것이지 위에 있는 x와는 완전히 다른 값이다.

 

4.다시 change()를 호출했던 자리로 가서 아래를 출력한다. 3번에서 1000으로 만들었지만 지역변수이기 때문에 돌아 왔을 땐 값이 남아있지 않는다. 

 

 

 

참조형 매개변수

package oct4;

public class Sample1024 {

	public static void main(String[] args) {
		Data d = new Data();
		d.x = 10;
		d.y = 3;
		
		change(d);
		System.out.println("After change()(d.x)");
		System.out.println("main : x = " + d.x );
		
	}
	
	static void change(Data d) {
		System.out.println("d.x = " + d.x + ", d.y = " + d.y);
		d.x = 1000;
		System.out.println("change() : x = " + d.x);
	}
}

class Data{
	int x, y;
}

 

d.x = 10, d.y = 3
change() : x = 1000
After change()(d.x)
main : x = 1000

 

지역변수는 반드시 값을 세팅해야한다. 그래서 메인에서 불러오자마자 d.x / d.y 선언을 해주었다.

 

change() 메소드에서는 이번에 일반매개변수 int가 아니라 참조형 매개변수 Data 타입을 받았다. 덕분에 객체 생성 없이 d.x 이것과 d.y 이것을 사용할 수 있다. 여기서는 매개변수에서 갖고 온 지역변수인 x가 아니라 참조형으로 받아 온 d.x값을 1000으로 바꿔줬기 때문에 참조하고 있는 주소 안의 값이 바뀐다. change()메소드가 끝나면 안에 있는 d.x의 변수는 쓰지 못 하지만 실제 주소 안의 값이 바뀌었기 때문에 결과로 1000이 나오는 것이다.

 

 

 

 

배열형 참조형 매개변수

		public static void main(String[] args) {
			int[] d = { 10 };
			
			System.out.println("main : x = " + d[0]);
			
			change(d);
			
			System.out.println("After change()(d[0])");
			System.out.println("main : x = " + d[0]);
		}
		
		static void change(int[] d) 
		{
			d[0] = 1000;
			System.out.println("change() : x = " + d[0]);
		}
	}

메소드 매개변수에 배열을 참조해서 사용할 수 있다. 마찬가지로 참조형 변수 라서 한군데에서 바꿔도 모든 d[0]가 바뀐다. 

 


 

package test1018;

public class program1022 {

	public static void main(String[] args) {
		int[] arr = new int[] {3, 2, 1, 6, 5, 4};
		printArr(arr); 
		sortArr(arr);
		printArr(arr); //같음
		
		System.out.println("sum = " + sumArr(arr)); 
		
	}
	
	static void printArr(int[] arr) { //모든 요소 출력
		for(int i=0; i<arr.length; i++)
		{
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}
	
	static void sortArr(int[] arr) { //오름차순
		int tmp;
		for(int i=0; i<arr.length-1; i++)
		{
			for(int j=i+1; j<arr.length; j++)
			{
				if(arr[i] > arr[j])
				{
					tmp = arr[i];
					arr[i] = arr[j];
					arr[j] = tmp;
				}
			}
		}
	}
	
	static int sumArr(int[] arr) { //배열 전체 썸
		int sum = 0;
		for(int i=0; i<arr.length; i++)
		{
			sum+=arr[i];
		}
		return sum;
	}
}
3 2 1 6 5 4 
1 2 3 4 5 6 
sum = 21

 

클래스의 메소드와 클래스의 변수로만 이루어져 있는 경우 객체 생성을 하지 않아도 된다. 메인에서 값을 바꿔주기 위해서 static을 써주는 것이 좋다!!

 

참조형 클래스(배열)

매개변수가 배열(시작주소를 가지기 때문에 내가 가지고 온 것과 같은 곳을 바라보고 있음)

출력 클래스 printArr(int[] arr)
배열이 이미 생성 돼 있음
메모리를 공유한다는 뜻이다.

정렬 클래스
내림차순이나 오름차순이나 무조건 삼각형을 그려야 함

sum 클래스
썸 변수는 이 지역을 벗어나면 쓸 수 없다.
썸을 리턴하게 되면 썸의 집에 있는 값이 가게 되는 것이다.
-
클래스 메소드와 인스턴스 메소드의 차이점
인스턴스 메소드는 객체생성을 통해서만 사용할 수 있다.
클래스 메소드는 인스턴스 메소드를 호출할 수 없다.
인스턴스 메소드에서는 클래스 메소드를 호출할 수 있다. 
-
모듈모듈 나누는 게 클래스이다.

 

--저번주 복습