충분히 쌓여가는
Java Test 3차 오답노트(김병우) 본문
03. Given:
public interface InterfaceOne {
void printOne();
}
Which three classes successfully override printOne()? (Choose three.)
(printOne()을 override 하는데 성공한 세가지 클래스는 무엇입니까?)
A)
public abstract class TestClass implements InterfaceOne {
public abstract void printOne();
}
B)
public class TestClass implements InterfaceOne {
private void printOne() {
System.out.println("one");
}
}
C)
public abstract class TestClass implements InterfaceOne {
public void printOne() {
System.out.println("one");
}
}
D)
public abstract class TestClass implements InterfaceOne {
public String printOne() {
return "one";
}
}
E)
public class TestClass implements InterfaceOne {
public void printOne() {
System.out.println("one");
}
}
F)
public class TestClass {
public void printOne() {
System.out.println("one");
}
}
답: A, C, E
풀이:
A: 인터페이스에서 메서드는 public abstract 메서드이름();인데 pulbic과 abstract이 평소에 생략되어 있다, 그런데 여기선 생략하지 않았고 따라서 있어도 무방하기 때문에 정답
B: default 접근 제어자인데 B는 접근 제어자가 private이다. 즉 오버라이드된 메서드의 범위가 더 좁다. 메서드 오버라이딩 조건에서 접근 제어자를 조상 클래스보다 좁은 범위로 변경할 수 없다
C: 접근 제어자를 public으로 지정하였다 default보다 넓은 범위이기 때문에 정상적인 오버라이드가 된다
D: 조상 클래스는 반환타입이 void, 자식 클래스는 반환타입이 String으로 일치하지 않는다. 오버라이딩이 되려면 선언부(반환 타입, 메서드 이름, 매개변수 목록)이 같아야 하기 때문에 답이 아님
E: C랑 같지만 abstract가 생략되어 있다. 그런데 생략되어도 오버라이딩 되는데 문제 없음
F: 인터페이스를 구현하려면 implements를 붙여 구현을 해야하는데 없음
04. Given:
public interface A {
public Iterable a();
}
public interface B extends A {
public Collection a();
}
public interface C extends A {
public Path a();
}
public interface D extends B, C {
}
Why does D cause a compilation error? (D가 컴파일 오류를 일으키는 이유는 무엇입니까?)
A) D inherits a() only from C.
B) D inherits a() from B and C but the return types are incompatible.
C) D extends more than one interface.
D) D does not define any method.
답: B
풀이:
B는 A를 상속받음, C는 A를 상속받음, D는 B, C를 상속받음
D는 B와 C로부터 a()를 상속받지만 반환 유형이 호환되지 않기 때문에 D에서 컴파일 오류가 발생함
D가 상속을 받으면 반환타입이 각각 B는 Collcetion이고 C는 Path인데 반환 유형이 호환되지 않음
05. Which interface in the java.util.function package will return a void return type?
(java.util.function 패키지의 어떤 인터페이스가 void return type을 반환합니까?)
A) Supplier
B) Predicate
C) Function
D) Consumer
답: D
풀이:
Consumer 인터페이스는 Java에서 함수형 프로그래밍을 구현하기 위해 Java 8부터 도입된 java.util.function 패키지의 일부.
Consumer 인터페이스는 하나의 인수를 받아 결과를 생성하는 함수를 나타내고 어떠한 값도 반환하지 않는다
06. Given the code fragment:
Integer[] ints = { 1, 2, 3, 4, 5, 6, 7 }; // 9
var list = Arrays.asList(ints); // 10
UnaryOperator<Integer> uo = x -> x * 3; // 11
list.replaceAll(uo); // 12
Which can replace line 11?
A) UnaryOperator<Integer> uo = x -> return (x * 3);
B) UnaryOperator<Integer> uo = var x -> { return x * 3; };
C) UnaryOperator<Integer> uo = (var x) -> { return x * 3; };
D) UnaryOperator<Integer> uo = (int x) -> x * 3;
답: C
풀이:
좌항에 UnaryOperator가 아닌 UnaryOperator<Integer>가 존재함
우항은 UnaryOperator<Integer> 동일해야 하고 변수를 담는 것은 여기서 var이기 때문에
(var x) -> {return x * 3;}으로 해야 함
import java.util.Arrays;
import java.util.function.UnaryOperator;
public class Test {
public static void main(String[] args) {
Integer[] ints = { 1, 2, 3, 4, 5, 6, 7 }; // 9
var list = Arrays.asList(ints); // 10
UnaryOperator<Integer> uo = x -> x * 3; // 11
list.replaceAll(uo); // 12
}
}
import java.util.Arrays;
import java.util.function.UnaryOperator;
public class Test {
public static void main(String[] args) {
Integer[] ints = { 1, 2, 3, 4, 5, 6, 7 }; // 9
var list = Arrays.asList(ints); // 10
UnaryOperator<Integer> uo = (var x) -> { return x * 3; };
list.replaceAll(uo); // 12
}
}
11. Which two are successful examples of autoboxing? (Choose two.)
A) String a = "A";
B) Integer e = 5;
C) Float g = Float.valueOf(null);
D) Double d = 4;
E) Long c = 23L;
F) Float f = 6.0;
답: B, E
풀이:
난 답을 A,B로 했는데 생각해보니 E도 기본타입 long를 래퍼 클래스로 변경하면 Long로 해야하므로 E는 정답이다
A가 정답이 아닌 이유는 기본타입에서 래퍼 클래스로 Boxing하는 것이 오토박싱인데 String 타입은 기본 타입이 아니라 오토박싱이라 할 수 없어 정답이 아니다. 따라서 답은 B와 E이다
public class Test {
public static void main(String[] args) {
String a = "A";
Integer e = 5;
Float g = Float.valueOf(null);
Double d = 4; // 에러
Long c = 23L;
Float f = 6.0; // 에러
}
}
12. Which two statements are true about the modular JDK? (Choose two.)
(모듈러 JDK에 대한 설명 중 맞는 것은 무엇입니까?)
A) The foundational APIs of the Java SE Platform are found in the java.base module.
(Java SE Platform의 기본 API는 java.base 모듈에서 찾을 수 있습니다.)
B) An application must be structured as modules in order to run on the modular JDK.
(모듈러 JDK에서 실행하려면 응용 프로그램을 모듈로 구성해야 합니다.)
C) It is possible but undesirable to configure modules’ exports from the command line.
(명령줄에서 모듈의 내보내기를 구성하는 것은 가능하지만 바람직하지 않습니다.)
D) APIs are deprecated more aggressively because the JDK has been modularized.
(JDK가 모듈화되었기 때문에 API는 더 적극적으로 사용되지 않습니다.)
답: A, C
풀이:
A: java.base에 Java SE Platform의 기본 API가 들어있다
B: 모듈로 구성하지 않아도 모듈러 JDK에서 실행됨
C: 커맨드 라인에서 모듈의 exports를 하는 것은 가능하긴한데 웬만하면 하지 않는 것이 좋다
D: 모듈화되었기 때문에 더욱 적극적으로 사용됨
14. Given:
public class Main {
class Student { // line 1
String className;
Student(String className) { // line 2
this.className = className;
}
}
public static void main(String[] args) {
var student = new Student("Biology"); // line 3
}
}
Which two independent changes will make Main class compile? (Choose two.)
(메인 클래스를 컴파일하는 두 가지 독립적인 변경 사항은 무엇입니까?)
A) Move the entire Student class declaration to a separate Java file, Student.java
(전체 Student 클래스 선언을 별도의 Java 파일인 Student.java로 이동)
B) Change line 2 to public Student(String className) {
C) Change line 1 to public class Student {
D) Change line 3 to Student student = new Student("Biology");
E) Change line 1 to static class Student {
답: A, E
풀이:
Student.java파일로 Student 클래스의 선언을 옮겨야 됨
public class Test {
class Student { // line 1
String className;
Student(String className) { // line 2
this.className = className;
}
}
public static void main(String[] args) {
var student = new Student("Biology"); // line 3 // 에러
}
}
또한 현재 main 클래스가 static으로 되어있는데 void로 바꿔야함
public class Test {
class Student { // line 1
String className;
Student(String className) { // line 2
this.className = className;
}
}
public void main(String[] args) {
var student = new Student("Biology"); // line 3
}
}
16. Given:
public class Person {
private String name;
public void setName(String name) {
String title = "Dr. ";
name = title + name;
}
public String toString() {
return name;
}
}
and
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.setName("Who");
System.out.println(p);
}
}
What is the result?
A) Dr. Who
B) Dr. null
C) An exception is thrown at runtime.
D) null
답: D
풀이:
setName에서 실제로 name에는 저장되지 않는다
또한 Person 클래스에서 name은 private 타입으로 기본값이 null로 지정되기 때문에 실제 Test 클래스에서
Person의 참조변수인 p를 출력하게 된다면 제일 처음 초기화된 값 null이 출력되게 된다
![](https://blog.kakaocdn.net/dn/cnrNVG/btsF3WhPXxy/JTAEwpbREmLqKoDcQUmyN1/img.png)
![](https://blog.kakaocdn.net/dn/bzURzU/btsF2MfHK5S/Yu2MKxLo0ospyTUQLcnf5K/img.png)
17. Given:
void myLambda() {
int i = 25;
Supplier<Integer> foo = () -> i;
i++;
System.out.println(foo.get());
}
Which is true?
A) The code compiles but does not print any result.
B) The code prints 25.
C) The code does not compile.
D) The code throws an exception at runtime.
답: C
풀이:
문제점으로 람다 표현식 내에서 외부 변수를 캡처하는 방식
람다 표현식은 외부 변수를 캡처할 수 있지만, 이 변수는 사실상 final 또는 final 효과를 가져야 한다
근데 이 코드에서는 i가 final로 선언되지 않았는데 값을 변경하고 있어 컴파일 자체가 되지 않는다
void myLambda() {
int[] i = {25}; // 배열을 사용하여 변경 가능한 final 변수로 만듦
Supplier<Integer> foo = () -> i[0]; // 배열의 첫 번째 요소를 가져옴
i[0]++; // 배열의 첫 번째 요소를 증가시킴
System.out.println(foo.get());
}
20. Given:
class Super {
static String greeting() { return "Good night"; }
String name() { return "Harry"; }
}
and
public class Sub extends Super {
static String greeting() { return "Good morning"; }
String name() { return "Potter"; }
}
and
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
What is the result?
A) Good morning, Potter
B) Good night, Potter
C) Good morning, Harry
D) Good night, Harry
답: B
풀이:
1) Super 클래스에는 static String greeting() 메서드와 String name() 메서드가 정의되어 있고 greeting() 메서드는 정적(static)이며, name() 메서드는 인스턴스 메서드임
2) Sub 클래스는 Super 클래스를 상속하고 있다, Sub 클래스에서는 greeting() 메서드와 name() 메서드가 오버라이딩(overriding)되어 재정의됨, greeting() 메서드는 정적(static)이며, name() 메서드는 인스턴스 메서드
3) Test 클래스의 main 메서드에서는 Super 클래스 타입의 변수 s에 Sub 클래스의 인스턴스를 할당
4) s.greeting()을 호출할 때, 정적 바인딩(static binding)에 의해 Super 클래스의 greeting() 메서드가 호출되고 변수의 타입에 따라 결정, 따라서 출력은 Good night
5) s.name()을 호출할 때, 동적 바인딩(dynamic binding)에 의해 Sub 클래스의 name() 메서드가 호출되고 출력은 Potter가 됨
22. Given:
public class Price {
private final double value;
public Price(String value) {
this(Double.parseDouble(value)); }
public Price(double value) {
this.value = value;
}
public Price() { }
public double getValue() {
return value;
}
public static void main(String[] args) {
Price p1 = new Price("1.99");
Price p2 = new Price(2.99);
Price p3 = new Price();
System.out.println(p1.getValue() + "," + p2.getValue() + "," + p3.getValue());
}
}
What is the result?
A) The compilation fails.
B) 1.99,2.99,0
C) 1.99,2.99,0.0
D) 1.99,2.99
답: A
풀이:
난 답이 1.99,2.99,0.0라고 생각했는데, 초기화를 하지 않아 컴파일 에러가 발생하는 문제였다
public class Price {
private final double value; // java: variable value might not have been initialized
public Price(String value) {
this(Double.parseDouble(value));
}
public Price(double value) {
this.value = value;
}
public Price() { }
public double getValue() {
return value;
}
public static void main(String[] args) {
Price p1 = new Price("1.99");
Price p2 = new Price(2.99);
Price p3 = new Price();
System.out.println(p1.getValue() + "," + p2.getValue() + "," + p3.getValue());
}
}
23. Which statement about a functional interface is true?
(functional 인터페이스에 대한 설명 중 맞는 것은 무엇입니까?)
A) It must be defined with public access modifier.(public access modifier로 정의해야 함)
B) It must be annotated with @FunctionalInterface (@FunctionalInterface로 주석을 달아야 함)
C) It is declared with a single abstract method.(single abstract method로 선언됨)
D) It is declared with a single default method.(single default method으로 선언됨)
E) It cannot have any private methods and static methods. (private 메서드 및 정적 메서드를 사용할 수 없다)
답: C
풀이:
A: 함수형 인터페이스의 접근 제어자는 제한되지 않는다. public, protected, default, private 등 모든 접근 제어자를 사용할 수 있다
B: @FunctionalInterface 애노테이션은 함수형 인터페이스를 나타내기 위한 것이지만, 이 애노테이션을 사용하는 것은 선택 사항임
C: functional 인터페이스는 단일 추상 메서드를 선언.함수형 인터페이스(Functional Interface)는 딱 하나의 추상 메서드를 가지는 인터페이스로 함수형 인터페이스는 람다 표현식 또는 메서드 참조를 사용하여 구현할 수 있다
D: 함수형 인터페이스는 딱 하나의 추상 메서드만을 가져야 함
E: 함수형 인터페이스는 기본적으로 추상 메서드를 하나만 가져야 하지만, private 메서드와 static 메서드는 포함될 수 있다
25. Given:
public class Test {
public static void main(String[] args) {
int x;
int y = 5;
if (y > 2) {
x = ++y;
y = x + 7;
} else {
y++;
}
System.out.println(x + " " + y);
}
}
What is the result?
A) Compilation error
B) 0 5
C) 6 13
D) 5 12
답: A
풀이:
주어진 코드에서는 변수 x가 초기화되지 않은 상태에서 사용되기 때문에 에러 발생함
즉, 컴파일러는 초기화되지 않은 변수를 사용하고 있기 때문에 해당 코드에서 컴파일 오류를 발생시킵니다.
public class Test {
public static void main(String[] args) {
int x = 0; // 변수 x를 초기화
int y = 5;
if (y > 2) {
x = ++y;
y = x + 7;
} else {
y++;
x = y; // else 블록에서도 x에 값을 할당
}
System.out.println(x + " " + y);
}
}
27. Given:
List<String> list1 = new ArrayList<>();
list1.add("A");
list1.add("B");
List list2 = List.copyOf(list1);
list2.add("C");
List<List<String>> list3 = List.of(list1, list2);
System.out.println(list3);
What is the result?
A) [[A, B], [A, B]]
B) An exception is thrown at run time.
C) [[A, B], [A, B, C]]
D) [[A, B, C], [A, B, C]]
답: B
풀이:
UnsupportedOperationException 발생함
1) List.copyOf(list1)을 사용하여 list1의 불변 복사본인 list2를 만든다
2)list2.add("C")를 통해 list2에 새로운 요소를 추가하려고 시도함,
여기서 에러 발생: List.copyOf() 메서드로 생성된 리스트는 불변이므로 수정할 수 없고 UnsupportedOperationException이 발생함
29. Given:
class MyCar {
}
and
javac C:\Workspace4\MyCar.java
What is the expected result of javac?
A) javac fails to compile the class and prints the error message, C:\Workspace4\MyCar.java:1:error: package java does not exist
(javac이 클래스를 컴파일하지 못하고 오류 메시지를 출력: C:\Workspace4\MyCar.java:1:error: package java does not exist)
B) javac compiles MyCar.java without errors or warnings.(javac은 오류나 경고 없이 MyCar.java를 컴파일함)
C) javac fails to compile the class and prints the error message, C:\Workspace4\MyCar.java:1:error: expected import java.lang
(javac이 클래스를 컴파일하지 못하고 오류 메시지를 출력: C:\Workspace4\MyCar.java:1:error: expected import java.lang)
D) javac fails to compile the class and prints the error message, Error: Could not find or load main class MyCar.class
(javac이 클래스를 컴파일하지 못하고 오류 메시지를 출력: Error: Could not find or load main class MyCar.class)
답: B
풀이:
MyCar 클래스를 컴파일하는 것이므로 컴파일러는 정상적으로 컴파일됨
클래스 내용이 비어 있더라도 Java 컴파일러는 정상적으로 처리가능함 -> 오류나 경고 없이 컴파일이 완료
30. Given:
public final class X {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() { return getName(); }
}
and
public class Y extends X {
public Y(String name) {
super();
setName(name);
}
public static void main(String[] args) {
Y y = new Y("HH");
System.out.println(y);
}
}
What is the result?
A) The compilation fails.
B) Y@<<hashcode>>
C) null
D) HH
답: A
풀이:
난 답을 HH가 출력된다고 했는데 다시 보니 Y 클래스의 생성자에서 super()를 호출하고 있고 이 호출은 X 클래스의 기본 생성자를 호출한다, 그러나 X 클래스에는 매개변수 없는 기본 생성자가 명시적으로 정의되어 있지 않다
따라서 Y 클래스의 생성자에서는 명시적으로 super(name)과 같이 X 클래스의 생성자를 호출해야 하고 그렇지 않으면 컴파일 에러가 발생
public final class X {
private String name;
public X(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() { return getName(); }
}
public class Y extends X {
public Y(String name) {
super(name); // X 클래스의 생성자 호출
}
public static void main(String[] args) {
Y y = new Y("HH");
System.out.println(y);
}
}
// HH
32. Given:
import java.util.ArrayList;
import java.util.Arrays;
public class NewMain {
public static void main(String[] args) {
String[] fruitNames = { "apple", "orange", "grape", "lemon","apricot", "watermelon" };
var fruits = new ArrayList<>(Arrays.asList(fruitNames));
fruits.sort((var a, var b) -> -a.compareTo(b));
fruits.forEach(System.out::println);
}
}
What is the result?
A) Nothing
B) watermelon
orange
lemon
grape
apricot
apple
C) apple
apricot
grape
lemon
orange
watermelon
D) apple
orange
grape
lemon
apricot
watermelon
답: B
풀이:
문자열을 역순으로 정렬한 후에 출력하는 코드
1) fruitNames 배열을 ArrayList로 변환하여 fruits 변수에 할당
2) fruits.sort((var a, var b) -> -a.compareTo(b)); 코드는 문자열을 역순으로 정렬: a.compareTo(b)는 문자열을 역순으로 비교하는 방식
3) 결과: "watermelon", "orange", "lemon", "grape", "apricot", "apple" 순서
import java.util.ArrayList;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
String[] fruitNames = { "apple", "orange", "grape", "lemon","apricot", "watermelon" };
var fruits = new ArrayList<>(Arrays.asList(fruitNames));
fruits.sort((var a, var b) -> -a.compareTo(b));
fruits.forEach(System.out::println);
}
}
watermelon
orange
lemon
grape
apricot
apple
33. Given:
public interface A {
abstract void x();
public default void y() { }
}
and
public abstract class B {
public abstract void z();
}
and
public class C extends B implements A {
/* insert code here */
}
What code inserted into class C would allow it to compile?
A)
public void x() { }
public void z() { }
B)
public void x() { }
protected void y() { super.y(); }
public void z() { }
C)
voidx(){}
public void y() { }
public void z() { }
D)
void x() { super.y(); }
public void z() { }
E)
voidx(){}
public void z() { }
답: A
풀이:
인터페이스 A를 구현하는 클래스 C는 인터페이스에 있는 모든 추상 메서드를 구현해야 한다
x() 메서드가 추상 메서드이므로 반드시 구현되어야 하고 추상 클래스 B를 상속받는 클래스 C는 추상 메서드 z()를 반드시 구현해야 함
따라서 밑의 코드를 C 클래스에 삽입해야 정상적으로 컴파일된다
public void x() { }
public void z() { }
34. Given:
String[][] arr = {
{ "Red", "White" },
{ "Black" },
{ "Blue", "Yellow", "Green", "Violet" }
};
for (int row = 0; row < arr.length; row++) {
int column = 0;
for (; column < arr[row].length; column++) {
System.out.println("[" + row + "," + column + "] = " + arr[row][column]);
}
}
What is the result?
A)
[0,0] = Red
[0,1] = White
[1,0] = Black
[1,1] = Blue
[2,0] = Yellow
[2,1] = Green
[3,0] = Violet
B)
[0,0] = Red
[1,0] = Black
[2,0] = Blue
C)
java.lang.ArrayOutOfBoundsException thrown
D)
[0,0] = Red
[0,1] = White
[1,0] = Black
[2,0] = Blue
[2,1] = Yellow
[2,2] = Green
[2,3] = Violet
답: D
풀이:
arr 의 구성
첫 번째 배열: "Red", "White"
두 번째 배열: "Black"
세 번째 배열: "Blue", "Yellow", "Green", "Violet"
첫 번째 반복문은 배열의 각 행(row)을 반복하고, 두 번째 반복문은 해당 행의 각 열(column)을 반복
따라서 출력 결과는 밑의 코드와 같음
public class Test {
public static void main(String[] args) {
String[][] arr = {
{ "Red", "White" },
{ "Black" },
{ "Blue", "Yellow", "Green", "Violet" }
};
for (int row = 0; row < arr.length; row++) {
int column = 0;
for (; column < arr[row].length; column++) {
System.out.println("[" + row + "," + column + "] = " + arr[row][column]);
}
}
}
}
[0,0] = Red
[0,1] = White
[1,0] = Black
[2,0] = Blue
[2,1] = Yellow
[2,2] = Green
[2,3] = Violet
36. Given the code fragment:
var list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 1
UnaryOperator<Integer> u = i -> i * 2; // 2
list.replaceAll(u); // 3
Which can replace line 2?
A) UnaryOperator<Integer> u = (int i) -> i * 2;
B) UnaryOperator<Integer> u = (var i) -> (i * 2);
C) UnaryOperator<Integer> u = var i -> { return i * 2; };
D) UnaryOperator<Integer> u = i -> { return i * 2; );
답: B
풀이:
UnaryOperator는 입력과 출력이 동일한 형식의 연산을 수행하는 함수형 인터페이스입니다. 즉, 하나의 인수를 받아서 그것을 다른 값으로 변환한다
람다식의 형식: i -> i * 2
i * 2를 반환함
A) 형식 지정이 불필요하고 람다식의 매개변수에 타입을 명시할 필요가 없음
B) var를 사용하여 변수를 선언하는 것이 가능
C) var를 사용하여 변수를 선언할 때는 반드시 람다식의 매개변수에만 사용해야 함
D) 닫는 괄호가 잘못 사용, 즉 ) 말고 }가 되어야 함
37. Given:
for (var i = 0; i < 10; i++) {
switch (i % 5) {
case 2:
i *= i;
break;
case 3:
i++;
break;
case 1:
case 4:
i++;
continue;
default:
break;
}
System.out.println(i + " ");
i++;
}
What is the result?
A) nothing
B) 0
C) 10
D) 0
4
9
답: D
풀이:
변수 i를 0부터 9까지 증가시키며 switch 문을 사용하여 각 경우에 따라 i의 값을 변경
1) case 2:에서는 i의 제곱값으로 변경(i*i)
2) case 3:에서는 1 증가
3) case 1: 및 case 4:에서는 각각 1 증가하고 continue 문을 만남 -> switch 문의 나머지 case를 실행하지 않고 다음 반복으로 넘어감
따라서 각 case에 따라 i의 값이 변경되고, 각 case가 실행될 때마다 i가 증가하고 0 4 9가 출력됨
public class Test {
public static void main(String[] args) {
for (var i = 0; i < 10; i++) {
switch (i % 5) {
case 2:
i *= i;
break;
case 3:
i++;
break;
case 1:
case 4:
i++;
continue;
default:
break;
}
System.out.println(i + " ");
i++;
}
}
}
0
4
9
38. Given:
public class Main {
public static void main(String[] args) {
List<Player> players = List.of(new Player("Scott", 115), new Player("John", 70), new Player("Jelly", 105));
double average = // line 1
System.out.println("The average is: " + average);
}
}
class Player {
public String name;
public int score;
public Player(String name, int score) {
this.name = name;
this.score = score;
}
}
You want to calculate average of the Player’s score. Which statement inserted on line 1 will accomplish this?
A) players.stream().average().orElse(0.0);
B) players.stream().mapToInt(a -> a.score).average().orElse(0.0);
C) players.stream().mapToDouble(a -> a.score).average();
D) players.stream().map(a -> a.score).average();
답: B
풀이:
Player 객체의 점수(score)의 평균을 계산해야 하고 stream 을 사용하여 Player 객체의 score를 추출한 후에 평균을 계산해야 함
A) Player 객체가 아닌 double 값을 직접 스트림으로 생성하고 있기 때문에 답 아님
B) Player 객체를 int 값으로 매핑하고, 이를 이용하여 평균을 계산, 정답
C) double 스트림을 생성하고 평균을 계산하지만, orElse 메서드를 사용하여 기본값이 없다. 이 경우 평균이 없을 때 기본값이 필요한데 없기 때문에 답 아님
D) int 스트림을 생성하고 평균을 계산하지만, orElse 메서드를 사용하여 기본값이 없음, 평균이 없을 때 기본값이 필요한데 없으니까 오답
코드를 수정하면
double average = players.stream()
.mapToInt(a -> a.score)
.average()
.orElse(0.0);
39. Given:
public class Foo {
private final ReentrantLock lock = new ReentrantLock();
private State state;
public void foo() throws Exception {
try {
lock.lock();
state.mutate();
} finally {
lock.unlock();
}
}
}
What is required to make the Foo class thread safe? (Foo 클래스 스레드를 안전하게 만들려면 무엇이 필요합니까?)
A) No change is required.
B) Make the declaration of lock static. (lock 선언을 static으로 만듬)
C) Replace the lock constructor call with new ReentrantLock(true); (lock constructor 호출을 새 Reentrant Lock(참)으로 교체)
D) Move the declaration of lock inside the foo method.(lock 선언문을 foo method 안으로 이동)
답: A
풀이:
foo 메서드가 lock을 사용하여 임계 영역을 보호 중
lock은 인스턴스 변수로 선언되어 있기 때문에 각각의 Foo 객체 인스턴스에 대해 별도의 lock이 생성됨 -> 여러 스레드에서 동시에 foo 메서드를 호출할 때 각 스레드가 서로 다른 lock을 사용하게 될 수 있음
-> 올바른 동기화를 위해서는 모든 Foo 객체 인스턴스가 같은 lock을 공유해야 하고 B, D 는 답이 아님
C는 데드락을 유발할 수 있으므로 올바른 해결책이 아닙니다.
(데드락(Deadlock: 멀티스레드나 멀티프로세스 환경에서 발생할 수 있는 상황으로, 두 개 이상의 작업이 서로 상대방의 작업이 끝나기만을 기다리고 있어서 모두가 진행하지 못하는 상태)
결론은 A, 변경이 필요하지 않습니다. 현재 코드에서는 이미 Foo 클래스가 적절하게 스레드 안전하게 작성되어 있다
40. Given:
public class Tester {
private int x;
private static int y;
public static void main(String[] args) {
Tester t1 = new Tester();
t1.x = 2;
Tester.y = 3;
Tester t2 = new Tester();
t2.x = 4;
t2.y = 5;
System.out.println(t1.x + "," + t1.y);
System.out.println(t2.x + "," + Tester.y);
System.out.println(t2.x + "," + t2.y);
}
}
What is the result?
A) 2,3
4,3
4,5
B) 2,3
4,5
4,5
C) 2,5
4,5
4,5
D) 2,3
4,5
4,3
답: C
풀이:
t1.x: t1 객체의 인스턴스 변수이므로 2
t1.y: 정적 변수, Tester.y를 통해 접근되고 변경되었으므로 5
t2.x: t2 객체의 인스턴스 변수이므로 4
t2.y: Tester.y는 정적 변수이며 이전에 5
t2.x: t2 객체의 인스턴스 변수이므로 4
t2.y: t2 객체의 인스턴스 변수이지만 이전에 Tester.y를 통해 5가 됨
2,5
4,5
4,5
41. Given:
class Employee {
String office;
}
and the code fragment:
public class HRApp {
var employee = new ArrayList<Employee>(); // 4
public var display() { // 5
var employee = new Employee(); // 6
var offices = new ArrayList<>(); // 7
offices.add("Chicago");
offices.add("Bangalore");
for (var office : offices) { // 10
System.out.println("Employee Location " + office);
}
}
}
Which two lines cause compilation error? (Choose two.)
A) line 7
B) line 10
C) line 6
D) line 5
E) line 4
답: D, E
풀이:
1) 메서드 내부의 반환 타입을 var로 선언하고 있는 것은 틀림
Java에서는 메서드의 반환 타입을 명시적으로 지정해야 함 -> display 메서드의 반환 타입을 지정, D line 5 틀림
2) ArrayList의 제네릭 타입이 생략되어 있음 -> Java에서는 제네릭 타입을 명시해 주어야 함 -> ArrayList 객체를 생성할 때 제네릭 타입을 명시적으로 지정, E line 4 틀림
42. Assuming the Widget class has a getPrice method, this code does not compile:
List widgets = List.of(new Widget("Basic Widget", 25.00), // line 1
new Widget("Enhanced Widget", 32.99),
new Widget("Luxary Edition Widget", 59.99));
Stream widgetStream = widgets.stream(); // line 4
idgetStream.filter(a -> a.getPrice() > 35) // line 5
.forEach(System.out::println);
Which two statements, independently, would allow this code to compile? (Choose two.)
(이 코드를 컴파일하는 데 독립적으로 허용되는 두 문장은 무엇입니까?)
A) Replace line 5 with widgetStream.filter(a -> ((Widget)a).getPrice() > 35)
B) Replace line 5 with widgetStream.filter((Widget a) -> a.getPrice() > 35)
C) Replace line 4 with Stream<Widget> widgetStream = widgets.stream();
D) Replace line 1 with List<Widget> widgetStream = widgets.stream();
답: A, C
풀이:
1) 람다 표현식에서 형변환을 시도
-> (Widget)a와 같이 형변환을 시도하여 Widget 객체로 캐스팅: 이 방법은 람다 표현식 내에서 변수 a를 Widget 타입으로 캐스팅하여 getPrice() 메서드를 호출: A 정답
2) 변수 widgetStream을 명시적으로 Stream<Widget> 타입으로 지정
-> widgetStream이 Widget 객체를 포함하는 Stream으로 정의되어 있으므로 getPrice() 메서드를 호출 가능, C 정답
46. Which two var declarations are correct? (Choose two.)
A) var names = new ArrayList<>();
B) var_=100;
C) var var = "Hello";
D) var y = null;
E) var a;
답: A, C
풀이:
A) ArrayList 객체를 생성, 제네릭 타입을 명시적으로 지정하지 않고 var 키워드를 사용하여 변수를 선언, 틀린게 없음
C) 문자열 "Hello"를 포함하는 변수를 선언, var 키워드는 우변의 표현식의 타입을 추론하여 변수를 선언하고 "Hello"는 문자열이므로 문제 없이 작동함
B) 변수 이름에 등호(=)를 포함(Java에서는 변수 이름에 등호를 사용할 수 없음)
D) null을 포함하는 변수를 선언(var 키워드를 사용하여 변수를 선언할 때에는 초기값을 통해 변수의 타입이 추론되어야하는데 null은 어떤 타입도 가지지 않은 상태를 나타내기 때문에 var와 함께 사용될 수 없음
E) 변수 a를 선언하고 있지만 초기값이 없음(Java에서는 var 키워드를 사용하여 변수를 선언할 때 초기값을 통해 변수의 타입을 추론해야 함)즉, 초기값이 없는 경우에는 컴파일러가 타입을 추론할 수 없으므로 오답
48. Given:
StringBuilder sb = new StringBuilder("ABCD");
Which would cause sb to be OBCD?
A) sb.replace(sb.indexOf("A"), sb.indexOf("C"), "O");
B) sb.replace(sb.indexOf("A"), sb.indexOf("B"), "O");
C) sb.replace(sb.indexOf("A"), sb.indexOf("A"), "O");
D) sb.replace(sb.indexOf("B"), sb.indexOf("B"), "O");
답: B
풀이:
StringBuilder 객체 sb를 "ABCD"로 초기화함
B) indexOf 메서드를 사용하여 문자열 "A"와 "B"의 인덱스를 찾은 후, 해당 범위의 문자열을 "O"로 대체 -> "OBCD"됨
A) "A"와 "C" 사이의 범위에는 "B"가 있기 때문에 대체할 수 없고 replace 메서드는 시작 인덱스부터 종료 인덱스까지를 대체하는데, "C"의 인덱스는 "C"의 바로 뒤이므로 범위가 정확하지 않댜
C)"A"와 "A" 사이의 범위는 존재하지 않으므로 아무런 변경이 일어나지 않음
D) "B"와 "B" 사이의 범위는 존재하지 않음 -> 아무것도 안바뀜
50. Given:
public class Main {
public static void main(String[] args) {
int i = 1;
for (String arg : args) {
System.out.println((i++) + ") " + arg);
}
}
}
executed with this command:
java Main one two three
What is the output of this class?
A) The compilation fails.
B) 1) one
2) two
3) three
C) A java.lang.ArrayIndexOutOfBoundsException is thrown.
D) 1) one
E) nothing
답: B
풀이:
1) java Main one two three 명령어를 실행: args 배열에 "one", "two", "three"라는 세 개의 문자열이 전달됨
2) for 문에서 args 배열의 각 요소를 반복하면서 해당 요소를 출력
3) 반복문 내에서는 각 요소 앞에 1씩 증가하는 숫자를 붙여서 출력
결과는
- one
- two
- three
가 나옴