[Java]Day03 - 연산자
2021-01-20 # Java

JAVA NEWS

오늘은 들어가기에 앞서 스터디에서 다룬 내용을 살펴보겠다.

Maven Dependencies Pop Quiz

정답은 28.2version이다.
dependency는 동일한 groupId일 경우 가장 마지막에 있는 버젼이 위에 있는 것을 오버라이딩한다고 생각하면 좋다.

정답은 28.2version이다.
dependency는 가장 POM파일에 명확하게 정의된 것으로 정의한다.
truth의 27.0.1version은 28.2v보다 depth가 깊다고 생각하면 된다.

정답은 27.0version이다.
dependencyManagement(이하 DM)는 추이적(transitive)으로 정의된 dependency보다는 가깝다.

정답은 27.0version이다.
DM은 dependency보다는 조금 멀다. DM은 어떤버젼을 쓸지 명시해놓은 것이다. 만약 guava 28.2-jre를 제거할 경우 27.0 version이 적용이 될것이다.

결론적으로는 dependency > DM > 추이적정의 순서대로 정의가 된다고 생각하면 된다.

Review Day02

Q1. Java에 unsigned이 존재하는가?

정답은 Yes이다. 정확히는 java8 이전까지는 unsigned형이 존재하지 않는다. C에서는 unsigned int를 사용하면 됐지만 java에는 이가 존재하지 않는다. int unsigned = Integer.parseUnsignedInt("21억이상")이라고 할 시 Integer.toUnsignedString(unsigned)로 출력을 하는것은 가능하다. 하지만 이는 좋은 방법이 아니므로 그냥 BigInteger를 사용하자! (L을 넣어야한다.)

Q2. int number = 1_000;이 정의가 되는가?

정답은 Yes이다. 숫자를 표현할 때 가독성이 좋게 하기위해 언더바(_)를 통해 정의할 수 있다.

또 하나의 중요한 점은 Static 변수와 Instance변수의 라이프사이클이다.
Static의 라이프사이클은 클래스가 로딩된 시점이지만 Instance변수의 라이프사이클은 클래스가 생성된 시점이므로 instance가 생성되기 이전에는 instance변수가 존재하지 않는다 따라서 static은 instance 변수를 참조할 수 없다. 이는 중요한 내용이므로 모르면 찾아보자
오늘의 리뷰는 짧게 하고 DAY03 시작해보겠다.

Day03. 연산자

산술 연산자, 비트 연산자, 관계 연산자, 논리 연산자, assignment(=) operator, 3항 연산자 그리고 연산자 우선 순위는 넘어가보도록 할 것이다. 시간이 부족해서 다른 것들에 더 집중해보도록 하겠다. 이에 대해서는 이 블로그에서 깔끔히 다뤘으므로 참고하면 좋겠다.

instanceof 연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof 연산자를 사용한다.
주로 조건문에서 사용되며, 왼쪽에는 참조변수를 오른쪽에는 타입(class name)을 쓴다. 그리고 연산의 결과는 boolean형인 truefalse를 반환한다.

instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

1
2
3
4
5
6
7
8
9
10
void doWork(Car c){
if(c instanceof FireEngine){
FireEngine fe = (FireEngine)c;
fe.water();
}
else if(c instance of Ambulance){
Ambulance a = (Ambulance)c;
a.siren();
}
}

위의 코드는 Car타입의 참조변수인 c를 매개변수로 하는 메서드이다. 이 메서드가 호출될 때, 매개변수로 Car클래스 혹은 그 자손 클래스의 인스턴스를 넘겨받겠지만 메서드 내에서는 정확히 어떤 인스턴스인지 알 수가 없다. 따라서, instanceof연산자를 이용해서 참조변수 c가 가리키고 있는 인스턴스의 타입을 체크하고 적절히 형변환을 한 다음에 작업을 해야한다.

위의 코드에서는 c라는 참조변수가 FireEngine인지 Ambulance인지 구분을 시킨 후 각각에 맞춰서 형변환을 이룬 후 메서드를 실행한다. 이는 정말 중요한 작업이다.

그리고 또한 중요한 것은 만약 c라는 참조변수가 FireEngine이라 해도 c instance of Car의 구문에서도 true를 반환한다는 점과 모든 클래스의 조상클래스인 Object의 인스턴스 이기도 하다는 것이다. 즉, 실제 인스턴스와 같은 타입의 instanceof연산 이외에 조상타입의 instanceof연산에도 true를 결과로 얻으며, instanceof연산의 결과가 true라는 것은 검사한 타입으로의 형변환을 해도 문제가 없다는 뜻이다.

화살표(->) 연산자

자바가 등장한 이후로 두 번의 큰 변화가 있었는데, 한번은 5버젼의 지네릭스와 8버젼의 람다식이다. ->연산자는 이 람다식이다.
람다식의 도입으로 자바는 객체지향언어임과 동시에 함수형 언어가 되었다.

람다식이란?

람다식에 대해 간단히 먼저 설명하자면, 메서드를 하나의 ‘식(Expression)’으로 표현한 것을 말한다. 람다식은 함수를 간략하면서도 명확한 식으로 표현할 수 있게 해준다.
메서드를 람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로, 람다식을 ‘Anonymous funcion’이라고도 한다.

아래와 같이 선언된 매개변수가 하나뿐인 경우에는 괄호()를 생략할 수 있다. 단, 매개변수의 타입이 있으면 괄호()를 생략할 수 없다.

1
2
(a) -> a*a // OK
(int a) -> a*a // Error

마찬가지로 괄호{}안의 문장이 하나일 때는 괄호{}를 생략할 수 있다. 이 때 문장의 끝에 ‘;’를 붙이지 않아야 한다는 것에 주의하자.

1
(String name, int i) -> System.out.println(name+"="+i)

그러나 괄호{}안의 문장이 return문일 경우에는 괄호를{}생략할 수 없다.

람다식에 대해서는 중요한 내용이므로 나아아중에 다시 제대로 다뤄보겠다.

Optional

Optional도 정말 중요한 내용이지만 우선 지금 다루기엔 너무 내용이 많으므로 간략히 다뤄보겠다.
Optional class는 지네릭(generic)클래스(벌써 범위를 넘어갔다.)로써 ‘T타입의 객체’를 감싸는 래퍼(wrapper) 클래스이다. 그래서 Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다.

1
2
3
public final class Optional<T>{
private final T value; // T타입의 참조변수
}

최종 연산의 결과를 그냥 반환하는 것이 아니라 Optional객체에 담아서 반환하는 것이다.이처럼 객체에 담아서 반환을 하면, 반환된 결과가 null인지 매번 if문으로 체크하는 대신 Optional에 정의된 메서드를 통해서 간단히 처리할 수 있다.
즉, Null체크를 위한 if문 없이도 NullPointerException이 발생하지 않는 안전한 코드를 작성하는 것이 가능해진 것이다.
자세한 내용은 이 블로그에서 참고하면 좋을 것 같다.

결론

이번 연산자단원에서는 내가 크게 다룬 것은 없다. ->연산자는 뒤에 람다식을 다루며 자세히 다뤄야할 내용이며 Optional도 그러하다. 진도를 빨리 나가기 위해 연산자에 대한 내용은 위에 참조된 링크들을 보면 좋을 것이다.

Reference

  • 자바의 정석