좋아, 정보처리기사 실기에서는 기초 개념을 헷갈리게 만드는 코드 트릭이나 정확한 순서/우선순위/기본 문법의 이해가 필요한 문제들이 자주 출제돼.
그래서 다음과 같은 기준을 고려해서 문제를 구성해봤어:
자바에서 static, 생성자 호출 순서, 연산자 우선순위, 배열과 참조 등을 잘 이해하지 못하면 틀릴 수 있게 설계
다음 Java 코드를 보고, 출력되는 값을 구하시오.
class Sample {
static int x = 10;
int y;
Sample(int val) {
y = val;
x += val;
}
void change(int val) {
x += val++;
y += ++val;
}
void print() {
System.out.println("x = " + x + ", y = " + y);
}
}
public class Main {
public static void main(String[] args) {
Sample a = new Sample(5);
Sample b = new Sample(3);
b.change(2);
a.print();
b.print();
}
}
(A)
x = 22, y = 5
x = 22, y = 6
(B)
x = 20, y = 5
x = 22, y = 7
(C)
x = 22, y = 5
x = 22, y = 7
(D)
x = 20, y = 5
x = 22, y = 6
정답은 (C) 입니다.
class Sample {
static int x = 10; // 클래스 변수(static), 모든 Sample 객체가 공유
int y; // 인스턴스 변수, 객체마다 별도 존재
Sample(int val) {
y = val; // 해당 객체의 y에 val 저장
x += val; // x = x + val → static 변수 x는 모든 객체가 공유함
}
예제에서
Sample a = new Sample(5); → x = 10 + 5 = 15, a.y = 5Sample b = new Sample(3); → x = 15 + 3 = 18, b.y = 3void change(int val) {
x += val++; // val 값을 x에 더한 후, val을 증가시킴 (후위 증가)
y += ++val; // val을 먼저 증가시킨 후, y에 더함 (전위 증가)
}
| 순서 | 내용 | 결과 |
|---|---|---|
x += val++ | x = 18 + 2 → x = 20, val은 3이 됨 | |
y += ++val | val은 먼저 4로 증가 → y = 3 + 4 = 7 |
void print() {
System.out.println("x = " + x + ", y = " + y);
}
57public class Main {
public static void main(String[] args) {
Sample a = new Sample(5); // x = 15, a.y = 5
Sample b = new Sample(3); // x = 18, b.y = 3
b.change(2); // x = 20, b.y = 7
a.print(); // x = 20, y = 5
b.print(); // x = 20, y = 7
}
}
하지만 b.change에서 x가 2 더해지고 val++의 후위증가 때문에 val이 3이 되고, ++val로 다시 4가 되어 y += 4가 되므로 최종적으로:
→ 정답: (C)
static 변수는 모든 객체가 공유하는 값 → 변할 수 있다!val++ vs ++val → 전위, 후위 연산자는 정확한 순서 차이가 있다.Sample 객체 a와 b는 y값이 다르지만, x는 공유된다.좋아, 정보처리기사 실기 스타일로 다양한 헷갈리기 쉬운 기초 코드 문제를 주제별로 조금씩 섞어서 줄게.
이번엔 배열 참조, String 비교, Object 참조, 연산 순서 쪽에서 많이 틀릴 수 있는 유형이야.
다음 Java 코드의 출력 결과를 고르시오.
public class Main {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2[0] = 9;
String s1 = "hello";
String s2 = new String("hello");
String s3 = "hello";
System.out.println(arr1[0] + arr2[0]);
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.equals(s2));
}
}
(A)
18
true
true
true
(B)
18
false
true
true
(C)
10
false
true
false
(D)
10
true
false
true
정답: (B)
int[] arr1 = {1, 2, 3};
int[] arr2 = arr1;
arr2[0] = 9;
arr1은 [1, 2, 3]arr2 = arr1; 이므로 arr2는 arr1을 참조함 (동일한 배열을 가리킴)arr2[0] = 9; → 결국 arr1[0] = 9 가 됨System.out.println(arr1[0] + arr2[0]);
9 + 9 = 18== vs .equals())String s1 = "hello"; // 문자열 상수 풀(string pool) 사용
String s2 = new String("hello"); // 새로운 객체 생성 (heap 메모리)
String s3 = "hello"; // 이미 있는 "hello" 참조 (pool 사용)
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // true
System.out.println(s1.equals(s2)); // true
== : 주소 비교 (참조 비교).equals() : 문자열 내용 비교따라서:
| 비교 | 결과 | 이유 |
|---|---|---|
| s1 == s2 | false | 서로 다른 객체 |
| s1 == s3 | true | 둘 다 "hello"라는 string pool 참조 |
| s1.equals(s2) | true | 문자열 내용 같음 |
18
false
true
true
→ 정답: (B)
| 포인트 | 설명 |
|---|---|
| 배열은 참조형이다 | 배열 변수는 객체를 가리키는 주소. 복사하면 같은 객체를 참조 |
== vs .equals() | 자바 문자열 비교 실수 유도. ==은 주소 비교, .equals()는 내용 비교 |
| 문자열 상수 풀 (String Pool) | "hello"처럼 리터럴은 자바가 자동으로 재사용 |
new String()은 heap에 별도 생성 | new를 쓰면 무조건 새 객체 생성됨 |
좋아! 그럼 정보처리기사 실기 스타일로 기초 개념 속 함정을 건드리는 5가지 문제를 모두 출제해줄게.
각 문제는 독립적이고, 마지막에 정답 + 디버깅 설명까지 전부 붙여줄게.
각 문제는 하나라도 개념이 흔들리면 틀리기 쉬운 포인트들을 정확히 찔러.
class A {
static int sx = initStatic();
int x = initInstance();
static int initStatic() {
System.out.println("Static init");
return 1;
}
int initInstance() {
System.out.println("Instance init");
return 2;
}
A() {
System.out.println("Constructor");
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
}
}
Q. 다음 코드의 출력 결과는?
public class Main {
public static void main(String[] args) {
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a == b);
System.out.println(c == d);
System.out.println(c.equals(d));
}
}
Q. 다음 출력 결과는?
public class Main {
public static void main(String[] args) {
Integer a = new Integer(10);
int b = 10;
System.out.println(a == b);
}
}
Q. 이 코드는 true를 출력할까 false를 출력할까?
class Parent {
int x = 10;
void print() {
System.out.println("Parent x = " + x);
}
}
class Child extends Parent {
int x = 20;
@Override
void print() {
System.out.println("Child x = " + x);
System.out.println("Parent x via super = " + super.x);
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.print();
}
}
Q. 위 코드의 출력 결과는?
public class Main {
public static int test() {
try {
return 1;
} catch (Exception e) {
return 2;
} finally {
return 3;
}
}
public static void main(String[] args) {
System.out.println(test());
}
}
Q. 위 코드의 출력 결과는?
Static init ← 클래스 처음 로딩 시 실행됨
Instance init ← 객체 생성 시 실행됨
Constructor ← 인스턴스 초기화 끝나고 나서 실행
정답 출력:
Static init
Instance init
Constructor
Integer a = 100;
Integer b = 100;
a == b → trueInteger c = 200;
Integer d = 200;
c == d는 falsec.equals(d)는 값이 같으므로 true정답 출력:
true
false
true
Integer a = new Integer(10);
int b = 10;
System.out.println(a == b); // true
a == b에서 a는 unboxing 되어 10 == 10으로 비교됨 → true정답: true
Parent p = new Child();
p.print(); // 자식의 print() 호출됨 (오버라이딩)
출력:
Child x = 20
Parent x via super = 10
x = 10은 Parent에 있고x = 20은 Child에 shadowing 되어 존재정답 출력:
Child x = 20
Parent x via super = 10
try {
return 1;
} finally {
return 3;
}
try에서 return 하더라도 finally에서 return이 또 있으면 그것이 최종 값정답 출력:
3
| 문제 번호 | 개념 포인트 | 정답 / 출력 |
|---|---|---|
| 문제 1 | static vs instance 순서 | Static init → Instance init → Constructor |
| 문제 2 | Integer 캐싱, == vs equals | true / false / true |
| 문제 3 | Integer vs int 비교 | true |
| 문제 4 | 오버라이딩, this vs super | Child x = 20 / Parent x via super = 10 |
| 문제 5 | finally의 return 우선순위 | 3 |