본문 바로가기
study_algorithm/문제풀면서 알게된 것들

java의 문자열 포맷 : String.format() 과 System.out.printf()

by developer_j 2020. 11. 25.
728x90
반응형

서식문자 관련 문제를 풀다가, 다른 사람들이 해결한 방법을 찾던 중

System.out.println(String.format(format,args));

형태의 코드를 보게 되었다.

이때까지 printf()로 풀고 있었는데 뭐가 다른가? 하고 궁금해서 찾아보게 되었는데, f3과 번역 콤보, 구글링으로 공부해 본 결과 변수를 정렬하여 출력할 수 있는 메소드로 printf()와 동일한 것 같다. (설명 주석으로 C의 printf()의 영향을 크게 받았다고 되어 있다.)

나는 예전에 c를 해본 적도 있고, java를 맨 처음 배웠을 때 서식문자를 사용해 출력하는 방법에 대해 printf()를 접해본 적이 있었는데 그 때 가르쳐주셨던 교수님께서 java의 printf()는 c언어 개발자의 접근성을 높이는 하나의 수단(?)으로 있는 것이라고 말씀 하셨던 것 같다.

F3을 통해 확인해본 String.format()과 System.out.printf()

1. String.format()

    public static String format(String format, Object... args) {
        return new Formatter().format(format, args).toString();
    }

String.format()의 경우 Formatter객체의 format() 메소드를 가지고 원하는 결과 형태로 바꾼 후 toString() --> 문자열로 변환됨

2. System.out.printf()

    public PrintStream printf(String format, Object ... args) {
        return format(format, args);
    }

여기서 format메소드는 같은 PrintStream 클래스 안의 format 함수로,

    public PrintStream format(String format, Object ... args) {
        try {
            synchronized (this) {
                ensureOpen();
                if ((formatter == null)
                    || (formatter.locale() != Locale.getDefault()))
                    formatter = new Formatter((Appendable) this);
                formatter.format(Locale.getDefault(), format, args);
    //formatter 변수 역시 위에서 private Formatter formatter 로 변수 선언 되어 있음.
            }
        } catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        } catch (IOException x) {
            trouble = true;
        }
        return this;
    }

똑같이 Formatter 객체를 생성(new)하고 Formatter 객체의 format()를 사용한다.

그렇다면 Formatter 객체의 format()은 어떤 역할일까?

3. Formatter 클래스의 format()?

     public Formatter format(String format, Object ... args) {
        return format(l, format, args);
    }

위의 format()은 같은 Formatter클래스 내의 format() 메소드를 사용한 것이다.

     public Formatter format(Locale l, String format, Object ... args) {
        ensureOpen();  
        //ensureOpen() == formatting된 결과를 담을 Appendable 인터페이스 변수가 null이면 Exception이 발생되도록 되어있음.
        //즉, null인지 먼저 체크한다

        // index of last argument referenced
        int last = -1;
        // last ordinary index
        int lasto = -1;

        FormatString[] fsa = parse(format);
        for (int i = 0; i < fsa.length; i++) {
            FormatString fs = fsa[i];
            int index = fs.index();
            try {
                switch (index) {
                case -2:  // fixed string, "%n", or "%%"
                    fs.print(null, l);
                    break;
                case -1:  // relative index
                    if (last < 0 || (args != null && last > args.length - 1))
                        throw new MissingFormatArgumentException(fs.toString());
                    fs.print((args == null ? null : args[last]), l);
                    break;
                case 0:  // ordinary index
                    lasto++;
                    last = lasto;
                    if (args != null && lasto > args.length - 1)
                        throw new MissingFormatArgumentException(fs.toString());
                    fs.print((args == null ? null : args[lasto]), l);
                    break;
                default:  // explicit index
                    last = index - 1;
                    if (args != null && last > args.length - 1)
                        throw new MissingFormatArgumentException(fs.toString());
                    fs.print((args == null ? null : args[last]), l);
                    break;
                }
            } catch (IOException x) {
                lastException = x;
            }
        }
        return this;
    }

즉, Formatter의 format() 메소드는 출력 양식을 결정하는 역할이라고 할 수 있다.
그러므로 String.format()과 printf()는 둘 다 특정한 출력 양식을 정해 출력할 때 사용.

  • String.format()은 문자열화 시킨 것을 String형 변수에 바인 시킬 수 있다(String 형 결과가 return됨).
    Formatter.format(args).toString();
  • System.out.printf()는 문자열화 시킨 것을 PrintStream으로 바로 출력되도록 할 수 있다.
    Formatter.format(args);

이처럼, 차이라고 한다면 String 형 변수에 바인딩 시킬 수 있냐(String.format()) 없냐, 바로 출력시키느냐(System.out.printf()) 아니냐로 나뉠 수 있겠다.

1줄요약 : 출력만 할거면 똑같다.

728x90
반응형