22.5.11 [HackerRank]Java

서태욱·2022년 5월 11일
0

Algorithm

목록 보기
45/45
post-thumbnail

✅ 문제 분석

Add 클래스와 메소드를 만들고 메소드가 function add에 전달된 수의 합을 출력하도록 해야 한다.

인풋에 정수를 포함하는 6줄이 있다.
아웃풋은 4줄만 출력된다. 각 라인은 메인 메소드의 변수로 전달된 정수의 합계가 출력되는 것.

🌱 배경지식

메소드 오버로딩

메소드 시그니처가 오버로딩의 핵심이다.
메소드 시그니처는 메소드 선언부에 명시되는 파라미터의 개수, 타입, 순서를 말한다.

같은 이름의 메소드를 중복해서 정의하는 것이다. 원래 자바는 한 클래스 안에 같은 이름의 메소드를 둘 이상 가질 수 없다.

하지만 파라미터 개수나 타입을 다르게 하면(메소드 시그니처가 다르면) 메소드 이름이 같아도 작성할 수 있다.
(반환 타입과는 관계가 없다.)

메소드 오버로딩을 사용하면 메소드에 사용하는 이름을 절약할 수 있고, 메소드 호출 시 전달해야 할 파라미터 타입이나 개수를 크게 신경쓰지 않아도 호출할 수 있다.
(오버로딩은 다형성을 구현하는 방법 중 하나다.)

class Test { //display() 메소드를 다양하게 오버로딩한다.

static void display(int num1) { 
	System.out.println(num1); 
	}

static void display(int num1, int num2) {
	System.out.println(num1 * num2); 
	}

static void display(int num1, double num2) {
	System.out.println(num1 + num2); 
	}
}

public class Method06 {

    public static void main(String[] args) {

        Test myfunc = new Test();

        myfunc.display(10); //사용자가 display()메소드를 호출하면, 컴파일러는 자동으로 같은 시그니처를 갖는 메소드를 찾아 호출한다.
        myfunc.display(10, 20);
        myfunc.display(10, 3.14);
    }
}

// 실행결과
10
200
13.14

자바 가변인자(Varargs): 파라미터 동적 사용

자바 오버로딩을 사용하면 파라미터의 개수와 타입이 달라도 같은 이름의 메소드 명으로 동일한 기능을 구현할 수 있다.

따라서 파라미터 타입이나 개수가 다르더라도 같은 메소드 명으로 오버로딩 할 수 있다.
하지만 파라미터 개수가 사용자의 쓰임에 따라 달라지는 경우를 생각해볼 때, 일일이 오버로딩하는 것은 매우 번거로운 일이 된다.

이를 해결하기 위해 자바 1.5에서 가변 인자 varargs 메서드가 추가되었다. 이 메서드는 파라미터의 개수를 동적으로 지정할 수 있게 된다.

가변인자를 사용하면 컴파일러가 파라미터를 배열 형식으로 바꾸고, 파라미터로 주어지는 변수들을 모아서 객체로 만들어버린다. 사용 방법은 ...을 파라미터 변수명 앞에 붙여주면 된다. 매개변수가 여러개일 경우에는 가장 마지막에 써준다.

public final class Test {
    public static void display(String ...strs) {
        for(String s: strs) {
            System.out.println(s);
        }
    }
    public static void main(String[] args) {
        
        display("abc", "def", "ghi");
    }
}

가변인자를 사용하면 파라미터를 넣지 않아도 정상 실행된다.
따라서 의도하지 않은 결과를 일으킬 수 있으므로,
가변 인자를 사용할 때 가변인자 길이를 가지고 Exception을 호출하거나 사용자가 방어적으로 코딩해야 한다.

public final class Test {    
    public static void varargsTest1(String ...args) {
        
    }
    
    public static void varargsTest2(String args) {
        
    }
    
    public static void main(String[] args) {
        varargsTest1();
        varargsTest2(); //실행하기 전에 Error 
    }
}

✏️ 해설

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

//Write your code here
class Add {
    public void add(int... intArgs) { //intArgs: [1, 2], 가변인자(Varargs)를 사용해 파라미터 개수를 동적으로 지정한다. 
    //파라미터 타입이나 개수가 달라도 같은 메소드 명으로 오버로딩이 가능해진다.
        int sum = 0;
        String operator = "";
        for (int i : intArgs) {
            sum += i; 
            System.out.print(operator + i); 
            operator = "+";
        }
        System.out.println("=" + sum);
    }
}

public class JavaVarargs {

    public static void main(String[] args) {
        try{
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
            //BufferedReader를 사용하면 버퍼에 입력을 일시적으로 모았다가 한번에 버퍼에 있는 데이터를 입력하므로 속도가 빠르고 효율적이다. 
            //띄어쓰기와 엔터를 경계로 입력값을 인식하는 스캐너 클래스와 달리, 엔터만 경계로 인식하고 받은 데이터가 String으로 고정되어 
            //데이터를 따로 가공해야 하는 단점은 있다. 하지만 속도가 빠르기 때문에, 데이터를 많이 입력받아야 하는 상황에서는 BufferedReader를 사용하면 좋다.
            int n1=Integer.parseInt(br.readLine()); //readLine()은 데이터를 라인 단위로 읽는다.
            int n2=Integer.parseInt(br.readLine());
            int n3=Integer.parseInt(br.readLine());
            int n4=Integer.parseInt(br.readLine());
            int n5=Integer.parseInt(br.readLine());
            int n6=Integer.parseInt(br.readLine());
            
            Add ob=new Add(); //Add 클래스를 사용해 변수명 ob로 인스턴스 생성.
            ob.add(n1,n2); // 객체 ob에 입력값들을 넣고, add 메소드 실행된다. intArgs[1, 2]
            ob.add(n1,n2,n3);// intArgs[1, 2, 3]
            ob.add(n1,n2,n3,n4,n5);// intArgs[1, 2, 3, 4, 5]
            ob.add(n1,n2,n3,n4,n5,n6);// intArgs[1, 2, 3, 4, 5, 6]
            
            Method[] methods=Add.class.getDeclaredMethods();
            Set<String> set=new HashSet<>();
            boolean overload=false;
            for(int i=0;i<methods.length;i++) {
                if(set.contains(methods[i].getName())) {
                    overload=true;
                    break;
                }
                set.add(methods[i].getName());
            }
            if(overload) {
                throw new Exception("Overloading not allowed");
            }
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

👉 참고

profile
re:START

0개의 댓글